FileVisibility stores full entity objects, causing memory accumulation
>>> [!note] Migrated issue
<!-- Drupal.org comment -->
<!-- Migrated from issue #3583772. -->
Reported by: [herved](https://www.drupal.org/user/2197136)
Related to !15
>>>
<h3 id="summary-problem-motivation">Problem/Motivation</h3>
<p>FileVisibility::updateFilesVisibility() queues full entity objects in $entities[] for deferred processing via KernelEvents::RESPONSE. In long-lived processes (Drush, Behat, cron,...), these objects accumulate over the entire process lifetime, consuming significant memory since they are not garbage collected.<br>
For historical context, the defer was introduced in <span class="drupalorg-gitlab-issue-link drupalorg-gitlab-link-wrapper"><a href="https://git.drupalcode.org/project/file_visibility/-/work_items/3536831" class="drupalorg-gitlab-link">https://git.drupalcode.org/project/file_visibility/-/work_items/3536831</a></span>.</p>
<p>track_usage's Recorder service, which has the same deferred processing pattern, already handles this correctly by storing lightweight identifiers (entity type, ID, revision) instead of full objects.</p>
<h4 id="summary-steps-reproduce">Steps to reproduce</h4>
<p>1. Fresh Drupal install</p>
<pre>ddev drush si standard -y<br>ddev drush en file_visibility_track_usage -y</pre><p>2. Create a TrackConfig and point file_visibility_track_usage at it.</p>
<pre>ddev drush php:eval "<br> \Drupal\track_usage\Entity\TrackConfig::create([<br> 'id' => 'file_visibility',<br> 'label' => 'File Visibility',<br> 'realTimeRecording' => TRUE,<br> 'activeRevision' => FALSE,<br> 'source' => ['node' => []],<br> 'traversable' => [],<br> 'target' => ['file' => []],<br> 'status' => TRUE,<br> ])->save();<br><br> \Drupal::configFactory()<br> ->getEditable('file_visibility_track_usage.settings')<br> ->set('track_usage_config', 'file_visibility')<br> ->save();<br> echo 'Done.' . PHP_EOL;<br>"</pre><p>3. Save the following script below as memory_hog.php.</p>
<pre><?php<br><br>gc_collect_cycles();<br>$before = memory_get_usage(FALSE);<br><br>$storage = \Drupal::entityTypeManager()->getStorage('node');<br>for ($i = 0; $i < 1000; $i++) {<br> $node = \Drupal\node\Entity\Node::create([<br> 'type' => 'page',<br> 'title' => 'memtest_' . $i,<br> 'status' => 1,<br> 'uid' => 1,<br> ]);<br> $node->save();<br> $storage->delete([$node]);<br>}<br><br>gc_collect_cycles();<br>$after = memory_get_usage(FALSE);<br><br>printf("before: %.1f MB\n", $before / 1048576);<br>printf("after: %.1f MB\n", $after / 1048576);<br>printf("delta: %.1f MB\n", ($after - $before) / 1048576);</pre><p>4. Execute it<br>
<code>ddev drush php:script memory_hog.php</code></p>
<p>Notice the memory consumption is high, on my machine:</p>
<pre>before: 8.5 MB<br>after: 58.3 MB<br>delta: 49.8 MB</pre><p>After provided fix:</p>
<pre>before: 8.5 MB<br>after: 13.3 MB<br>delta: 4.8 MB</pre><h3 id="summary-proposed-resolution">Proposed resolution</h3>
<p>Store entity type/ID/revision in FileVisibility::$entities instead of full entity objects, consistent with track_usage's Recorder.</p>
<h3 id="summary-remaining-tasks">Remaining tasks</h3>
<p>?</p>
<h3 id="summary-ui-changes">User interface changes</h3>
<p>None</p>
<h3 id="summary-api-changes">API changes</h3>
<p>None</p>
<h3 id="summary-data-model-changes">Data model changes</h3>
<p>None</p>
issue