Counting errors in a large log within a time budget
Write numberOfErrors($errorCode) that counts lines in a large log.txt whose second ;-separated field equals $errorCode. The file is too big to load into memory, and the scan must stop after a 100 ms wall-clock budget.
<?php
class LogController {
public function numberOfErrors(int $errorCode): Response {
// your code here
}
}
Write the implementation.
Stream the file line by line with fgets in a loop, so memory stays constant regardless of file size. For each line explode(';', ...) and compare the field to $errorCode. Track elapsed time with microtime(true) and break once it exceeds 100 ms. Crucially fclose the handle (the reference snippet leaks it), and note the budget yields a partial count.
- ✗Loading the whole file (
file,file_get_contents) instead of streaming, blowing memory - ✗Forgetting
fclose, leaking the file handle (the reference snippet has this flaw) - ✗Treating the time-budgeted partial count as a complete count of all matches
- →Why is
fgetsconstant-memory whilefile()is proportional to file size? - →How would you make the partial result honest — return a flag saying the scan was cut off?
A large file must not be loaded whole — file() and file_get_contents() hold the entire volume in memory. Streaming with fgets reads one line at a time, so memory usage stays constant.
<?php
public function numberOfErrors(int $errorCode): Response {
$startAt = microtime(true);
$f = fopen('/log.txt', 'rb');
$count = 0;
while (($line = fgets($f)) !== false) {
$parts = explode(';', $line);
if (isset($parts[1]) && (int) $parts[1] === $errorCode) {
$count++;
}
if ((microtime(true) - $startAt) * 1000 > 100) {
break;
}
}
fclose($f); // the reference forgets this — the handle leaks
return new Response(json_encode(['found_errors' => $count]), 200);
}
Two honest points in the interview: the original snippet does not close the handle (fclose), and the time cut-off makes the result partial — it is worth returning a flag that the scan was interrupted.