Magento 2's Silent Memory Drain: How a Core Fix Revolutionizes Performance and Integration Tests

Unmasking Magento 2's Hidden Memory Drain

For Magento 2 developers and merchants striving for optimal performance and efficient development cycles, memory management is a constant battle. A significant insight from the Magento GitHub community highlights a critical memory leak that has been silently impacting system resources, particularly during integration testing and other long-running processes. This issue, centered around how Magento's SessionManager and Webapi\ErrorProcessor interact with PHP's shutdown functions, reveals a clever solution that dramatically reduces memory consumption.

The Core Problem: Persistent References and Memory Bloat

The root cause of this memory leak lies in the use of PHP's register_shutdown_function(). Magento's SessionManager::registerShutdown() and Webapi\ErrorProcessor::registerShutdownFunction() were registering callbacks using [$this, ...]. While seemingly innocuous, this approach creates a strong reference to the entire object (and by extension, its associated object graph, including the ObjectManager) that persists until the PHP process fully exits. PHP has no built-in mechanism to unregister these shutdown callbacks.

In a typical, short-lived web request, this behavior has minimal impact as objects would naturally live until the process ends. However, in long-running processes, such as integration test suites (especially those using @magentoAppIsolation which reinitializes the application after each test), this became a severe problem. Each new application instance would create new session and error processor objects, and their strong references would accumulate in memory, leading to a continuous drain.

Quantifying the Impact: From Gigabytes to Megabytes

The consequences of this memory leak were staggering. Measurements on a third-party module's integration suite (528 tests) on Magento 2.4.9 revealed:

  • Before the fix: Peak memory usage reached 9.07 GB, with approximately 15 MB kept per isolated test. This frequently resulted in processes running out of memory with an 8GB limit.
  • After the fix: The same 528 tests completed with a peak memory usage of just 1.77 GB, successfully passing without memory exhaustion and maintaining the same wall time.

Even core Magento classes, like Magento/Catalog/Controller/Product/CompareTest, showed a growth of 8–16 MB per test before the fix, which stabilized afterwards. This clearly indicates a widespread issue affecting the entire development ecosystem.

The Elegant Solution: Embracing WeakReference

The proposed solution is both elegant and effective: utilizing PHP's WeakReference. Instead of passing a direct strong reference to register_shutdown_function(), the callbacks now hold a WeakReference to the SessionManager and Webapi\ErrorProcessor objects. This allows the objects to be garbage collected if no other strong references to them exist. When the shutdown function eventually executes, it checks if the object referenced by the WeakReference is still alive. If it is (which is always the case in a regular request), the original shutdown logic (writeClose() and apiShutdownFunction()) executes as before. If the object has already been garbage collected (as in an isolated integration test), the callback simply does nothing.

Beyond Memory: A Cleaner Error Reporting

An additional benefit of this fix addresses a minor but annoying side effect. Previously, after a fatal error in a long-running process, the web API error JSON would be printed multiple times – once for every error processor ever created. With the WeakReference implementation, only error processors that are still actively in use at the time of the fatal error will report it, leading to much cleaner and more accurate error logs.

This core fix significantly enhances the developer experience by making integration tests more reliable and less resource-intensive. For merchants, while less direct, improved development efficiency translates to faster feature delivery and more stable Magento installations.

Start with the tools

Explore migration tools

See options, compare methods, and pick the path that fits your store.

Explore migration tools