Make WordPress Core

Opened 2 years ago

Last modified 18 months ago

#40988 new enhancement

Use objects for `get_item_schema()` calls

Reported by: schlessera Owned by:
Milestone: Awaiting Review Priority: normal
Severity: normal Version: 4.7
Component: REST API Keywords:
Focuses: rest-api, performance Cc:


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.

Change History (4)

This ticket was mentioned in Slack in #core-bootstrap by schlessera. View the logs.

2 years ago

This ticket was mentioned in Slack in #core-i18n by rmccue. View the logs.

23 months ago

#3 @schlessera
23 months ago

Related ticket, where most of the problem has already been alleviated in a different way: #41305

Last edited 20 months ago by SergeyBiryukov (previous) (diff)

#4 @joehoyle
18 months ago

I think an easy implementation here would be to just use either a static variable, or an instance var as a cache, as once a class is instantiated, it shouldn't ever need to change the return of get_item_schema.

Note: See TracTickets for help on using tickets.