3

I am using code similar to the following one.

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;
}

Every time a loop is completed, the used memory is increased. For example, after the first loop, the used memory is 110 MB, and after the third loop is 230 MB.

How do I avoid the used memory keep increasing?

  • Welcome to Drupal Answers! What you describe is a task for Dupal's Batch API. Implementing it you'd pass the node one after the other to a dedicated process to avoid running out of memory. – leymannx Oct 26 at 13:58
  • @leymannx You should add that as an alternate answer. – mpdonadio Oct 28 at 22:46
2

It happens because node_load(), as every Drupal function that loads entities from the database, stores in memory the loaded entity. If you want to avoid that happens, you can use code similar to the following one.

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);
}

The last argument of entity_load() is telling Drupal not to store in memory cache the previously loaded entity.

This is what happens with the default entity controller implemented from Drupal, DrupalDefaultEntityController, which uses the following code for DrupalDefaultEntityController::resetCache().

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.