rpc:测试std::mutex 和 futex封装的FastPthreadMutex以及butex

FastPthreadMutex

class FastPthreadMutex {
public:
    FastPthreadMutex() : _futex(0) {}
    ~FastPthreadMutex() {}
    void lock();
    void unlock();
    bool try_lock();
private:
    DISALLOW_COPY_AND_ASSIGN(FastPthreadMutex);
    int lock_contended();
    unsigned _futex;
};
#else
typedef butil::Mutex FastPthreadMutex;
#endif
}

FastPthreadMutex在是对futex的封装,在保证互斥的条件下使得线程间切换次数更少,以提高系统性能。

与mutex 在lock unlock的耗时测试

首先测试单线程 lock unlock的基准测试:

#include "bthread/mutex.h"
#include <chrono>
#include <thread>
#include <iostream>
#include <cassert>
#include <vector>

// 对比FastPthreadMutex 和 std::mutex 的性能差距
bthread::internal::FastPthreadMutex waiter_lock{};
std::mutex std_mutex;
constexpr static int N = 10000000;
int cnt = 0;

void test1() {
    for(int i = 0; i < N; i++) {
        std_mutex.lock();
        ++cnt;
        std_mutex.unlock();
    }
}
void test2() {
    for(int i = 0; i < N; i++) {
        waiter_lock.lock();
        ++cnt;
        waiter_lock.unlock();
    }
}
int main() {
    // 统计耗时
    auto start = std::chrono::steady_clock::now();
    int n = 1;
    std::vector<std::thread> nums(n);
    for(int i = 0; i < n; i++) {
        nums[i] = std::thread(test1);
    }
    for(int i = 0; i < n; i++) {
        nums[i].join();
    }
    auto end = std::chrono::steady_clock::now();

    assert(cnt == n * N);
    std::cout << "std::mutex cost: " << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() << "ms" << std::endl;


    cnt = 0;
    start = std::chrono::steady_clock::now();
    
    for(int i = 0; i < n; i++) {
        nums[i] = std::thread(test2);
    }
    for(int i = 0; i < n; i++) {
        nums[i].join();
    }
    end = std::chrono::steady_clock::now();

    assert(cnt == n * N);
    std::cout << "FastPthreadMutex cost: " << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() << "ms" << std::endl;

}


在这里插入图片描述

当n = 1, 可以看到,在完全没有竞争的场景下,FastPthreadMutex的性能要比mutex强上一些

当n = 2时:
在这里插入图片描述

两个线程来回lock unlock的场景下,其性能表现波动较大,完全取决于OS当时的调度策略。

当n=4时:

在这里插入图片描述
FastPthreadMutex的表现明显强过std::mutex,因为FastPthreadMutex陷入内核的次数更少。

补充

#include <chrono>
#include <thread>
#include <iostream>
#include <cassert>
#include <typeinfo>
#include <vector>
#include <bthread/bthread.h>  
#include <bthread/butex.h>  

// 对比FastPthreadMutex 和 std::mutex 的性能差距
bthread::internal::FastPthreadMutex waiter_lock{};

// butex
bthread::Mutex bthread_mutex{};

// mutex
std::mutex std_mutex;


constexpr static int N = 10000000;
int n = 2;
int cnt = 0;

void test1() {
    for(int i = 0; i < N; i++) {
        std_mutex.lock();
        ++cnt;
        std_mutex.unlock();
    }
}
void test2() {
    for(int i = 0; i < N; i++) {
        waiter_lock.lock();
        ++cnt;
        waiter_lock.unlock();
    }
}

void* test3(void*) {
    for(int i = 0; i < N; i++) {
        bthread_mutex.lock();
        ++cnt;
        bthread_mutex.unlock();
    }
    return nullptr;
}
int main() {
    logging::SetMinLogLevel(1);
    // 统计耗时
    auto start = std::chrono::steady_clock::now();

    std::vector<std::thread> nums(n);
    for(int i = 0; i < n; i++) {
        nums[i] = std::thread(test1);
    }
    for(int i = 0; i < n; i++) {
        nums[i].join();
    }
    auto end = std::chrono::steady_clock::now();

    assert(cnt == n * N);
    std::cout << "std::mutex cost: " << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() << "ms" << std::endl;


    cnt = 0;
    start = std::chrono::steady_clock::now();
    
    for(int i = 0; i < n; i++) {
        nums[i] = std::thread(test2);
    }
    for(int i = 0; i < n; i++) {
        nums[i].join();
    }
    end = std::chrono::steady_clock::now();

    assert(cnt == n * N);
    std::cout << "FastPthreadMutex cost: " << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() << "ms" << std::endl;

    cnt = 0;
    std::vector<bthread_t> nums2(n);
    start = std::chrono::steady_clock::now();
    for(int i = 0; i < n; i++) {
        if (bthread_start_urgent(&nums2[i], NULL, test3, NULL) != 0) {
            perror("bthread_start_urgent");
            return 1;
        }
    }

    for(int i = 0; i < n; i++) {
        bthread_join(nums2[i], NULL);
    }
    end = std::chrono::steady_clock::now();

    assert(cnt == n * N);
    std::cout << "butex cost: " << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() << "ms" << std::endl;


    return 0;
    
}


增加了对butex的测试,首先是单thread,无竞争的情况:

在这里插入图片描述

butex 都是略好于上面两个。

然后是n=2的情况:

在这里插入图片描述

可以看到,在这种竞争情况下,mutex和futex都会因为竞争的不确定定到导致耗时的巨大波动,而butex则保持稳定,且维护互斥所需的耗时非常少。

n = 4时:

在这里插入图片描述

butex 大约开销是mutex的一半。

相关推荐

  1. Vue组件原理好处

    2024-04-20 21:26:06       55 阅读
  2. 苹果免签优势安全风险

    2024-04-20 21:26:06       26 阅读
  3. Android 工具类

    2024-04-20 21:26:06       37 阅读
  4. charts使用 vue2

    2024-04-20 21:26:06       37 阅读
  5. 根据ElasticsearchRestTemplate工具类

    2024-04-20 21:26:06       32 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-04-20 21:26:06       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-04-20 21:26:06       100 阅读
  3. 在Django里面运行非项目文件

    2024-04-20 21:26:06       82 阅读
  4. Python语言-面向对象

    2024-04-20 21:26:06       91 阅读

热门阅读

  1. 【YOLO改进】主干SE模块(基于MMYOLO)

    2024-04-20 21:26:06       36 阅读
  2. 解决AGP升级到8.0后编译报错kaptGenerateStubsDebugKotlin

    2024-04-20 21:26:06       42 阅读
  3. 计算机网络

    2024-04-20 21:26:06       23 阅读
  4. 【eladmin项目拆解】登录功能实现源码

    2024-04-20 21:26:06       24 阅读
  5. 怎么用3ds MAX制作蜂窝状模型?

    2024-04-20 21:26:06       30 阅读
  6. SiteServer 学习笔记 Day08 内容补充

    2024-04-20 21:26:06       31 阅读
  7. 面了百度自驾算法岗(实习),这次我要上岸了

    2024-04-20 21:26:06       35 阅读
  8. Jmeter redis连接测试

    2024-04-20 21:26:06       37 阅读