Chinaunix首页 | 论坛 | 博客
  • 博客访问: 519680
  • 博文数量: 78
  • 博客积分: 995
  • 博客等级: 准尉
  • 技术积分: 1462
  • 用 户 组: 普通用户
  • 注册时间: 2011-11-15 20:22
个人简介

技术中沉思的时候最快乐,问题得到完美解决的时候最有成就感!

文章分类

全部博文(78)

文章存档

2013年(39)

2012年(37)

2011年(2)

分类: C/C++

2013-04-05 22:32:37

原文地址:memcmp之优化 作者:hk2305621

前段时间在公司移植一个工具的时候,历经千辛万难,终于把工具移植过去了。因为工具涉及到写Nand Flash,所以需要将写入的数据读出来,确认是否数据被正确的写入到flash上。结果,发现两者的效率确实有相当大的差异。于是,就着手开始找问题出在哪里。由于是和nand flash相关,最开始是以为移植后的nand驱动的效率不高导致。但是最后,定位到是memcmp。

1. 编译的工具使用的是memcmp,但是memcmp通过__attribute__("alisa")定义为另外一个自己写的函数的别名.
int my_memcmp(void *s1, void *s2, int len)__attribute__((alias("my_memcmp"));
但是,my_memcmp的效率太低了。导致工具移植后的效率也降下来。
my_memcmp的实现大致如下:

  1. int my_memcmp_1(void *s1, void *s2, int len)
  2. {
  3.     int count;
  4.     const char *str1, *str2;

  5.     str1 = (const char *)s1;
  6.     str2 = (const char *)s2;

  7.     for (count = 0; count < len; count++) {
  8.         if (*(str1 + count) != *(str2 + count)) {
  9.             return *(str1 + count ) > *(str2 + count) ? 1 : -1;
  10.         }
  11.     }
  12.     return 0;
  13. }
所以,需要着手优化my_memcmp。

2. 因为旧工具中,memcmp使用的是gcc的库函数,所以,就直接下来了的源码,找到memcmp函数,然后将代码直接拿过来用。
gcc中间的memcmp实现很简洁,在gcc-4.5.3/libiberty/memcmp.c中,实现如下:
  1. int
  2. memcmp (const PTR str1, const PTR str2, size_t count)
  3. {
  4.     register const unsigned char *s1 = (const unsigned char*)str1;
  5.     register const unsigned char *s2 = (const unsigned char*)str2;

  6.     while (count-- > 0) {
  7.         if (*s1++ != *s2++)
  8.      return s1[-1] < s2[-1] ? -1 : 1;
  9.     }
  10.     return 0;
  11. }

但是,发现效率也并没有太大的改善。

3. 将电脑中gcc库,通过obj-dump工具,将gcc的库反汇编出来,看看工具链中gcc的memcmp是怎么实现的。
结果发现,gcc库中实现的memcmp一次跳4个字节。突然就茅塞顿开。根据汇编代码实现我自己的memcmp。效率工具链中的memcmp效率基本一致。

  1. int my_memcmp(void *s1, void *s2, int len)
  2. {
  3.     const int *p1, *q1;
  4.     const char *p2, *q2;
  5.     int off, mod;

  6.     off = len >> 2;
  7.     mod = len - (off << 2);

  8.     if (mod > 0) {
  9.         p2 = (const char *)s1;
  10.         q2 = (const char *)s2;
  11.         while (mod --) {
  12.             if (*p2 ++ != *q2 ++) {
  13.                 return p2[-1] > q2[-1] ? 1 : -1;
  14.             }
  15.         }
  16.     }

  17.     /* if p1 & q1 address don't align with 4 bytes,
  18.        how about the efficiency ? */
  19.     mod = len - (off << 2);
  20.     p1 = (const int *)(s1 + mod);
  21.     q1 = (const int *)(s2 + mod);

  22.     while (off --) {
  23.         if (*p1 ++ != *q1 ++) {
  24.             return p1[-1] > q1[-1] ? 1 : -1;
  25.         }
  26.     }

  27.     return 0;
  28. }

4.经过测试,基本OK.也算大功告成。
不过还有一个疑惑就是,在将char类型指针转换为int类型指针的时候,是否会存在因为地址没有对齐,而降低效率呢?


 

阅读(3446) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~