Problem/Motivation
When enabling a search index via CLI using drush using search api command or a features-import, the allowed memory size is being reached because all content entities are being loaded (and cached) at once.
Here is the general error and attached is the stack trace
PHP Fatal error: Allowed memory size of 1073741824 bytes exhausted (tried to allocate 20480 bytes) in ../core/lib/Drupal/Core/Entity/ContentEntityBase.php on line 207
Proposed resolution
Breakup the indexing of content entities into smaller chunks and reset the content entity storage cache after each chunk is indexed.
Remaining tasks
- Determine how many entities should be indexed per chunk.
- Maybe make chunk size configurable.
User interface changes
N/A
API changes
N/A
Data model changes
N/A
| Comment | File | Size | Author |
|---|---|---|---|
| #5 | 2907518-5--fix_index_tracking_in_cli.patch | 11.51 KB | drunken monkey |
Comments
Comment #2
jrockowitz commentedComment #3
drunken monkeyThis should already work, we have batching already implemented for this case, just on a higher layer. (That's the
$pagebeing passed to that method.)(Also, this is not indexing, but tracking.)
Could you find out the exact backtrace of the call to that method, if it really does get
$page = NULLpassed? If it does get a page number, the only thing that could go wrong is you having the tracking batch size (search_api.settings:tracking_page_sizeconfig value) set too high for your site.Comment #4
jrockowitz commentedMy specific issue is that the indexing is happening via CLI which triggers every entity to be loaded and no batch processing is being triggered.
Below is the code where I saw CLI processing triggering every entity being indexed at once.
FROM: http://cgit.drupalcode.org/search_api/tree/src/Entity/Index.php#n1329
I think I might be the first person to have this problem because I am enabling the Search API on existing website with 40,000+ nodes. Most websites probably have already enabled Search API and then they start adding their nodes.
Comment #5
drunken monkeyAgain, it's "tracking", not "indexing".
In any case, though, your problem description makes sense. Indeed, if running in the CLI, after saving an index the module will try to get the complete set of items already tracked right away. This was implemented in #2624424: Indexes enabled with drush aren't tracked, since it seems Drush doesn't automatically execute batches we set. (If we could manually make Drush execute the batch, that would probably be the best solution. But I don't think we can/should call
drush_backend_batch_process()right in the middle of the post-save phase. Maybe with a shutdown hook – might that work?)However, while it does currently try to load all entities in one request/process, it will already do so in batches, not load them all at once. That means that most of your patch (the whole "chunks" code) is unnecessary, we simply need to clear the static cache after loading the entities:
However, the attached patch is much more massive, since I also took the opportunity of refactoring the
php_sapi_name() === 'cli'check (which is used quite a bit throughout our code) to a helper method on theUtilityclass. But the effective portion of the patch is just the above.Please try out whether this also resolves your problem!
And, to anyone that wants to review: Do you think the new method makes sense like this? It would actually have been great to somehow make it dependency-injectable (is that a word), i.e., an instance method on some service, so it can be mocked in tests (e.g., to really test CLI compliance in the
CliTest, not some state setting). However, I don't really think that would make any sense from any other point of view, so it seemed like a bit much just for the sake of slighlty better tests. This way, it's really just as simple to use as the previous code, just a bit more … "clean"?Anyways, I'd be glad for others' opinions on this!
Comment #6
borisson_I think this is a good idea. While it's not easy to mock this from a test it does make sense to extract this code, it makes it easier in the other code to get the actual meaning.
In any case, this patch looks solid from just a review but I haven't manually tested it yet.
Comment #7
jrockowitz commentedI have manually tested the patch via CLI and setting up the initial tracking of 30,000+ nodes worked fine.
The patch makes complete sense to me.
Marking this as RTBC.
Thanks
Comment #9
drunken monkeyThanks a lot for testing, good to hear it works!
Also thanks for your review, Joris, of course!
Committed.