web-dev-qa-db-ja.com

node_load()から使用されているメモリを解放するにはどうすればよいですか?

次のようなコードを使用しています。

for ($i = 0; $i < 1000000; $i++) {
   $nid = get_node_id($i);
   $node = node_load($nid);
   $data = [
     $node->field_1,
     $node->field_3,
     ...
   ];
   save_to_database($data);

   echo round(memory_get_usage() / 1024 / 1024, 2) . ' MB'. PHP_EOL;
}

ループが完了するたびに、使用メモリが増加します。たとえば、最初のループの後、使用されるメモリは110 MBであり、3番目のループの後は230 MBです。

使用済みメモリが増え続けるのを防ぐにはどうすればよいですか?

3
AGH

node_load()は、データベースからエンティティをロードするすべてのDrupal関数として、ロードされたエンティティをメモリに保存するために発生します。それを回避したい場合は、コードを使用できます次のようなものです。

_for ($i = 0; $i < 1000000; $i++) {
  $nid = get_node_id($i);
  $node = entity_load('node', array($nid), array(), TRUE);
  $data = [
    $node->field_1,
    $node->field_3,
  ];
  save_to_database($data);
}
_

entity_load() の最後の引数は、Drupalに以前に読み込まれたエンティティをメモリキャッシュに保存しないように指示しています。

これは、Drupalから実装されたデフォルトのエンティティコントローラ DrupalDefaultEntityController で何が起こるかです。これは DrupalDefaultEntityController::resetCache() に次のコードを使用します。

_public function resetCache(array $ids = NULL) {
  if (isset($ids)) {
    foreach ($ids as $id) {
      unset($this->entityCache[$id]);
    }
  }
  else {
    $this->entityCache = array();
  }
}
_
2
kiamlaluno