diff --git a/CHANGELOG.rst b/CHANGELOG.rst index d0562feff..77f8ec5f4 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,7 +1,8 @@ 2.1.14 (unreleased) ------------------- -- Nothing changed yet. +- Improve performance of json schema serialization + [vangheem] 2.1.13 (2017-11-29) diff --git a/guillotina/json/serialize_schema.py b/guillotina/json/serialize_schema.py index fa452d9f1..6c6ac6ecb 100644 --- a/guillotina/json/serialize_schema.py +++ b/guillotina/json/serialize_schema.py @@ -6,6 +6,7 @@ from guillotina.interfaces import IRequest from guillotina.interfaces import ISchemaFieldSerializeToJson from guillotina.interfaces import ISchemaSerializeToJson +from guillotina.profile import profilable from guillotina.schema import getFieldsInOrder from zope.interface import Interface @@ -19,6 +20,7 @@ def __init__(self, factory, request): self.factory = factory self.request = request + @profilable async def __call__(self): factory = self.factory result = { diff --git a/guillotina/json/serialize_schema_field.py b/guillotina/json/serialize_schema_field.py index 7cda7b179..bcb44f377 100644 --- a/guillotina/json/serialize_schema_field.py +++ b/guillotina/json/serialize_schema_field.py @@ -5,6 +5,7 @@ from guillotina.interfaces import ISchemaFieldSerializeToJson from guillotina.interfaces import ISchemaSerializeToJson from guillotina.json.serialize_value import json_compatible +from guillotina.profile import profilable from guillotina.schema import getFields from guillotina.schema.interfaces import IBool from guillotina.schema.interfaces import IChoice @@ -24,6 +25,9 @@ from zope.interface import Interface +FIELDS_CACHE = {} + + @configure.adapter( for_=(IField, Interface, Interface), provides=ISchemaFieldSerializeToJson) @@ -49,14 +53,20 @@ def __init__(self, field, schema, request): self.field = field self.schema = schema self.request = request - self.field_attributes = {} + @profilable async def __call__(self): result = {'type': self.field_type} - for schema in implementedBy(self.field.__class__).flattened(): - self.field_attributes.update(getFields(schema)) - for attribute_name in sorted(self.field_attributes.keys()): - attribute_field = self.field_attributes[attribute_name] + # caching the field_attributes here improves performance dramatically + if self.field.__class__ in FIELDS_CACHE: + field_attributes = FIELDS_CACHE[self.field.__class__].copy() + else: + field_attributes = {} + for schema in implementedBy(self.field.__class__).flattened(): + field_attributes.update(getFields(schema)) + FIELDS_CACHE[self.field.__class__] = field_attributes + for attribute_name in sorted(field_attributes.keys()): + attribute_field = field_attributes[attribute_name] if attribute_name in self.filtered_attributes: continue