I've done some digging into the sample app @iljaiwas provided. (Thanks for putting that together!)
macOS, no leaks
From what I can tell memory usage looks normal on macOS, with no leaks. The memory usage graph does make it seem like some memory is leaking, but I believe this is due to Foundation's internal caching for JSON serialization and Date components. The memory graph debugger and leak debugger show no new allocations (after enough requests to load all lazy services in).
Linux, leaking
On Linux however, it's a much different story. The first request takes the application from 2.9MiB
in the System Monitor to 374.2MiB
. From what I can tell, that memory is never released.
I ran valgrind on the executable using the following command:
valgrind --leak-check=full .build/release/Run
It was able to detect 434,075,912
bytes "definitely lost". Here is the output for that loss record:
==30059== 434,075,912 (719,640 direct, 433,356,272 indirect) bytes in 9,995 blocks are definitely lost in loss record 1,218 of 1,218
==30059== at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==30059== by 0x51F1C91: swift_slowAlloc (in /home/tanner/swift/swift-5.0-RELEASE-ubuntu18.04/usr/lib/swift/linux/libswiftCore.so)
==30059== by 0x51F1CFE: _swift_allocObject_(swift::TargetHeapMetadata<swift::InProcess> const*, unsigned long, unsigned long) (in /home/tanner/swift/swift-5.0-RELEASE-ubuntu18.04/usr/lib/swift/linux/libswiftCore.so)
==30059== by 0x3FCFC9: $s10Foundation4DataV11bytesNoCopy5count11deallocatorACSv_SiAC11DeallocatorOtcfCTf4nngd_n (in /home/tanner/dev/sandbox/vapor-memory-leak/.build/x86_64-unknown-linux/release/Run)
==30059== by 0x3FCB8A: $s3NIO10ByteBufferV19NIOFoundationCompatE7getData2at6length10Foundation0G0VSgSi_SitF (in /home/tanner/dev/sandbox/vapor-memory-leak/.build/x86_64-unknown-linux/release/Run)
==30059== by 0x3FCA80: $s3NIO10ByteBufferV19NIOFoundationCompatE8readData6length10Foundation0G0VSgSi_tF (in /home/tanner/dev/sandbox/vapor-memory-leak/.build/x86_64-unknown-linux/release/Run)
==30059== by 0x3249F6: $s5MySQL0A21SQLBinaryResultsetRowV5bytes7columnsAC3NIO10ByteBufferVz_SayAA0A21SQLColumnDefinition41VGtKcfCTf4nnd_n (in /home/tanner/dev/sandbox/vapor-memory-leak/.build/x86_64-unknown-linux/release/Run)
==30059== by 0x31EEB2: $s5MySQL0A16SQLPacketDecoderC23decodeStatementProtocol3ctx6buffer14statementState12capabilities3NIO08DecodingK0OAI21ChannelHandlerContextC_AI10ByteBufferVzAA0a12SQLStatementgK0OAA0A15SQLCapabilitiesVtKF (in /home/tanner/dev/sandbox/vapor-memory-leak/.build/x86_64-unknown-linux/release/Run)
==30059== by 0x31BCC5: $s5MySQL0A16SQLPacketDecoderC6decode3ctx6buffer3NIO13DecodingStateOAG21ChannelHandlerContextC_AG10ByteBufferVztKF (in /home/tanner/dev/sandbox/vapor-memory-leak/.build/x86_64-unknown-linux/release/Run)
==30059== by 0x3202F8: $s5MySQL0A16SQLPacketDecoderC3NIO013ByteToMessageD0AadEP6decode3ctx6bufferAD13DecodingStateOAD21ChannelHandlerContextC_AD0F6BufferVztKFTW (in /home/tanner/dev/sandbox/vapor-memory-leak/.build/x86_64-unknown-linux/release/Run)
==30059== by 0x38CA08: $sTA (in /home/tanner/dev/sandbox/vapor-memory-leak/.build/x86_64-unknown-linux/release/Run)
==30059== by 0x38CA58: $sTA.15 (in /home/tanner/dev/sandbox/vapor-memory-leak/.build/x86_64-unknown-linux/release/Run)
And the final leak summary:
==30059== LEAK SUMMARY:
==30059== definitely lost: 720,720 bytes in 9,999 blocks
==30059== indirectly lost: 433,356,272 bytes in 29,836 blocks
==30059== possibly lost: 7,782,952 bytes in 171 blocks
==30059== still reachable: 26,334,436 bytes in 182,329 blocks
==30059== suppressed: 0 bytes in 0 blocks
From what I can tell, the leak seems related to Foundation.Data.init(bytesNoCopy:count:deallocator:)
, though I'm not sure how or why. Any additional insight would be greatly appreciated, thanks!