Reduce memory allocations due to zlib's uncompress().
authorGuus Sliepen <guus@tinc-vpn.org>
Sun, 18 Feb 2018 14:38:12 +0000 (15:38 +0100)
committerGuus Sliepen <guus@tinc-vpn.org>
Sun, 18 Feb 2018 14:38:33 +0000 (15:38 +0100)
Everytime uncompress() is called, zlib allocates some buffer on the heap
and frees it again. When compression is enabled, this is the biggest source
of memory allocations in tinc. Instead of using this function, use
inflate(), which can store its state in a z_stream variable, which avoids
(re)allocating memory for every packet received.

This issue was found thanks to heaptrack.

src/net_packet.c

index d37f2202c23f5fdedfdb70634c1fd49fdef1d936..3d3d6913f34d9cc1061bc827f8a47ffc2654bc0b 100644 (file)
@@ -23,6 +23,7 @@
 #include "system.h"
 
 #ifdef HAVE_ZLIB
+#define ZLIB_CONST
 #include <zlib.h>
 #endif
 
@@ -249,9 +250,22 @@ static length_t uncompress_packet(uint8_t *dest, const uint8_t *source, length_t
 #ifdef HAVE_ZLIB
        else {
                unsigned long destlen = MAXSIZE;
+               static z_stream stream;
 
-               if(uncompress(dest, &destlen, source, len) == Z_OK) {
-                       return destlen;
+               if(stream.next_in) {
+                       inflateReset(&stream);
+               } else {
+                       inflateInit(&stream);
+               }
+
+               stream.next_in = source;
+               stream.avail_in = len;
+               stream.next_out = dest;
+               stream.avail_out = destlen;
+               stream.total_out = 0;
+
+               if(inflate(&stream, Z_FINISH) == Z_STREAM_END) {
+                       return stream.total_out;
                } else {
                        return -1;
                }