c++和python之间性能差距的一点感悟

今天在了解到了strace这个工具,然后就想着用它来看看c++和python之间的性能差距,于是就写了一个简单的程序,然后用strace来查看系统调用的次数,结果发现c++的程序调用次数要远远少于python的程序。

用来测试的c++代码如下:

1
2
3
4
5
6
#include <iostream>

int main(int argc, const char** argv) {
std::cout << "hello world\n";
return 0;
}

用来测试的python代码如下:

1
print("hello world\n")

然后用strace来查看系统调用的次数:

1
2
strace -c ./a.out
strace -c python3 test.py

结果如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64

# c++
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
33.10 0.000239 4 58 53 openat
22.30 0.000161 7 22 mmap
9.70 0.000070 8 8 mprotect
5.96 0.000043 21 2 write
4.57 0.000033 33 1 prlimit64
4.29 0.000031 1 16 9 newfstatat
3.74 0.000027 5 5 close
3.19 0.000023 5 4 read
2.77 0.000020 20 1 munmap
2.63 0.000019 6 3 brk
1.94 0.000014 14 1 getrandom
1.39 0.000010 10 1 futex
1.11 0.000008 4 2 1 arch_prctl
1.11 0.000008 8 1 set_tid_address
1.11 0.000008 8 1 set_robust_list
1.11 0.000008 8 1 rseq
0.00 0.000000 0 4 pread64
0.00 0.000000 0 1 1 access
0.00 0.000000 0 1 execve
------ ----------- ----------- --------- --------- ----------------
100.00 0.000722 5 133 64 total

# python
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
34.89 0.002077 8 248 38 newfstatat
19.52 0.001162 15 77 read
12.78 0.000761 6 110 56 openat
10.13 0.000603 25 24 getdents64
7.91 0.000471 6 74 3 lseek
6.11 0.000364 6 57 close
4.87 0.000290 6 46 39 ioctl
0.79 0.000047 23 2 write
0.79 0.000047 1 28 mmap
0.57 0.000034 3 10 brk
0.42 0.000025 12 2 munmap
0.29 0.000017 3 5 3 readlink
0.17 0.000010 10 1 getuid
0.15 0.000009 0 66 rt_sigaction
0.15 0.000009 4 2 getcwd
0.15 0.000009 9 1 getgid
0.15 0.000009 9 1 geteuid
0.15 0.000009 9 1 getegid
0.00 0.000000 0 9 mprotect
0.00 0.000000 0 4 pread64
0.00 0.000000 0 1 1 access
0.00 0.000000 0 3 dup
0.00 0.000000 0 1 execve
0.00 0.000000 0 1 fcntl
0.00 0.000000 0 1 sysinfo
0.00 0.000000 0 2 1 arch_prctl
0.00 0.000000 0 1 futex
0.00 0.000000 0 1 set_tid_address
0.00 0.000000 0 1 set_robust_list
0.00 0.000000 0 1 prlimit64
0.00 0.000000 0 2 getrandom
0.00 0.000000 0 1 rseq
------ ----------- ----------- --------- --------- ----------------
100.00 0.005953 7 784 141 total

可以看到c++总共进行了133次系统调用,而python总共进行了784次系统调用,而且还可以看到c++系统调用的时间总共只有0.000722s,而python却花了0.005953秒,这也就说明了c++的性能要远远好于python。这也就是为什么很多大型的项目都是用c++来写的原因吧。

同时我还了解到可以通过ltrace来查看动态库函数调用的执行次数,所以我也尝试了一下,使用ltrace,
ltrace可以通过apt-get install ltrace直接安装,与strace的使用方法基本一致,测试结果如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112

# c++
% time seconds usecs/call calls function
------ ----------- ----------- --------- --------------------
68.45 0.001506 1506 1 _ZNSt8ios_base4InitC1Ev
21.73 0.000478 478 1 _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc
6.55 0.000144 144 1 _ZNSolsEPFRSoS_E
3.27 0.000072 72 1 __cxa_atexit
------ ----------- ----------- --------- --------------------
100.00 0.002200 4 total

