• Giuseppe Ottaviano's avatar
    Reuse the writable tail after IOBufQueue::append(IOBuf) · 0d412cdd
    Giuseppe Ottaviano authored
    Summary:
    After calling `IOBufQueue::append(IOBuf)` (both the `unique_ptr` and value overloads) the existing writable tail is lost, because the new tail buffer may not have a writable tail (in practice it's often shared or sized to fit).
    
    This is especially a problem for zero-copy Thrift serialization, for example of a struct like
    ```
    struct S {
      1: binary (cpp2.type = "folly::IOBuf") data;
    }
    ```
    Thrift allocates at least 16KiB for each new buffer, and writes a handful of bytes before and after the `IOBuf`, so the epilogue will take a whole new 16KiB allocation. The problem is amplified with consecutive binary fields, if they don't fit in 4KiB (`kMaxPackCopy`) and the existing writable tail, each will cost an extra 16KiB, which means a 4x memory amplification.
    
    This diff reuses the previous writable tail buffer by appending a new `IOBuf` to the chain that references it.
    
    Reviewed By: philippv
    
    Differential Revision: D31882377
    
    fbshipit-source-id: fe1d0c82f7df5528534d42b46da78f6597a9e519
    0d412cdd
IOBufQueue.h 20.2 KB