遗留PHP系统直接将一个巨大的日志文件(~5gb)读取到内存中的变量并进行一些处理。
编辑:关于阅读5gb的内存是高度不推荐和其他建议,请相信,这必须保持不变,因为一些遗留的设计,我们不能改变。
现在,我需要通过另一个服务来处理数据,该服务每次通话最多需要1000行。
我尝试了两种方法,这两种方法都在起作用。
1-将新行字符处的整个字符串拆分为数组,然后使用array_chunk将该数组拆分为子数组,然后取每个子数组并内爆生成一个字符串。
$logFileStr; // a variable that already contains 5gb file as string
$logLines = explode(PHP_EOL, $logFileStr);
$lineGroups = array_chunk($logLines, 1000);
foreach($lineGroups as $lineGroup)
{
$linesChunk = implode(PHP_EOL, $lineGroup);
$archiveService->store($linesChunk);
}优点:它的速度很快,因为所有的东西都在内存中工作:涉及到大量的过度工作&需要大量内存
2-最初将字符串变量的内容写入本地临时文件。然后使用exec函数拆分文件。
split -l 1000 localfile 这会产生大量的文件,每行1000行。然后,我可以简单地递归地读取文件,并将每个文件作为一个字符串处理。
优点:更简单,更容易维护。
缺点:涉及磁盘I/O,速度慢,需要大量的写读开销。
我的问题是,由于我的内存中已经有了一个包含整个字符串的变量,我如何才能以可迭代的方式从该变量中读取1000行的代码块,从而避免写入磁盘或生成新的数组和重新合并开销?
发布于 2018-01-31 03:41:33
解决此问题的一种方法是使用以下步骤:
我创建了一个遵循上述步骤的示例php代码:
<?php
$str = "line1\nline2\nline3\nline4\nline5\n"; // Sample string
$max_new_lines = 2; // Max number of lines. Replace this with 1000
$str_length = strlen($str);
$new_line_count = 0;
$str_chunk = "";
$start = 0;
// Loop through every character of the string
for ($i = 0; $i < $str_length; ++$i) {
if ($str[$i] == "\n") {
++$new_line_count;
// If we reached the max number of newlines, extract the substring
if (($new_line_count % $max_new_lines) == 0) {
$str_chunk = substr($str, $start, $i - $start);
$start = $i + 1;
// echo "\n\nchunk:\n" . $str_chunk;
}
}
}
// Extract the remaining lines
$str_chunk = substr($str, $start, $i - $start);
// echo "\n\nchunk:\n" . $str_chunk;https://stackoverflow.com/questions/48533450
复制相似问题