function UserFieldValueTest::testMemoryProfile

Same name and namespace in other branches
  1. 11.x core/modules/user/tests/src/Kernel/UserFieldValueTest.php \Drupal\Tests\user\Kernel\UserFieldValueTest::testMemoryProfile()

Profiles memory usage of getFieldValue() vs typed data field access.

Not a pass/fail test — reports measurements to help developers understand the memory characteristics of each access path. Run with --display-notices or check test output for the report.

Example output (PHP 8.5, SQLite): Entity load: ~23KB, getFieldValue: ~280 bytes, get()->value: ~4KB Batch with resetCache: 0 bytes growth for both paths.

File

core/modules/user/tests/src/Kernel/UserFieldValueTest.php, line 102

Class

UserFieldValueTest
Tests fast scalar field access on the user entity.

Namespace

Drupal\Tests\user\Kernel

Code

public function testMemoryProfile() : void {
  $storage = \Drupal::entityTypeManager()->getStorage('user');
  for ($i = 0; $i < 10; $i++) {
    $this->createUserEntity([
      'name' => "profiler{$i}",
      'mail' => "profiler{$i}@example.com",
    ]);
  }
  $storage->resetCache();
  gc_collect_cycles();
  $uids = array_values($storage->getQuery()
    ->accessCheck(FALSE)
    ->execute());
  $uid = $uids[1];
  // Measure single entity.
  gc_collect_cycles();
  $before = memory_get_usage();
  $account = $storage->load($uid);
  $after_load = memory_get_usage();
  $account->getAccountName();
  $after_trait = memory_get_usage();
  $account->get('mail')->value;
  $after_typed = memory_get_usage();
  $storage->resetCache([
    $uid,
  ]);
  unset($account);
  gc_collect_cycles();
  $after_cleanup = memory_get_usage();
  // Measure batch — trait path.
  gc_collect_cycles();
  $b1 = memory_get_usage();
  foreach ($uids as $u) {
    $a = $storage->load($u);
    $a->getAccountName();
    $a->isActive();
    $a->getTimeZone();
    $storage->resetCache([
      $u,
    ]);
  }
  unset($a);
  gc_collect_cycles();
  $a1 = memory_get_usage();
  // Measure batch — typed data path.
  gc_collect_cycles();
  $b2 = memory_get_usage();
  foreach ($uids as $u) {
    $a = $storage->load($u);
    $a->get('name')->value;
    $a->get('status')->value;
    $a->get('timezone')->value;
    $storage->resetCache([
      $u,
    ]);
  }
  unset($a);
  gc_collect_cycles();
  $a2 = memory_get_usage();
  $report = sprintf("Memory profile (PHP %s):\n" . "  Entity load:         %d bytes\n" . "  getFieldValue:       %d bytes\n" . "  get()->value:        %d bytes\n" . "  After cleanup:       %d bytes residual\n" . "  Batch trait (%d):    %d bytes growth\n" . "  Batch typed (%d):    %d bytes growth", PHP_VERSION, $after_load - $before, $after_trait - $after_load, $after_typed - $after_trait, $after_cleanup - $before, count($uids), $a1 - $b1, count($uids), $a2 - $b2);
  // Report via notice so it shows with --display-notices.
  trigger_error($report, E_USER_NOTICE);
  $this->addToAssertionCount(1);
}

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.