Opened 7 years ago
Last modified 4 months ago
#40988 assigned enhancement
Use objects for `get_item_schema()` calls
Reported by: | schlessera | Owned by: | pbearne |
---|---|---|---|
Milestone: | Awaiting Review | Priority: | normal |
Severity: | normal | Version: | 4.7 |
Component: | REST API | Keywords: | |
Focuses: | rest-api, performance | Cc: |
Description
The get_item_schema()
method of a REST API controller always returns a dynamically generated array of schema information. This dynamic nature is needed, because some keys/values can change based on the current environment/controller.
This incurs a large performance penalty because the arrays need to be set up again and again, and as a side-effect, the translations that are being used for the 'description'
field are being loaded every single time. On a fresh, empty install of WordPress 4.8, making a request to GET /wp-json/wpv2/posts
can spend a third or more of its time translating strings. Most of these translations are done multiple times, every single time an item schema is being requested. See blackfire profiling run here: https://blackfire.io/profiles/20516863-50e3-4df2-938a-7fa2f462abc8/graph
I suggest turning the arrays that get_item_schema()
returns into a collection of smart objects that implement ArrayAccess
. This offers the following benefits:
- Objects use up the memory for their keys once.
- Objects can be cloned (with the possibility to make changes after the clone), making sure that translations will at the most be loaded only once for every individual string.
- Objects can be extended and/or decorated, making it easy and clean to provide different structures for different use case, to get around
if/else
edge case handling. - Objects can provide "lazily-loaded" keys (through magic methods or the proxy pattern), allowing the descriptions to only be processed when they are actually being requested. This would avoid the translation work completely for a use case like I tested above.
I expect this to shave around 30% off of the execution time of the above test case. It also makes the code more scalable, as large response sets might even incur yet a bigger performance penalty than the one I have recorded.
Related ticket, where most of the problem has already been alleviated in a different way: #41305