# python
% time seconds usecs/call calls function
------ ----------- ----------- --------- --------------------
23.47 1.515623 65 22992 memcpy
12.93 0.834656 67 12446 strlen
11.38 0.735042 66 11101 memset
9.39 0.606523 65 9291 memcmp
7.88 0.508997 69 7289 pthread_mutex_lock
7.87 0.508476 69 7289 pthread_mutex_unlock
5.23 0.337681 69 4859 pthread_cond_signal
2.95 0.190305 63 3019 wcstombs
2.82 0.182225 70 2598 __errno_location
2.20 0.142134 71 1980 readdir64
1.82 0.117427 1726 68 read
1.15 0.074294 495 150 stat64
1.09 0.070605 65 1074 pthread_self
0.98 0.063064 70 893 strncmp
0.91 0.059068 19689 3 qsort
0.89 0.057308 69 820 strcmp
0.83 0.053327 65 808 strchr
0.74 0.047969 64 748 mbstowcs
0.71 0.045808 63 721 wcscmp
0.54 0.034866 64 539 sem_post
0.54 0.034743 1052 33 open64
0.43 0.027669 87 315 strrchr
0.42 0.027413 67 408 sem_trywait
0.39 0.025498 66 386 memmove
0.30 0.019511 71 271 __ctype_b_loc
0.29 0.018577 66 278 realloc
0.26 0.016521 67 246 wcslen
0.14 0.009171 70 131 sem_wait
0.14 0.008875 125 71 lseek64
0.13 0.008263 66 125 sem_destroy
0.13 0.008143 65 125 sem_init
0.12 0.008060 122 66 fstat64
0.12 0.007463 109 68 sigaction
0.11 0.007193 1798 4 fopen64
0.11 0.006882 69 99 memrchr
0.08 0.005425 120 45 isatty
0.07 0.004799 133 36 close
0.05 0.003121 74 42 wcscat
0.04 0.002873 95 30 getenv
0.04 0.002311 77 30 memchr
0.03 0.002087 173 12 opendir
0.02 0.001526 127 12 closedir
0.02 0.001500 68 22 strerror
0.02 0.001443 84 17 calloc
0.02 0.001408 78 18 wcscpy
0.02 0.001079 119 9 setlocale
0.01 0.000751 57 13 wcschr
0.01 0.000714 71 10 __wcsncpy_chk
0.01 0.000673 67 10 fileno
0.01 0.000645 322 2 localtime_r
0.01 0.000449 64 7 nl_langinfo
0.01 0.000433 108 4 readlink
0.01 0.000385 385 1 pthread_condattr_init
0.01 0.000385 128 3 mmap64
0.01 0.000348 348 1 __realpath_chk
0.01 0.000325 108 3 dup
0.00 0.000285 142 2 write
0.00 0.000254 84 3 __uflow
0.00 0.000230 57 4 sigemptyset
0.00 0.000221 73 3 flockfile
0.00 0.000197 65 3 strncpy
0.00 0.000193 64 3 funlockfile
0.00 0.000191 63 3 sysconf
0.00 0.000189 94 2 __vsnprintf_chk
0.00 0.000178 178 1 fread
0.00 0.000169 169 1 getcwd
0.00 0.000164 82 2 strcpy
0.00 0.000159 159 1 pthread_condattr_setclock
0.00 0.000150 75 2 fflush
0.00 0.000140 140 1 ftell
0.00 0.000136 136 1 getrandom
0.00 0.000133 133 1 ioctl
0.00 0.000133 133 1 fclose
0.00 0.000132 132 1 getc
0.00 0.000119 59 2 pthread_mutex_init
0.00 0.000119 119 1 rewind
0.00 0.000114 57 2 pthread_cond_init
0.00 0.000107 107 1 getuid
0.00 0.000105 105 1 getegid
0.00 0.000104 104 1 getgid
0.00 0.000101 101 1 geteuid
0.00 0.000098 98 1 fcntl64
0.00 0.000089 89 1 __sprintf_chk
0.00 0.000087 87 1 pthread_key_delete
0.00 0.000086 86 1 pthread_key_create
0.00 0.000079 79 1 ungetc
0.00 0.000068 68 1 wcsrchr
0.00 0.000067 67 1 confstr
0.00 0.000064 64 1 floor
0.00 0.000063 63 1 time
0.00 0.000060 60 1 __libc_current_sigrtmin
0.00 0.000058 58 1 getauxval
0.00 0.000058 58 1 __libc_current_sigrtmax
0.00 0.000056 56 1 pthread_setspecific
0.00 0.000056 56 1 pthread_getspecific
------ ----------- ----------- --------- --------------------
100.00 6.457072 91699 total

可以看到c++总共进行了4次动态库函数调用,而python却进行了91699次动态库函数调用,我有点惊讶,没想到python动态库函数调用的次数会这么多,而c++却只有四次,在时间方面,c++只用了0.002200秒,而python却用了6.457072秒,两者差距非常大。不过python如果只是单纯地打印hello world的话,应该是用不到一秒的啊,(或许这里的动态库函数调用应该也包括了ltrace跟踪函数调用所需要调用的函数吧。)

作者

axgn

发布于

2025-01-25

更新于

2025-12-23

许可协议