Repository navigation
perf: stream the slow query log during import to fix the 10GB memory footprint - #47
Merged
Merged
Conversation
…ll into memory import_logfile() read the entire log into a PHP array with file(), so a multi-gigabyte slow query log cost many times its own size in array overhead (a ~1.6GB log pushed the importer past 10GB RSS). Stream it a line at a time with fgets() instead; detail rows are already flushed to plugin_slowlog_details in SLOWLOG_IMPORT_BATCH_SIZE batches as parsing proceeds, so nothing accumulates in memory.
Contributor
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Stream read errors can silently produce partial imports marked as successful.
Review effort: Balanced
Findings: 1
What changed in this PR
Streams slow-query logs during import to avoid whole-file memory usage.
Changes:
- Replaces
file()withfopen()/fgets()streaming. - Documents the performance improvement.
| File | Description |
|---|---|
includes/slowlog_functions.php |
Streams log parsing line by line. |
CHANGELOG.md |
Records the memory optimization. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
fgets() returns false for both EOF and a read error, so a mid-file I/O failure was treated as a clean end-of-log: the partial import was finalized and post-processing started on a truncated log. Check feof() before closing the handle and route a failed read through the import-failure path (status 3) instead of finalizing the parent record.
browniebraun
previously approved these changes
Oct 1, 2026
xmacan
previously approved these changes
Oct 1, 2026
cigamit
approved these changes
Oct 1, 2026
This file contains hidden or 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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Summary
Addresses the import memory blow-up (problem #1): a ~1.6GB slow query log (~1M queries) pushed the importer past 10GB RSS.
Root cause
import_logfile()read the entire log into a PHP array up front withfile($logfile). For a multi-gigabyte log that costs many times the file's own size in PHP array/string overhead — hence >10GB for a 1.6GB log.Fix
Stream the log a line at a time with
fgets()instead. This is a clean fit because the detail rows are already flushed toplugin_slowlog_detailsinSLOWLOG_IMPORT_BATCH_SIZE(1000-row) batches as parsing proceeds — so once the whole-file slurp is removed, nothing accumulates in memory and RSS stays flat regardless of log size. (This is the "insert as you go" item.)file($logfile)→fopen()+while (($l = fgets($fh)) !== false), withfclose()after the loop.Validation
php -lclean.tests/Integration/ImportLogfileParsingTest.phpdrivesimport_logfile()against a real temp-file log and asserts the generatedINSERTSQL; streaming produces byte-identical output, so it stays green.2.6section; no version bump (per request).Not in this PR (proposed follow-up)
Your other points — de-normalizing
plugin_slowlog_details_methodsfrommethodidto amethodvarchar (and dropping theplugin_slowlog_methods/plugin_slowlog_tablesdictionary-table usage), and restructuring theSELECT DISTINCT sld.*details query — are a larger schema + query change that rewrites ~6 Pest tests under the 100%-patch-coverage gate and needs a clean install to drop the old tables. I kept this PR to the memory fix (the most severe, blocking issue) so it lands cleanly; happy to do the de-normalization as a focused follow-up PR next.