zoukankan      html  css  js  c++  java
  • String.IndexOf

    还是上次那个json解析程序的优化, 虽然速度已经比较理想, 但是看到IndexOf占到整个解析时长的20%+, 心里还是不爽. 我写的IndexOf是按照UTF16字符, 一个字符一个字符去比较的, 所以当时能想到的办法, 就是一次比较多个字符.

    大概是五六年前, 我看过某一个libc里面实现的strlen, 算法就是((i - 0x1) & ~i) & 0x80, 这个算法只能针对比较, 所以我在想, 如果我把i矫正成0, 那么算法应该就会变得通用. 然后撸了一下午, 写了一个一次比较4个UTF16 char的版本.

     1 const ulong l1u = 0x1ul | 0x1ul << 16 | 0x1ul << 32 | 0x1ul << 48;
     2 const ulong l80u = 0x8000ul | 0x8000ul << 16 | 0x8000ul << 32 | 0x8000ul << 48;
     3 
     4 public static int IndexOf(char* s, int length, char c)
     5 {
     6   int offset = 0;
     7   int align = (int)s & 0x7;
     8   //8 byte aligned or 4 char aligned
     9   if (align != 0)
    10   {
    11     int index = IndexOf(s, offset, align >> 1, c);
    12     if (index >= 0) return index;
    13   }
    14   //strlen's quick check is based on ((i - 0x1) & ~i) & 0x80
    15   //so, if i add `-expectedChar` onto i
    16   //then i can reuse this formula
    17   ulong magic = (ulong)c;
    18   ulong expected = unchecked(magic | magic << 16 | magic << 32 | magic << 48);
    19   offset += align >> 1;
    20   int padLength = (length - offset) >> 2 << 2;
    21   for (; offset < padLength; offset += 4)
    22   {
    23     ulong p = *(ulong*)(s + offset);
    24     p = p >= expected ? unchecked(p - expected) : unchecked(expected - p);
    25     if (unchecked((p - l1u) & ~p & l80u) != 0)
    26     {
    27       return IndexOf(s, offset, 4, c);
    28     }
    29   }
    30   return IndexOf(s, offset, length - offset, c);
    31 }
    32 
    33 private static int IndexOf(char* s, int offset, int length, char c)
    34 {
    35   if (length > 4) throw new System.Exception("FUCK U");
    36   char* p = s + offset;
    37   switch (length)
    38   {
    39     case 4: goto L4;
    40     case 3: goto L3;
    41     case 2: goto L2;
    42     case 1: goto L1;
    43   }
    44   L4: if (*p++ == c) goto Found;
    45   L3: if (*p++ == c) goto Found;
    46   L2: if (*p++ == c) goto Found;
    47   L1: if (*p++ == c) goto Found;
    48   return -1;
    49   Found: return (int)(p - s);
    50 }

    费劲了脑汁, 结果他妈的, 跑的还没一次比较四个char的快(就是四次if)…..

    妈蛋, 我得什么时候去研究一下这个代码为啥会慢, 感觉不科学啊

    感觉这就是玄学

    PS:

    今天把代码改了一下, 也没改多少, 就是以前一次扫描一个ulong, 现在一次扫描两个ulong, 算法还是一样的.

    在x64下面, 速度是要比一次比较4个char来的快, 快50%以上; 不过在x86下面, 速度比4个char的版本慢一点, 应该是x86面, int64是模拟出来的缘故.

  • 相关阅读:
    Dat2Rin.exe + runpkr00.exe 将*.T0* 数据转换成Rinex文件
    使用scipy.spatial.Delaunay 三角网的构建
    tinkphp3第三方类库引入问题
    git 撤销更改
    nginx各种配置
    elastic教程
    centos添加动态库默认搜索路径
    JSwebsocket问题:One or more reserved bits are on: reserved1 = 1, reserved2 = 1, reserved3 = 0
    关于脚本手动正常运行,放入crontab无效的问题
    mysql相关操作
  • 原文地址:https://www.cnblogs.com/egmkang/p/7449616.html
Copyright © 2011-2022 走看看