uWebSockets: Memory doesn't free

Hi I am running a simple test with the following code:

#include <iostream>

#include "App.h"

using namespace std;

struct SocketContext {
  string id;
};

int main(int argc, char** argv) {
  uWS::SSLApp({
    .key_file_name = getenv("SSL_KEY_FILE"),
    .cert_file_name = getenv("SSL_CERT_FILE")
  })
  .ws<SocketContext>(
    "/",
    {
      .compression = uWS::SHARED_COMPRESSOR,
      .maxPayloadLength = 256 * 1024,
      .idleTimeout = 60,
      .maxBackpressure = 64 * 1024,
      .closeOnBackpressureLimit = false,
      .resetIdleTimeoutOnSend = false,
      .sendPingsAutomatically = false,
      .upgrade = nullptr,
      .open = [](auto* ws) { },
      .message = [](auto* ws, string_view message, uWS::OpCode opCode) {  },
      .drain = [](auto* ws) { },
      .ping = [](auto* ws, string_view message) {},
      .pong = [](auto* ws, string_view message) {},
      .subscription = [](auto* ws, string_view message, int, int) {},
      .close = [](auto* ws, int code, string_view message) { }})
  .listen(8081,[](auto* token) {})
  .run();

  return 0;
}

uWebsocket version/commit used: https://github.com/uNetworking/uWebSockets/tree/ba6ff7b7f4015859586691c7c1ec0149a3ee3858 .

I run the process under massif memory tool valgrind --tool=massif --threshold=0.01 <executable>, and run a simple tester against this opening 100s of connections and terminating them.

This is the memory usage I get from massif:


    MB
59.74^                                  #                                     
     |                             @@::@#                                     
     |                             @ : @#:::@:::@:::@::::@::::::::@::: ::  :  
     |                             @ : @#:::@:::@:::@: ::@::::::::@:::::::@:::
     |                          :@:@ : @#:::@:::@:::@: ::@::::::::@:::::::@:::
     |                        :::@:@ : @#:::@:::@:::@: ::@::::::::@:::::::@:::
     |                       :: :@:@ : @#:::@:::@:::@: ::@::::::::@:::::::@:::
     |                   :@:::: :@:@ : @#:::@:::@:::@: ::@::::::::@:::::::@:::
     |                   :@:::: :@:@ : @#:::@:::@:::@: ::@::::::::@:::::::@:::
     |                  ::@:::: :@:@ : @#:::@:::@:::@: ::@::::::::@:::::::@:::
     |              ::::::@:::: :@:@ : @#:::@:::@:::@: ::@::::::::@:::::::@:::
     |              ::::::@:::: :@:@ : @#:::@:::@:::@: ::@::::::::@:::::::@:::
     |            ::::::::@:::: :@:@ : @#:::@:::@:::@: ::@::::::::@:::::::@:::
     |            ::::::::@:::: :@:@ : @#:::@:::@:::@: ::@::::::::@:::::::@:::
     |         :::::::::::@:::: :@:@ : @#:::@:::@:::@: ::@::::::::@:::::::@:::
     |        ::::::::::::@:::: :@:@ : @#:::@:::@:::@: ::@::::::::@:::::::@:::
     |        ::::::::::::@:::: :@:@ : @#:::@:::@:::@: ::@::::::::@:::::::@:::
     |      ::::::::::::::@:::: :@:@ : @#:::@:::@:::@: ::@::::::::@:::::::@:::
     |  :@::::::::::::::::@:::: :@:@ : @#:::@:::@:::@: ::@::::::::@:::::::@:::
     |  :@::::::::::::::::@:::: :@:@ : @#:::@:::@:::@: ::@::::::::@:::::::@:::
   0 +----------------------------------------------------------------------->Gi
     0                                                                   23.00

Number of snapshots: 75
 Detailed snapshots: [3, 20, 27, 29, 32, 33 (peak), 37, 41, 45, 50, 60, 70]

The alignment might look a bit janky but point is that the memory doesn’t get released upon termination of the tester connections.

This is a problem I am dealing with at the moment in a production application, but for simplicity I wrote the code above. results are similar.

I did the same without use of SSL ( uWS::App()) and here is massif memory print:

     MB
4.821^                                       :                                
     |                                    :@#:::::::::::::::::::::::::::::::::
     |                                  :::@#::                              :
     |                                @@:::@#::                              :
     |                              :@@@:::@#::                              :
     |                           :@@:@@@:::@#::                              :
     |                         @@:@@:@@@:::@#::                              :
     |                      :::@@:@@:@@@:::@#::                              :
     |                    :@:::@@:@@:@@@:::@#::                              :
     |                  @::@:::@@:@@:@@@:::@#::                              :
     |                @@@::@:::@@:@@:@@@:::@#::                              :
     |              @:@@@::@:::@@:@@:@@@:::@#::                              :
     |           @:@@:@@@::@:::@@:@@:@@@:::@#::                              :
     |         :@@:@@:@@@::@:::@@:@@:@@@:::@#::                              :
     |        ::@@:@@:@@@::@:::@@:@@:@@@:::@#::                              :
     |      @:::@@:@@:@@@::@:::@@:@@:@@@:::@#::                              :
     |    ::@:::@@:@@:@@@::@:::@@:@@:@@@:::@#::                              :
     |    ::@:::@@:@@:@@@::@:::@@:@@:@@@:::@#::                              :
     |    ::@:::@@:@@:@@@::@:::@@:@@:@@@:::@#::                              :
     |    ::@:::@@:@@:@@@::@:::@@:@@:@@@:::@#::                              :
   0 +----------------------------------------------------------------------->Mi
     0                                                                   281.8

Number of snapshots: 56
 Detailed snapshots: [7, 13, 15, 17, 18, 21, 22, 23, 27, 32, 34, 36, 37, 38, 40, 41, 42, 43, 48, 50, 52 (peak)]

Would appreciate any insights. Can provide any more information required.

About this issue

  • Original URL
  • State: closed
  • Created a year ago
  • Comments: 15 (7 by maintainers)

Most upvoted comments

How do you exit the server? Of course it will have blocks still reachable if you for instance just hit Control + C to kill it. If you expect a clean shut down you need to shut down it cleanly like we do in the fuzz tests (they all startup and shutdown cleanly under LeakSanitizer).

glibc is not very keen on returning memory to the system, so having a higher than iniitial memory usage is not a bug. This is different with for instance libtcmalloc or jemalloc which are more reliably returning memory to the system.