359 words, 2 min read

You've just run a long-running Artisan command and production is complaining about memory. Before reaching for Xdebug or a full profiler, there's a tool already on your machine that answers the question in one line:

/usr/bin/time -l php artisan your:command 2>&1 | grep "maximum resident"

That's it. No code changes, no instrumentation, no deployment.

Breaking it down

  • /usr/bin/time — the system binary, not the shell built-in. The full path is important: your shell likely has a time built-in that doesn't support the -l flag.
  • -l — tells it to emit detailed resource usage. On Linux, use -v instead.
  • 2>&1time writes its output to stderr, so you need to redirect it into stdout before you can pipe it.
  • | grep "maximum resident" — filters down to the one line you care about.

The output looks like this:

147922944 maximum resident set size

That number is in bytes. Divide by 1024 × 1024 and you have the peak RSS in megabytes — in this case, 141 MB. That's the high-water mark of physical RAM the process held at any one moment, and the right number to compare against memory_limit in php.ini.

Why not memory_get_peak_usage()?

PHP's own memory_get_peak_usage(true) is great when you control the code — add it at the end of handle() and you see PHP's internal allocator peak. But it only sees what PHP's memory manager tracked. The OS-level approach catches everything: the runtime itself, loaded extensions, forked child processes. For commands that spawn subprocesses or load large extensions, the two numbers can diverge meaningfully.

The OS measurement also requires no deployment — run it against production code on a staging server without touching a line.

macOS vs. Linux

Swap -l for -v on Linux. The field name also changes slightly — look for "Maximum resident set size (kbytes)" — and note the unit shift from bytes to kilobytes.

Drop the grep for more

Skip the pipe entirely and /usr/bin/time -l dumps the full resource table after your command finishes: page faults, context switches, I/O operations, wall time. Worth reading once to understand what your command is actually doing at the OS level.