字符串拷贝函数memcpy()、strncpy()和snprintf()性能之比较

问题:

函数memcpy(dest, src, sizeof(dest))、strncpy(dest, src, sizeof(dest))和snprintf(dest, sizeof(dest), "%s", src)都可以将src字符串中的内容拷贝到dest字符串中。

哪一种方式效率最高呢?

就是说,哪种方式性能最好呢?


解决办法:

1. 建立三个文件test_memcpy.c,test_strncpy.c和test_snprintf.c:

文件test_memcpy.c:

[cpp]  view plain copy print ?
  1. david@u1110-hp:~/wrk/tmp/cstring$ cat test_memcpy.c  
  2. #include   
  3. int main(){  
  4.     char src[] = "1234567890";  
  5.     char dest[2048];  
  6.     int len = 0;  
  7.   
  8.     for(int i = 0; i < 10000000; ++i){  
  9.         memset(dest, 0, sizeof(dest));  
  10.         len = strlen(src);  
  11.         len = sizeof(dest) - 1 > len? len: sizeof(dest) -1;  
  12.         memcpy(dest, src, len);  
  13.         dest[len] = '\0';  
  14.     }  
  15.   
  16.     return 0;  
  17. }  

文件test_strncpy.c:

[cpp]  view plain copy print ?
  1. #include   
  2. int main() {  
  3.     char src[] = "1234567890";  
  4.     char dest[2048];  
  5.     int len = 0;  
  6.       
  7.     for(int i = 0; i < 10000000; ++i) {  
  8.         memset(dest, 0, sizeof(dest));  
  9.         strncpy(dest, src, sizeof(dest));  
  10.     }  
  11.       
  12.     return 0;  
  13. }  
文件test_snprintf.c:

[cpp]  view plain copy print ?
  1. #include   
  2. #include   
  3.   
  4. int main() {  
  5.     char src[] = "1234567890";  
  6.     char dest[2048];  
  7.     int len = 0;  
  8.       
  9.     for(int i = 0; i < 10000000; ++i) {  
  10.         memset(dest, 0, sizeof(dest));  
  11.         snprintf(dest, sizeof(dest), "%s", src);  
  12.     }  
  13.       
  14.     return 0;  
  15. }  

2. 分别编译三个文件:

[cpp]  view plain copy print ?
  1. david@u1110-hp:~/wrk/tmp/cstring$ gcc -std=c99 -o test_memcpy test_memcpy.c  
  2. david@u1110-hp:~/wrk/tmp/cstring$ gcc -std=c99 -o test_strncpy test_strncpy.c  
  3. david@u1110-hp:~/wrk/tmp/cstring$ gcc -std=c99 -o test_snprintf test_snprintf.c  

3. 没有优化的情况下不同函数消耗时间对比:

[cpp]  view plain copy print ?
  1. david@u1110-hp:~/wrk/tmp/cstring$ time ./test_strncpy  
  2.   
  3. real    0m16.472s  
  4. user    0m16.309s  
  5. sys 0m0.036s  
  6. david@u1110-hp:~/wrk/tmp/cstring$ time ./test_snprintf   
  7.   
  8. real    0m6.106s  
  9. user    0m6.100s  
  10. sys 0m0.000s  
  11. david@u1110-hp:~/wrk/tmp/cstring$ time ./test_memcpy   
  12.   
  13. real    0m4.179s  
  14. user    0m4.144s  
  15. sys 0m0.000s  
  16. david@u1110-hp:~/wrk/tmp/cstring$  

从上面运行结果可以看出:没有任何优化的情况下,memcpy()和strncpy()性能相差4倍,snprintf()和strncpy()性能相差约2.5倍。


4.采用O3优化情况下不同函数消耗时间对比:

[cpp]  view plain copy print ?
  1. david@u1110-hp:~/wrk/tmp/cstring$ gcc -std=c99 -O3 -o test_snprintf test_snprintf.c  
  2. david@u1110-hp:~/wrk/tmp/cstring$ gcc -std=c99 -O3 -o test_strncpy test_strncpy.c  
  3. david@u1110-hp:~/wrk/tmp/cstring$ gcc -std=c99 -O3 -o test_memcpy test_memcpy.c  
  4. david@u1110-hp:~/wrk/tmp/cstring$  
[cpp]  view plain copy print ?
  1. david@u1110-hp:~/wrk/tmp/cstring$ time ./test_strncpy  
  2.   
  3. real    0m16.178s  
  4. user    0m16.161s  
  5. sys 0m0.000s  
  6. david@u1110-hp:~/wrk/tmp/cstring$ time ./test_snprintf   
  7.   
  8. real    0m6.242s  
  9. user    0m6.032s  
  10. sys 0m0.056s  
  11. david@u1110-hp:~/wrk/tmp/cstring$ time ./test_memcpy   
  12.   
  13. real    0m3.567s  
  14. user    0m3.436s  
  15. sys 0m0.012s  
  16. david@u1110-hp:~/wrk/tmp/cstring$  

从上面运行结果可以看出:采用O3优化后,memcpy()和strncpy()性能相差近5倍,snprintf()和strncpy()性能相差基本不变约2.5倍。

5. 性能对比结论:

在需要用到字符串拷贝函数的时候,永远不要使用strncpy(),无论什么时候都用snprintf()来代替,而memcpy()是性能更好的实现方式

strlen+memcpy也是linux内核的实现方式。

6. 意外收获结论:

将上述三个文件中的memset()改为用bzero()来实现数组的清零操作。

使用O3来进行优化,三个函数的耗时时间如下:

[cpp]  view plain copy print ?
  1. david@u1110-hp:~/wrk/tmp/cstring$ time ./test_strncpy  
  2.   
  3. real    0m14.395s  
  4. user    0m13.929s  
  5. sys 0m0.092s  
  6. david@u1110-hp:~/wrk/tmp/cstring$ time ./test_snprintf   
  7.   
  8. real    0m3.785s  
  9. user    0m3.772s  
  10. sys 0m0.000s  
  11. david@u1110-hp:~/wrk/tmp/cstring$ time ./test_memcpy   
  12.   
  13. real    0m1.241s  
  14. user    0m1.236s  
  15. sys 0m0.004s  
  16. david@u1110-hp:~/wrk/tmp/cstring$  

结论:仅仅换了一个清零函数,使得memcpy()和strncpy()的性能差别达到约12倍,而snprintf()和strncpy()的性能差别也达到约4倍。

就清零操作来说,bzero()远比memset()更高效


你可能感兴趣的:(字符串拷贝函数memcpy()、strncpy()和snprintf()性能之比较)