`std::string` allocations are my current bottleneck - how can I optimize with a custom allocator?

后端 未结 6 1965
半阙折子戏
半阙折子戏 2021-02-04 06:44

I\'m writing a C++14 JSON library as an exercise and to use it in my personal projects.

By using callgrind I\'ve discovered that the current bottleneck

6条回答
  •  面向向阳花
    2021-02-04 07:09

    The best way to avoid a memory allocation is don't do it!
    BUT if I remember JSON correctly all the readStr values either gets used as keys or as identifiers so you will have to allocate them eventually, std::strings move semantics should insure that the allocated array are not copied around but reused until its final use. The default NRVO/RVO/Move should reduce any copying of the data if not of the string header itself.

    Method 1:
    Pass result as a ref from the caller which has reserved SomeResonableLargeValue chars, then clear it at the start of readStr. This is only usable if the caller actually can reuse the string.

    Method 2:
    Use the stack.

    // Reserve memory for the string (BOTTLENECK)
    if (end - idx < SomeReasonableValue) { // 32?
      char result[SomeReasonableValue] = {0};  // feel free to use std::array if you want bounds checking, but the preceding "if" should insure its not a problem.
      int ridx = 0;
    
      for(; idx < end; ++idx) {
        // Not an escape sequence
        if(!isC('\\')) { result[ridx++] = getC(); continue; }
        // Escape sequence: skip '\'
        ++idx;
        // Convert escape sequence
        result[ridx++] = getEscapeSequence(getC());
      }
    
      // Skip closing '"'
      ++idx;
      result[ridx] = 0; // 0-terminated.
      // optional assert here to insure nothing went wrong.
      return result; // the bottleneck might now move here as the data is copied to the receiving string.
    }
    // fallback code only if the string is long.
    // Your original code here
    

    Method 3:
    If your string by default can allocate some size to fill its 32/64 byte boundary, you might want to try to use that, construct result like this instead in case the constructor can optimize it.

    Str result(end - idx, 0);
    

    Method 4:
    Most systems already has some optimized allocator that like specific block sizes, 16,32,64 etc.

    siz = ((end - idx)&~0xf)+16; // if the allocator has chunks of 16 bytes already.
    Str result(siz);
    

    Method 5:
    Use either the allocator made by google or facebooks as global new/delete replacement.

提交回复
热议问题