folly源码分析(1) - Conv.h

Conv是一个类型转换的库,主要实现了字符串到整数和浮点数的转换,性能要比snprintfstrtol要好上一些。

doublestring的来回转换主要是用google的开源项目double conversion来实现的,这里按下不表

我们主要考察intstring的来回转换的实现

其中int->string的关键代码是,可以看到是非常简单的查表操作:

extern const chardigit1[101] =
 "00000000001111111111222222222233333333334444444444"
 "55555555556666666666777777777788888888889999999999";
extern const chardigit2[101] =
 "01234567890123456789012345678901234567890123456789"
 "01234567890123456789012345678901234567890123456789";
 
// Returns the offset ofthe formatted string from the start of
// the supplied buffer.The new string will be at range
//[buf+begin,buf+bufLen). Uint will be either uint32_t or uint64_t.
template 
size_tuintToBuffer(char*const buffer, size_t bufLen, Uint v) {
  extern const char digit1[101], digit2[101];
  for (;;) {
    if (v < 100) {
      if (v < 10) {
        buffer[--bufLen] =static_cast(v + '0');
      } else {
        size_t r =static_cast(v);
        bufLen -= 2;
        buffer[bufLen] = digit1[r];
        buffer[bufLen + 1] = digit2[r];
      }
      break;
    }
    Uint t = v;
    v /= 100;
    size_t r = static_cast (t - v* 100);
    bufLen -= 2;
    buffer[bufLen] = digit1[r];
    buffer[bufLen + 1] = digit2[r];
  }
  return bufLen;
}


性能:1y随机数转化成string,耗时3.8ssnprintf耗时27.3s

 

而从string->int的操作的核心代码如下,也是简单的差别操作:

/*
 * Lookup tables that converts from a decimalcharacter value to an integral
 * binary value, shifted by a decimal"shift" multiplier.
 * For all character values in the range'0'..'9', the table at those
 * index locations returns the actual decimalvalue shifted by the multiplier.
 * For all other values, the lookup tablereturns an invalid OOR value.
 */
// Out-of-range flagvalue, larger than the largest value that can fit in
// four decimal bytes(9999), but four of these added up together should
// still not overflowuint16_t.
constexpr int32_t OOR =10000;
 
__attribute__((aligned(16)))constexpr uint16_t shift1[] = {
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 0-9
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 10
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 20
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 30
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,0,         //  40
  1, 2, 3, 4, 5, 6, 7, 8, 9, OOR, OOR,
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 60
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 70
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 80
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 90
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 100
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 110
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 120
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 130
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 140
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 150
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 160
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 170
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 180
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 190
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 200
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 210
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 220
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 230
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 240
  OOR, OOR, OOR, OOR, OOR, OOR                       // 250
};
 
__attribute__((aligned(16)))constexpr uint16_t shift10[] = {
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 0-9
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 10
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 20
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 30
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,0,         //  40
  10, 20, 30, 40, 50, 60, 70, 80, 90, OOR, OOR,
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 60
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 70
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 80
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 90
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 100
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 110
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 120
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 130
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 140
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 150
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 160
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 170
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 180
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 190
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 200
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 210
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 220
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 230
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 240
  OOR, OOR, OOR, OOR, OOR, OOR                       // 250
};
 
__attribute__((aligned(16)))constexpr uint16_t shift100[] = {
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 0-9
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 10
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 20
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 30
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,0,         //  40
  100, 200, 300, 400, 500, 600, 700, 800, 900,OOR, OOR,
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 60
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 70
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 80
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 90
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 100
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 110
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 120
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 130
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 140
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 150
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 160
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 170
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 180
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 190
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 200
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 210
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 220
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 230
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 240
  OOR, OOR, OOR, OOR, OOR, OOR                       // 250
};
 
__attribute__((aligned(16)))constexpr uint16_t shift1000[] = {
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 0-9
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 10
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 20
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 30
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,0,         //  40
  1000, 2000, 3000, 4000, 5000, 6000, 7000,8000, 9000, OOR, OOR,
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 60
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 70
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 80
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 90
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 100
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 110
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 120
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 130
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 140
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 150
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 160
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 170
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 180
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 190
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 200
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 210
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 220
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 230
  OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR,  // 240
  OOR, OOR, OOR, OOR, OOR, OOR                       // 250
};
 
/**
 * String represented as a pair of pointers tochar to unsigned
 * integrals. Assumes NO whitespace before orafter, and also that the
 * string is composed entirely of digits. Tgtmust be unsigned, and no
 * sign is allowed in the string (even it's'+'). String may be empty,
 * in which case digits_to throws.
 */
  template 
  Tgt digits_to(const char * b, const char * e){
 
   static_assert(!std::is_signed::value, "Unsigned typeexpected");
    assert(b <= e);
 
    const size_t size = e - b;
 
    /* Although the string is entirely made ofdigits, we still need to
     * check for overflow.
     */
    if (size >=std::numeric_limits::digits10 + 1) {
      // Leading zeros? If so, recurse to keepthings simple
      if (b < e && *b == '0') {
        for (++b;; ++b) {
          if (b == e) return 0; // just zeros,e.g. "0000"
          if (*b != '0') returndigits_to(b, e);
        }
      }
      FOLLY_RANGE_CHECK(size ==std::numeric_limits::digits10 + 1 &&
                        strncmp(b,detail::MaxString::value, size) <= 0,
                        "Numeric overflowupon conversion");
    }
 
    // Here we know that the number won'toverflow when
    // converted. Proceed without checks.
 
    Tgt result = 0;
 
    for (; e - b >= 4; b += 4) {
      result *= 10000;
      const int32_t r0 =shift1000[static_cast(b[0])];
      const int32_t r1 =shift100[static_cast(b[1])];
      const int32_t r2 =shift10[static_cast(b[2])];
      const int32_t r3 =shift1[static_cast(b[3])];
      const auto sum = r0 + r1 + r2 + r3;
      assert(sum < OOR &&"Assumption: string only has digits");
      result += sum;
    }
 
    switch (e - b) {
      case 3: {
        const int32_t r0 =shift100[static_cast(b[0])];
        const int32_t r1 =shift10[static_cast(b[1])];
        const int32_t r2 =shift1[static_cast(b[2])];
        const auto sum = r0 + r1 + r2;
        assert(sum < OOR &&"Assumption: string only has digits");
        return result * 1000 + sum;
      }
      case 2: {
        const int32_t r0 =shift10[static_cast(b[0])];
        const int32_t r1 =shift1[static_cast(b[1])];
        const auto sum = r0 + r1;
        assert(sum < OOR &&"Assumption: string only has digits");
        return result * 100 + sum;
      }
      case 1: {
        const int32_t sum =shift1[static_cast(b[0])];
        assert(sum < OOR &&"Assumption: string only has digits");
        return result * 10 + sum;
      }
    }
 
    assert(b == e);
    FOLLY_RANGE_CHECK(size > 0, "Foundno digits to convert in input");
    return result;
  }


性能:1y数据digits_to耗时5sstrtol耗时10s

你可能感兴趣的:(folly源码分析(1) - Conv.h)