God一直致力于研究高并发服务端的开发,这次要优化的是libGod库中的线程本地存储变量,线程本地存储变量访问非常频繁,优化后库的性能应该会提高不少。已知的线程本地存储方法有boost中的thread_specific_ptr类,gcc中的__thread关键字,pthread中的pthread_getspecific函数。这次测试这3中本地存储以及普通变量之间的性能差别,代码如下:
- #include <iostream>
- #include <stdio.h>
- #include <pthread.h>
- #include <boost/thread/thread.hpp>
- #include <boost/thread/tss.hpp>
- using namespace std;
- class C {
- public:
- C(int a) {
- m_a = a;
- printf("C() %d\n", m_a);
- }
- ~C() {
- printf("~C() %d\n", m_a);
- }
- private:
- int m_a;
- };
- #define TM 3
- #if TM == 1
- boost::thread_specific_ptr<C> pc;
- const char *testType = "boost";
- #elif TM == 2
- __thread C *pc;
- const char *testType = "__thread";
- #elif TM == 3
- pthread_key_t pc;
- const char *testType = "pthread";
- #else
- C *pc;
- const char *testType = "normal";
- #endif
- void boostthreadFunc() {
- #if TM == 1
- pc.reset(new C(10));
- #elif TM == 2
- pc = new C(20);
- #elif TM == 3
- if (pthread_key_create(&pc, NULL)) {
- cout << "pthread_key_create" << endl;
- return;
- }
- if (pthread_setspecific(pc, new C(30))) {
- cout << "pthread_setspecific" << endl;
- return;
- }
- #else
- pc = new C(20);
- #endif
- int switches = 5000000;
- int i = switches;
- struct timeval tm_start, tm_end;
- gettimeofday(&tm_start, NULL);
- while (i--) {
- #if TM == 1
- C *c1 = pc.get();
- C *c2 = pc.get();
- C *c3 = pc.get();
- C *c4 = pc.get();
- C *c5 = pc.get();
- C *c6 = pc.get();
- C *c7 = pc.get();
- C *c8 = pc.get();
- C *c9 = pc.get();
- C *c10 = pc.get();
- C *c11 = pc.get();
- C *c12 = pc.get();
- C *c13 = pc.get();
- C *c14 = pc.get();
- C *c15 = pc.get();
- C *c16 = pc.get();
- C *c17 = pc.get();
- C *c18 = pc.get();
- C *c19 = pc.get();
- C *c20 = pc.get();
- C *c21 = pc.get();
- C *c22 = pc.get();
- C *c23 = pc.get();
- C *c24 = pc.get();
- C *c25 = pc.get();
- C *c26 = pc.get();
- C *c27 = pc.get();
- C *c28 = pc.get();
- C *c29 = pc.get();
- C *c30 = pc.get();
- C *c31 = pc.get();
- C *c32 = pc.get();
- C *c33 = pc.get();
- C *c34 = pc.get();
- C *c35 = pc.get();
- C *c36 = pc.get();
- C *c37 = pc.get();
- C *c38 = pc.get();
- C *c39 = pc.get();
- C *c40 = pc.get();
- #elif TM == 2
- C *c1 = pc;
- C *c2 = pc;
- C *c3 = pc;
- C *c4 = pc;
- C *c5 = pc;
- C *c6 = pc;
- C *c7 = pc;
- C *c8 = pc;
- C *c9 = pc;
- C *c10 = pc;
- C *c11 = pc;
- C *c12 = pc;
- C *c13 = pc;
- C *c14 = pc;
- C *c15 = pc;
- C *c16 = pc;
- C *c17 = pc;
- C *c18 = pc;
- C *c19 = pc;
- C *c20 = pc;
- C *c21 = pc;
- C *c22 = pc;
- C *c23 = pc;
- C *c24 = pc;
- C *c25 = pc;
- C *c26 = pc;
- C *c27 = pc;
- C *c28 = pc;
- C *c29 = pc;
- C *c30 = pc;
- C *c31 = pc;
- C *c32 = pc;
- C *c33 = pc;
- C *c34 = pc;
- C *c35 = pc;
- C *c36 = pc;
- C *c37 = pc;
- C *c38 = pc;
- C *c39 = pc;
- C *c40 = pc;
- #elif TM == 3
- C *c1 = (C *)pthread_getspecific(pc);
- C *c2 = (C *)pthread_getspecific(pc);
- C *c3 = (C *)pthread_getspecific(pc);
- C *c4 = (C *)pthread_getspecific(pc);
- C *c5 = (C *)pthread_getspecific(pc);
- C *c6 = (C *)pthread_getspecific(pc);
- C *c7 = (C *)pthread_getspecific(pc);
- C *c8 = (C *)pthread_getspecific(pc);
- C *c9 = (C *)pthread_getspecific(pc);
- C *c10 = (C *)pthread_getspecific(pc);
- C *c11 = (C *)pthread_getspecific(pc);
- C *c12 = (C *)pthread_getspecific(pc);
- C *c13 = (C *)pthread_getspecific(pc);
- C *c14 = (C *)pthread_getspecific(pc);
- C *c15 = (C *)pthread_getspecific(pc);
- C *c16 = (C *)pthread_getspecific(pc);
- C *c17 = (C *)pthread_getspecific(pc);
- C *c18 = (C *)pthread_getspecific(pc);
- C *c19 = (C *)pthread_getspecific(pc);
- C *c20 = (C *)pthread_getspecific(pc);
- C *c21 = (C *)pthread_getspecific(pc);
- C *c22 = (C *)pthread_getspecific(pc);
- C *c23 = (C *)pthread_getspecific(pc);
- C *c24 = (C *)pthread_getspecific(pc);
- C *c25 = (C *)pthread_getspecific(pc);
- C *c26 = (C *)pthread_getspecific(pc);
- C *c27 = (C *)pthread_getspecific(pc);
- C *c28 = (C *)pthread_getspecific(pc);
- C *c29 = (C *)pthread_getspecific(pc);
- C *c30 = (C *)pthread_getspecific(pc);
- C *c31 = (C *)pthread_getspecific(pc);
- C *c32 = (C *)pthread_getspecific(pc);
- C *c33 = (C *)pthread_getspecific(pc);
- C *c34 = (C *)pthread_getspecific(pc);
- C *c35 = (C *)pthread_getspecific(pc);
- C *c36 = (C *)pthread_getspecific(pc);
- C *c37 = (C *)pthread_getspecific(pc);
- C *c38 = (C *)pthread_getspecific(pc);
- C *c39 = (C *)pthread_getspecific(pc);
- C *c40 = (C *)pthread_getspecific(pc);
- #else
- C *c1 = pc;
- C *c2 = pc;
- C *c3 = pc;
- C *c4 = pc;
- C *c5 = pc;
- C *c6 = pc;
- C *c7 = pc;
- C *c8 = pc;
- C *c9 = pc;
- C *c10 = pc;
- C *c11 = pc;
- C *c12 = pc;
- C *c13 = pc;
- C *c14 = pc;
- C *c15 = pc;
- C *c16 = pc;
- C *c17 = pc;
- C *c18 = pc;
- C *c19 = pc;
- C *c20 = pc;
- C *c21 = pc;
- C *c22 = pc;
- C *c23 = pc;
- C *c24 = pc;
- C *c25 = pc;
- C *c26 = pc;
- C *c27 = pc;
- C *c28 = pc;
- C *c29 = pc;
- C *c30 = pc;
- C *c31 = pc;
- C *c32 = pc;
- C *c33 = pc;
- C *c34 = pc;
- C *c35 = pc;
- C *c36 = pc;
- C *c37 = pc;
- C *c38 = pc;
- C *c39 = pc;
- C *c40 = pc;
- #endif
- }
- gettimeofday(&tm_end, NULL);
- switches *= 40;
- long long ns = (tm_end.tv_sec - tm_start.tv_sec) * 1000LL * 1000LL * 1000LL +
- (tm_end.tv_usec - tm_start.tv_usec) * 1000LL;
- std::cout << "####Benchmark result#### " << testType << std::endl;
- std::cout << "Totol switches : " << switches << std::endl;
- std::cout << "Cost per switch(ns) : " << (double)ns/switches << std::endl;
- std::cout << "All cost switch(ns) : " << ns << std::endl;
- std::cout << "####Benchmark result####" << std::endl;
- }
- int main() {
- boost::thread bt(&boostthreadFunc);
- bt.join();
- printf("main exit..\n");
- return 0;
- }
详情请访问libgod官网..