|
30 | 30 | //================================================================================== |
31 | 31 | #include "utils/memory.h" |
32 | 32 |
|
| 33 | +#if defined(__GLIBC__) |
| 34 | + #include <malloc.h> |
| 35 | +#endif |
| 36 | + |
33 | 37 | namespace lbcrypto { |
34 | 38 |
|
| 39 | +#if defined(__GLIBC__) |
| 40 | +// Tune glibc malloc for FHE allocation patterns. Each homomorphic operation allocates and |
| 41 | +// frees many large (~0.5-30 MB) polynomial coefficient buffers. By default glibc returns |
| 42 | +// these freed buffers to the OS (brk heap-trim / munmap) and re-faults the pages on the next |
| 43 | +// operation; under a single thread this page-fault / kernel-time overhead can dominate |
| 44 | +// runtime. Keeping large allocations on the heap (M_MMAP_MAX=0) and never trimming it back to |
| 45 | +// the OS (M_TRIM_THRESHOLD=-1) lets the buffers be reused, eliminating the churn. Runs once, |
| 46 | +// process-wide, at library load. NOTE: this retains freed memory in-process, so workloads |
| 47 | +// with large transient allocation peaks will show a higher resident set size. Use AllocTrim() |
| 48 | +// after large allocations are freed if this becomes an issue. |
| 49 | +namespace { |
| 50 | +[[maybe_unused]] const bool ofheGlibcMallocTuned = []() noexcept { |
| 51 | + mallopt(M_MMAP_MAX, 0); |
| 52 | + mallopt(M_TRIM_THRESHOLD, -1); |
| 53 | + return true; |
| 54 | +}(); |
| 55 | +} // namespace |
| 56 | +#endif |
| 57 | + |
| 58 | +// AllocTrim() asks the allocator to return free (unused) heap memory to the OS. It is the |
| 59 | +// companion to the retain-by-default malloc tuning above: call it at a quiescent point after a |
| 60 | +// large transient-footprint operation (e.g. EvalBootstrap) to reclaim peak scratch memory. |
| 61 | +// |
| 62 | +// WARNING: this is a performance / RSS tool, NOT a security primitive. It does not erase data -- |
| 63 | +// it only releases already-free chunks (the bytes are not scrubbed; the kernel zero-fills pages |
| 64 | +// only when they are next handed out). To wipe sensitive data (keys, plaintext, noise) use |
| 65 | +// secure_memset() before freeing. |
| 66 | +// |
| 67 | +// Not async-signal-safe and acquires allocator locks; call only from normal execution context, |
| 68 | +// never from a signal handler. Returns true if a trim was attempted, false on unsupported builds. |
| 69 | +bool AllocTrim() { |
| 70 | +#if defined(__GLIBC__) |
| 71 | + malloc_trim(0); |
| 72 | + return true; |
| 73 | +#else |
| 74 | + return false; |
| 75 | +#endif |
| 76 | +} |
| 77 | + |
35 | 78 | void secure_memset(volatile void* mem, uint8_t c, size_t len) { |
36 | 79 | volatile uint8_t* ptr = (volatile uint8_t*)mem; |
37 | 80 | for (size_t i = 0; i < len; ++i) |
|
0 commit comments