-
-
Save filipnavara/7bf3791fb795266fe46f4383a075423c to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// dotnet counters monitor -n sslcounter Crypto.Memory | |
using System.Diagnostics.Tracing; | |
using System.Runtime.InteropServices; | |
using System.Security.Cryptography; | |
CryptoMemoryTracker.Initialize(); | |
Console.WriteLine("Ready"); | |
for (;;) | |
{ | |
var rsa = RSA.Create(4096); | |
rsa.ExportRSAPublicKey(); | |
Console.WriteLine($"Memory usage: {CryptoMemoryTracker.TotalMemory}"); | |
Thread.Sleep(1000); | |
rsa.Dispose(); | |
} | |
[EventSource(Name = SourceName)] | |
unsafe class CryptoMemoryTracker : EventSource | |
{ | |
const string SourceName = "Crypto.Memory"; | |
static CryptoMemoryTracker? instance = null!; | |
static long totalMemory; | |
PollingCounter? cryptoMemoryCounter; | |
[DllImport("ssl", EntryPoint = "CRYPTO_set_mem_functions")] | |
static extern int CRYPTO_set_mem_functions(delegate* unmanaged<nuint, char*, int, void*> mallocFunction, delegate* unmanaged<void*, nuint, char*, int, void*> reallocFunction, delegate* unmanaged<void*, void> freeFunction); | |
public static long TotalMemory => totalMemory; | |
private CryptoMemoryTracker() | |
: base(SourceName, EventSourceSettings.EtwSelfDescribingEventFormat) | |
{ | |
int res = CRYPTO_set_mem_functions(&CryptoMalloc, &CryptoRealloc, &CryptoFree); | |
if (res == 1) | |
{ | |
totalMemory = 0; | |
cryptoMemoryCounter = new PollingCounter( | |
"crypto-memory", | |
this, | |
() => totalMemory) | |
{ | |
DisplayName = "Crypto Heap Size", | |
}; | |
} | |
} | |
public static void Initialize() | |
{ | |
instance = new(); | |
} | |
[UnmanagedCallersOnly] | |
internal static void* CryptoMalloc(nuint size, char* file, int line) | |
{ | |
void* ptr = NativeMemory.Alloc(size + (nuint)sizeof(AllocationHeader)); | |
if (ptr is null) | |
return null; | |
AllocationHeader* header = (AllocationHeader*)ptr; | |
header->Size = size; | |
Interlocked.Add(ref totalMemory, (nint)size); | |
return (void*)((nuint)ptr + (nuint)sizeof(AllocationHeader)); | |
} | |
[UnmanagedCallersOnly] | |
internal static void* CryptoRealloc(void* oldPtr, nuint size, char* file, int line) | |
{ | |
nuint oldSize = 0; | |
AllocationHeader* header = null; | |
if (oldPtr is not null) | |
{ | |
header = (AllocationHeader*)((nuint)oldPtr - (nuint)sizeof(AllocationHeader)); | |
oldSize = header->Size; | |
} | |
void* newPtr = NativeMemory.Realloc((void*)header, size + (nuint)sizeof(AllocationHeader)); | |
if (newPtr is null) | |
return null; | |
header = (AllocationHeader*)newPtr; | |
header->Size = size; | |
Interlocked.Add(ref totalMemory, -(nint)oldSize + (nint)size); | |
return (void*)((nuint)newPtr + (nuint)sizeof(AllocationHeader)); | |
} | |
[UnmanagedCallersOnly] | |
internal static void CryptoFree(void* ptr) | |
{ | |
if (ptr is not null) | |
{ | |
AllocationHeader* header = (AllocationHeader*)((nuint)ptr - (nuint)sizeof(AllocationHeader)); | |
Interlocked.Add(ref totalMemory, -(nint)header->Size); | |
NativeMemory.Free((void*)header); | |
} | |
} | |
struct AllocationHeader | |
{ | |
public nuint Size; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment