Perf: Fix mis-usage of Arena in HPACK#6495
Conversation
687b2eb to
93b9d1d
Compare
|
I'm worried about a size of the internal buffer and a length of the block chain in Arena. Using an arena for long time might have a similar issue with HdrHeap. |
|
What kind of memory behavior is required? How long do the encoded strings need to persist? |
|
All usage of Arena in the HPACK is allocating temporal strings. When the required buffer is small, we can use a buffer on the stack instead of Arena. ( it's another approach. ) The stored strings are freed at the end of function at longest. IIUC, unlike HdrHeap, allocated memory for Arena is re-used. The problem of HdrHeap is when the string in the HdrHeep is freed, the actual buffer was not freed. Similar things can happen to Arena? |
|
I didn't read the code closely so I may be wrong. The space seems like to be freed, but blocks are not. Once the chain gets long it never gets short, IIUC. |
|
The block will be reused if possible, so the worst case is requested string length keeps growing. When requested string length is 1byte to 128KB, the total allocated memory is 568KB (in 13 blocks). (128KB is default value of |
|
@SolidWallOfCode |
|
Well, not the |
|
The Temporary Allocation will cover this case well. No accumulation seems good. Let's use it when it backported. For now, let's land this change. Or if we really worry about the total size of Arena, we can go another approach like switching |
| if (len == -1) { | ||
| if (use_huffman && value_len) { | ||
| arena.str_free(data); | ||
| } |
There was a problem hiding this comment.
You could use https://github.com/apache/trafficserver/blob/master/include/tscpp/util/PostScript.h to avoid having to repeat this free 3 times.
There was a problem hiding this comment.
I didn't know we have this. I was thinking to introduce "defer" like this.
There was a problem hiding this comment.
Dr. Zret picked the name PostScript.
| } | ||
|
|
||
| return p - buf_start; | ||
| } |
There was a problem hiding this comment.
An alternative to using an arena here would be something like:
template <std::size_t EstSizeBound = 1024>
class LocalBuffer
{
public:
LocalBuffer(std::size_t size) : _ptr(size > EstSizeBound ? new char[size] : _buf) {}
char * get() const { return _ptr; }
~LocalBuffer()
{
if (_ptr != buf) {
delete [] _ptr;
}
}
private:
char _buf[EstSizeBound];
char * const _ptr;
};
(Where 1024 is the default arena block size.). I'm guessing it would have better performance in the most likely scenarios.
There was a problem hiding this comment.
Looks smarter than what I told as alternative approach (switching alloca & malloc ).
I agree with performance is better in most cases. I'll try this way.
|
#6536 looks much better on performance and no concern about memory accumulation. |
Arenais used for temporally buffer in some functions of HAPCK, but they are destroyed immediately. This is making some overhead of memory allocation. The arena should be reused.