Last active
May 12, 2023 07:46
-
-
Save maczniak/4262b30ad3a64f7802d5dd9579ff3ee5 to your computer and use it in GitHub Desktop.
volatile global variable test in Rust (please use ArcSwap instead)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[package] | |
name = "memory-leak-test" | |
version = "0.0.1" | |
edition = "2021" | |
[dependencies] | |
actix-rt = "2.8" | |
actix-web = "4" | |
env_logger = "0.10" | |
log = "0.4" | |
lazy_static = "1.4" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use std::sync::atomic::{AtomicPtr, Ordering}; | |
use std::ptr::null_mut; | |
use actix_rt::time; | |
use core::time::Duration; | |
use lazy_static::lazy_static; | |
#[derive(Debug, Clone)] | |
struct Dummy { | |
buffer: Vec<u32>, | |
} | |
impl Drop for Dummy { | |
fn drop(&mut self) { | |
log::info!("drop called"); | |
} | |
} | |
lazy_static! { | |
static ref GLOBAL_PTR : AtomicPtr<Dummy> = AtomicPtr::new(null_mut::<Dummy>()); | |
} | |
#[actix_web::main(flavor = "current_thread")] | |
async fn main() -> std::io::Result<()> { | |
env_logger::init_from_env(env_logger::Env::new().default_filter_or("info")); | |
let mut dummy = Box::new(Dummy { buffer: Vec::with_capacity(10_000_000) }); | |
for _ in 0..10_000_000 { | |
dummy.buffer.push(1217); | |
} | |
log::info!("initial value {}", dummy.buffer[555]); | |
GLOBAL_PTR.store(Box::into_raw(dummy), Ordering::Relaxed); | |
log::info!("global_ptr address {:?}", std::ptr::addr_of!(GLOBAL_PTR)); | |
unsafe { | |
log::info!("first fetch {}", (*GLOBAL_PTR.load(Ordering::Relaxed)).buffer[555]); | |
} | |
let mut handles = Vec::new(); | |
for i in 0..10 { | |
let ii = i; | |
let handle = actix_rt::spawn(async move { | |
let mut interval = time::interval(Duration::from_secs(10)); | |
loop { | |
interval.tick().await; | |
unsafe { | |
log::info!("fetch in thread #{} {:?}", ii, (*GLOBAL_PTR.load(Ordering::Acquire)).buffer[555]); | |
} | |
let mut dummy = Box::new(Dummy { buffer: Vec::with_capacity(10_000_000) }); | |
for _ in 0..10_000_000 { | |
dummy.buffer.push(ii); | |
} | |
let new_ptr : &'static mut Dummy = Box::leak(dummy); | |
let old_ptr = GLOBAL_PTR.swap(new_ptr, Ordering::AcqRel); | |
unsafe { | |
drop(Box::from_raw(old_ptr)); | |
} | |
} | |
}); | |
handles.push(handle); | |
} | |
log::info!("out of loop"); | |
for handle in handles { | |
let _ = handle.await; | |
} | |
Ok(()) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment