gpt4 book ai didi

rust - 为什么多个线程在持有 Mutex 时使用太多内存

转载 作者:行者123 更新时间:2023-11-29 07:55:08 24 4
gpt4 key购买 nike

下面的代码在单线程中使用约 150MB,但在 100 个线程中使用几 GB:

use std::sync::{Arc, Mutex};
use std::thread;

fn main() {
let f = Arc::new(Mutex::new(Foo::new("hello")));

let mut threads = vec![];
for i in 0..100 {
let f = f.clone();
let t = thread::spawn(move || loop {
let mut locked = f.lock().unwrap();
*locked = Foo::new("hello");
drop(locked);
println!("{} reloaded", i);
thread::yield_now();
});
threads.push(t);
}

threads.into_iter().for_each(|h| h.join().unwrap());
}

pub struct Foo {
_data: Vec<String>,
}

impl Foo {
fn new(s: &str) -> Foo {
Foo {
_data: vec![s.to_owned(); 1024 * 1024],
}
}
}

持有 LockGuard 时,线程应该具有独占访问权限。因此,新的 Foo 应该被分配,旧的值应该在那个时候被丢弃。因此,从多个线程调用时使用这么多内存对我来说没有任何意义。

谁能解释一下为什么这段代码占用了这么多内存?

即使有 1000 个线程,Java 中的类似代码也能保持约 200mb 的内存。

import java.util.ArrayList;
import java.util.List;

public class Foo {
private List<String> data;

public static void main(String[] args) {
Foo f = new Foo();
for (int i = 0; i < 1000; i++) {
int n = i;
new Thread(() -> {
while (true) {
f.update();
System.gc();
System.out.println(n + " updated");
}
}).start();
}
}

public synchronized void update() {
data = new ArrayList<>(1024 * 1024);
for (int i = 0; i < 1024 * 1024; i++) {
data.add(new String("hello"));
}
}
}

最佳答案

所以问题出在大量的 glibc 的 malloc arenas 上,每个竞技场都有预分配内存的缓存。检查它的简单方法是使用 MALLOC_ARENA_MAX=2 运行二进制文件,但最终解决方案取决于使用模式,有很多变量可以调整 glibc 的分配器:http://man7.org/linux/man-pages/man3/mallopt.3.html .

Java虚拟机其实也受malloc的allocator的影响。根据我的经验,有时配置 arena 的数量是合适的,以防止 docker 中的 jvm 使用大量内存。

关于rust - 为什么多个线程在持有 Mutex 时使用太多内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58110081/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com