FastMM5 Memory Manager

repository·master·Indexed 43 days ago

https://github.com/pleriche/fastmm5

A high-performance replacement memory manager for Embarcadero Delphi applications. FastMM5 is designed for multithreaded scaling, low fragmentation, and runtime configurability, featuring support for shared memory between modules, debug mode for memory corruption detection, and profiling tools like FastMM_SamplingProfiler and FastMM_SnapshotDiff.

Tokens
3.5K
Snippets
7
Records
13
Agent score
6%

What's inside FastMM5

  1. Share the memory manager between modules

    master

    When memory allocated in one module (e.g., a DLL) is freed in another (e.g., the main application), you must ensure they share the same memory manager instance. Use the following functions:

    • FastMM_ShareMemoryManager: Shares the memory manager instance of the current module with other modules.
    • FastMM_AttemptToUseSharedMemoryManager: Switches the current module to use the memory manager of another module already in the process.
  2. Guidelines for writing new FastMM5 tests

    master

    When developing new tests for the FastMM5 suite, keep the following technical constraints in mind:

    1. Small Block Corruption Observability

    Corrupting a freed small block is not observable via the scanner. Because the block resides in the debug free queue, it is a candidate for the next allocation of that size. When the scanner detects the corruption, it raises an exception. However, raising an exception requires an allocation, which may hand out the very block being tested. This causes a secondary corruption detection while an exception is already in flight, crashing the process before the test can report the result. Workaround: Use medium or large blocks for testing freed block corruption.

    2. Size Class Coverage

    A corruption test using a large block does not prove that small blocks are protected. The internal walking mechanism treats the three size classes (small, medium, large) differently. Requirement: Every corruption test must run across all three size classes to ensure full coverage.

  3. Install and use FastMM5 in a Delphi project

    master

    To use FastMM5, add FastMM5.pas as the first unit in your project's .DPR file. It will automatically install itself during application startup and replace the default Delphi memory manager.

    If you need to control when FastMM is installed (rather than automatic startup installation), define FastMM_DisableAutomaticInstall in your conditional defines. In this case, you must manually call FastMM_Initialize very early in the unit initialization sequence (ideally in the first or second unit of your .DPR) and call FastMM_Finalize to uninstall it and perform leak checks.

    // Standard automatic installationegin
    program MyProject;
    uses
      FastMM5, // Must be the first unit
      Forms, 
      Unit1 in 'Unit1.pas' if not debug;
    begin
      Application.Initialize;
      Application.CreateForm(TForm1, Form1);
      Application.Run;
    end.
  4. Run the FastMM5 test suite

    master

    The FastMM5 test suite consists of standalone console applications that exit with 0 if all checks pass, or the number of failed checks otherwise. You can run the suite using the RunTests.ps1 PowerShell script. By default, the script uses the newest Delphi installation found in the registry or via the %EmbarcaderoRoot% environment variable.

    PowerShell Script Commands

    Use the following commands to control the test execution:

    • Run newest compiler (Win32/Win64): pwsh -File RunTests.ps1
    • Run all discovered installations: pwsh -File RunTests.ps1 -AllCompilers
    • Run a specific installation: pwsh -File RunTests.ps1 -Only <Version> (e.g., 23.0)
    • Run on a specific platform: pwsh -File RunTests.ps1 -Platforms <Platform> (e.g., Win32)
    • Run quick stress tests: pwsh -File RunTests.ps1 -Quick
    • Enable verbose output: pwsh -File RunTests.ps1 -VerboseOutput
    • List discovered compilers without running tests: pwsh -File RunTests.ps1 -ListCompilers
    # Run newest installed compiler, Win32 and Win64
    pwsh -File RunTests.ps1
    
    # Run every installation that was found
    pwsh -File RunTests.ps1 -AllCompilers
    
    # Run one specific installation
    pwsh -File RunTests.ps1 -Only 23.0
    
    # Run one platform only
    pwsh -File RunTests.ps1 -Platforms Win32
    
    # Shorter stress runs
    pwsh -File RunTests.ps1 -Quick
    
    # Print the full output of every test
    pwsh -File RunTests.ps1 -VerboseOutput
    
    # Only report what was found, run nothing
    pwsh -File RunTests.ps1 -ListCompilers
  5. Configure custom compiler paths via CompilerPaths.txt

    master

    If you need to pin specific Delphi installation locations, use a file named CompilerPaths.txt placed in the same directory as the RunTests.ps1 script. This is useful for machines where the registry cannot be read or when you want to run tests against a specific set of versions.

    Each line should contain one installation root. You can optionally provide a name using the format Name = Path. The name is used by the -Only flag in the PowerShell script. If no name is provided, the folder name is used.

    Note: This file is ignored by .gitignore to prevent local configurations from being committed.

    # One Delphi installation root per line, optionally "Name = Path".
    # The name is what -Only matches; without one the folder name is used.
    Athens  = C:\Program Files (x86)\Embarcadero\Studio\23.0
    %ProgramFiles(x86)%\Embarcadero\Studio\22.0
  6. Use FastMM5 Profiling Tools

    master

    The following optional units can be added to your project to gain deeper insights without affecting the core memory manager:

    • FastMM_SamplingProfiler.pas: Runs a low-priority background thread that periodically samples memory state and writes time-series data to a CSV file. This is useful for tracking memory growth and fragmentation trends over time.
    • FastMM_SnapshotDiff.pas: Captures point-in-time snapshots of live allocations and compares them. This helps identify which classes or data types are causing memory growth between two specific points in time.
  7. Configure event logging (errors, leaks, etc.)

    master

    FastMM5 allows you to route event notifications (like memory leaks or errors) to the debugger, a log file, the screen, or a combination.

    Control routing via these variables:

    • FastMM_LogToFileEvents: Route to a log file.
    • FastMM_MessageBoxEvents: Route to a message box.
    • FastMM_OutputDebugStringEvents: Route to the debugger via OutputDebugString.

    To override the default log filename (which is based on the application path), use:

    • FastMM_SetEventLogFilename
  8. Build and run a single FastMM5 test manually

    master

    You can build and run an individual test program manually using dcc32. Ensure you compile from within the Tests directory so that older compilers can correctly resolve the in 'FastMM_TestUtils.pas' clause relative to the current directory.

    dcc32 -B -U..;<lib\win32\release> -NSSystem;System.Win;Winapi;Vcl FastMM5Test_DebugMode.dpr
    FastMM5Test_DebugMode.exe
  9. Enable and disable Debug Mode

    master

    Debug mode provides advanced features like detecting memory corruption and usage of freed objects (by filling freed blocks with the $808080... pattern). This comes at a performance and memory cost.

    • FastMM_EnterDebugMode: Switches to debug mode ("FullDebugMode").
    • FastMM_ExitDebugMode: Returns to performance mode.

    Note: These calls can be nested. Debug mode remains active until the number of FastMM_ExitDebugMode calls matches the number of FastMM_EnterDebugMode calls.

    FastMM_EnterDebugMode;
    try
      // Perform memory intensive or risky operations
    finally,
      FastMM_ExitDebugMode;
    end;
  10. Tune the optimization strategy

    master

    You can adjust the balance between execution speed and memory efficiency at runtime using:

    • FastMM_SetOptimizationStrategy: Sets the strategy to favor performance, low memory usage, or a blend of both (default).
  11. Configure memory alignment

    master

    If your application requires specific memory alignment (8, 16, 32, or 64 bytes) for all blocks, use the following functions:

    • FastMM_EnterMinimumAddressAlignment: Requests a minimum block alignment.
    • FastMM_ExitMinimumAddressAlignment: Rescinds the prior alignment request.

    Note: Calls can be nested, and the coarsest (largest) alignment request currently in effect will take precedence.

    FastMM_EnterMinimumAddressAlignment(32);
    try
      // Code requiring 32-byte alignment
    finally,
      FastMM_ExitMinimumAddressAlignment;
    end;
  12. Reference: FastMM5 Test Programs

    master

    The following standalone console applications comprise the FastMM5 test suite. They use FastMM_TestUtils.pas for shared scaffolding, assertions, and failure counting.

    | Program | What it covers |
    |---|---||
    | `FastMM5Test_DebugMode.dpr` | Smoke test: entering and leaving debug mode, allocating, writing, reallocating and freeing in both modes, and the allocated byte count returning to its starting value. |
    | `FastMM5Test_SizeClasses.dpr` | Every size class from 1 byte to 2 MB, plus reallocations across the class boundaries, each verified by a size dependent fill pattern. |
    | `FastMM5Test_UsagePerSizeClass.dpr` | Churns each size class in turn and asserts that nothing stays allocated and that the committed address space does not keep growing from phase to phase. |
    | `FastMM5Test_ModeTransition.dpr` | The contract of the debug and erase mode switches (issue #85): the nesting counter follows the calls, not their success, even if a Begin fails. |
    | `FastMM5Test_DoubleFree.dpr` | Double free handling (issue #73): ensures the second free is rejected and leaves the pending free list intact. |
    | `FastMM5Test_ScanCoverage.dpr` | Verifies `FastMM_ScanDebugBlocksForCorruption` detects corrupted header checksums, overruns into debug footers, and writes into freed blocks for small, medium, and large blocks. |
    | `FastMM5Test_ScanRace.dpr` | Ensures a scanning thread does not report false corruption or crash while other threads churn small debug blocks. |
    | `FastMM5Test_ScanHeaderBounds.dpr` | Corrupts size fields in the debug header (`UserSize`, `StackTraceEntryCount`) to ensure the scanner produces a clean corruption report rather than an access violation. |
    | `FastMM5Test_MultiThreadStress.dpr` | Multithreaded allocation stress with optional cross-thread frees. Parameters: `Threads Iterations MaxBlockSize DebugMode CrossThreadFree`. |