如何管理PHP内存?

时间:2018-10-15 18:09:44

标签: php session memory-management memory-limit

我编写了一个一次性脚本,用于解析保存在数据库中的PDF。到目前为止,在解析2700多个文档后内存用尽之前,一切正常。

脚本的基本流程如下:

  1. 获取所有要解析的文档ID的列表,并将其保存为会话中的数组(〜155k文档)。
  2. 显示一个包含用于开始解析的按钮的页面
  3. 单击该按钮时发出AJAX请求,该请求将解析会话数组中的前50个文档

$files = $_SESSION['files'];

$ids = array();

$slice = array_slice($files, 0, 50);
$files = array_slice($files, 50, null); // remove the 50 we are parsing on this request

if(session_status() == PHP_SESSION_NONE) {
  session_start();
}
$_SESSION['files'] = $files;
session_write_close();

for($i = 0; $i < count($slice); $i++) {
  $ids[] = ":id_{$i}";
}
$ids = implode(", ", $ids);

$sql = "SELECT d.id, d.filename, d.doc_content
  FROM proj_docs d
  WHERE d.id IN ({$ids})";

$stmt = oci_parse($objConn, $sql);
for($i = 0; $i < count($slice); $i++) {
  oci_bind_by_name($stmt, ":id_{$i}", $slice[$i]);
}
oci_execute($stmt, OCI_DEFAULT);
$cnt = oci_fetch_all($stmt, $data);
oci_free_statement($stmt);

# Do the parsing..
# Output a table row..

  1. 对AJAX请求的响应通常包括脚本是否已完成解析约155k文档的状态-如果未完成,则会发出另一个AJAX请求来解析接下来的50个文档。每个请求之间存在5秒的延迟。

问题

  • 当我期望峰值内存使用率是在#1上获得所有文档ID的列表时,为什么会出现内存不足的情况,因为它包含所有可能的文档,不是几分钟后,当会话数组少容纳2700个元素时?
  • 我看到了几个与我的问题类似的问题,他们建议将内存设置为unlimited,而我根本不想这样做。其他人建议在适当的时候将我的变量设置为null,尽管我做到了,但是在解析大约2700个文档后,我仍然用光了内存。那么我应该尝试其他什么方法?

# Freeing some memory space
$batch_size = null;
$with_xfa = null;
$non_xfa = null;
$total = null;
$files = null;
$ids = null;
$slice = null;
$sql = null;
$stmt = null;
$objConn = null;
$i = null;
$data = null;
$cnt = null;
$display_class = null;
$display = null;
$even = null;
$tr_class = null;

1 个答案:

答案 0 :(得分:0)

所以我不太确定为什么,但是将我解析的文档数量从每批50减少到10似乎可以解决此问题。我现在已经超过了5,000个文档,并且脚本仍在运行。我唯一的猜测是,当我解析50个文档时,我一定会遇到很多大文件,它们占用了所有分配的内存。

更新#1

我又遇到了另一个错误,关于内存用完了8,500多个文档。我将批次进一步简化为每个5个文档,明天将看看是否可以一路解析所有内容。如果失败,我只是增加临时分配的内存。

更新#2

因此,事实证明,我内存不足的唯一原因是,我们显然有多个超过300MB的PDF文件上传到数据库。我将分配给PHP的内存增加到512MB,这似乎使我可以完成所有内容的解析。