为什么需要测试 rust 的锁性能?

       IM 中核心组件有 RPC,在开发完 java, flutter,  TS 客户端时,都完成了相应的 RPC client 客户端。但是在开发 rust wasm 客户端时,开发 rust rpc client 特别的复杂,需要使用宏完成,宏比较复杂,前期就采用事件机制完成 rust 的客户端,代码过于复杂,维护太不方便了,就又开始学习 rust 的宏。初步完成了数据发送和数据接受宏的实现,随后就需要设计业务线程池了,设计的思想是: 1,线程 + 锁模式。 2,线程 + mpsc 模式。此时就需要了解下 rust 的锁性能。

性能测试的设计

    进行一次非常简单测试, 开启 5 个线程,每个线程循环 200 次对数字进行加 1,记录所用时间以及数字叠加后最后值,确认并发操作正确,没有丢失值

测试方法:

    一, 使用 Mutex 锁,五个线程循环 200 次对数字加 1 操作。

     代码如下:

pub fn mutex_test() {
    let num_mutex = Arc::new(Mutex::new(0));
    let mut list = Vec::new();

    let start = Instant::now();

    for _ in 0..5 {
        let num_mutex = num_mutex.clone();
        let thread = thread::spawn(move || {
            for _ in 0..200 {
                let mut num = num_mutex.lock().unwrap();
                *num += 1;
            }
        });
        list.push(thread);
    }

    for thread in list {
        thread.join().unwrap();
    }

    let result = *num_mutex.lock().unwrap();
    let duration = start.elapsed();

    println!("mutex_test执行时间: {:?}, result: {}", duration, result);
}

 二, 使用 mpsc 模式

pub fn mpsc_test() {
    let (sender, receiver) = mpsc::channel();

    let start = Instant::now();

    for _ in 0..4 {
        let sender_clone = sender.clone();
        let thread = thread::spawn(move || {
            for _ in 0..250 {
                sender_clone.send(1).unwrap();
            }
        });
    }

    drop(sender);
    let mut result = 0;
    for rr in receiver.iter() {
        result += 1;
    }

    let duration = start.elapsed();

    eprintln!("mpsc_test执行时间: {:?}, total: {} ", duration, result);
}

 三,使用 AtomicIsize 进行测试(按照 Java 性能,这个性能应该最好) 

pub fn atomic_isize_test() {
    let atomic_size = Arc::new(AtomicIsize::new(0));
    let mut list = Vec::new();

    let start = Instant::now();

    for _ in 0..5 {
        let num_mutex = atomic_size.clone();
        let thread = thread::spawn(move || {
            for _ in 0..200 {
                num_mutex.fetch_add(1, Ordering::Relaxed);
            }
        });
        list.push(thread);
    }

    for thread in list {
        thread.join().unwrap();
    }

    let result = atomic_size.load(Ordering::Relaxed);
    let duration = start.elapsed();


    eprintln!("atomic_isize_test执行时间: {:?}, total: {}", duration, result);
}

测试结果 (release 运行的结果)

  mutex_test 执行时间: 469.2µs, result: 1000
  atomic_isize_test 执行时间: 374µs, total: 1000
  mpsc_test 执行时间: 249.7µs, total: 1000

性能最好的是 mpsc(最小锁机制吧)。 

这个结果还是挺意外的,和最初的想法(AtomicIsize 性能最好)相差很大。

测试完了 rust 的锁性能,就想要不也对 java 的锁性能进行测试,测试场景如下:

1, 线程池模式。 2,AtomicInteger。 3,生产和消费模式。

测试结果是 AtomicInteger 性能最好。但是比 rust 性能差 3-8 倍。为了提高性能,找了个 mpsc 的无锁组件 jctools。发现性能还次于 AtomicInteger, 比其它两个性能强点。

总结:

    rust 的 mpsc 性能非常的好,可以优先使用。

更多推荐