Uncached IDocumentModelResolver may impact performance

Since it recently came up in a project, we (the A12 Kernel team) want to raise awareness that your implementation of IDocumentModelResolver may have performance implications for various Kernel functions.

In the above-mentioned project, creation of the document model search service took around 30ms for a large document model. Due to a lack of caching in IDocumentModelResolver.getDocumentModelSearchService, this cost was incurred every time a document value was accessed (which typically takes less than 1ms), since Kernel internally requires the IDocumentModelSearchService to create the IDocumentSearchService.

We suggest implementing both getDocumentModelById and getDocumentModelSearchService in IDocumentModelResolver with caching if possible. Not doing so may lead to unexpectedly low performance on a variety of Kernel functions that internally make use of the document model resolver.

Here’s what an implementation with caching may look like:

public class DocumentModelResolverImpl implements IDocumentModelResolver {
	private Map<String, IDocumentModel> documentModelsById = new ConcurrentHashMap<>();
	private Map<String, IDocumentModelSearchService> documentModelSearchServicesById = new ConcurrentHashMap<>();

	@Override
	public IDocumentModel getDocumentModelById(String documentModelId) {
		return documentModelsById.computeIfAbsent(documentModelId, id -> {
			// actually load the document model here
		});
	}

	@Override
	public Optional<IDocumentModelSearchService> getDocumentModelSearchService(String documentModelId) {
		return Optional.ofNullable(documentModelSearchServicesById.computeIfAbsent(documentModelId, id -> {
			return new DocumentModelServiceFactory().createDocumentModelSearchService(this.getDocumentModelById(id));
		}));
	}
}

This is a notice from the A12 kernel team to users. Thanks @stephan-virtual-tundra :wink: