HaikuDepot : Faster DTO Models

This change includes some changes to the
generated DTO models between HaikuDepotServer
and HaikuDepot which should improve
performance.

Change-Id: I74c6014f8115aa0a55907a24b6115dd48d341794
Reviewed-on: https://review.haiku-os.org/c/haiku/+/7165
Reviewed-by: Jérôme Duval <jerome.duval@gmail.com>
This commit is contained in:
Andrew Lindesay 2023-11-30 08:33:45 +13:00 committed by waddlesplash
parent 255314f734
commit ba1465cc86
3 changed files with 80 additions and 49 deletions

View File

@ -29,6 +29,7 @@ CPP_TYPE_NUMBER = "double"
# The possible C++ default values
CPP_DEFAULT_STRING = "NULL"
CPP_DEFAULT_OBJECT = "NULL"
CPP_DEFAULT_ARRAY = "NULL"
CPP_DEFAULT_BOOLEAN = "false"
CPP_DEFAULT_INTEGER = "0"
CPP_DEFAULT_NUMBER = "0.0"
@ -64,6 +65,8 @@ def propmetadatatocppdefaultvalue(propmetadata):
return CPP_DEFAULT_NUMBER
if type == JSON_TYPE_OBJECT:
return CPP_DEFAULT_OBJECT
if type == JSON_TYPE_ARRAY:
return CPP_DEFAULT_ARRAY
raise Exception('unknown json-schema type [' + type + ']')
@ -176,9 +179,7 @@ def augment_schema(schema: dict[str, any]) -> None:
prop["isobject"] = JSON_TYPE_OBJECT == prop_type
prop["iscppnonscalarnoncollectiontype"] = not is_scalar_type and not is_array_type
prop["toplevelcppname"] = top_level_cpp_name
if prop_type != "array":
prop["cppdefaultvalue"] = propmetadatatocppdefaultvalue(prop)
prop["cppdefaultvalue"] = propmetadatatocppdefaultvalue(prop)
if not prop_type or 0 == len(prop_type):
raise Exception('missing "type" field')
@ -199,6 +200,11 @@ def augment_schema(schema: dict[str, any]) -> None:
def collect_referenced_class_names() -> list[str]:
result = set()
properties = obj['properties'].items()
if len(properties) > 15:
raise RuntimeError("an object has more than 15 properties"
" which is not allowed")
for _, prop in obj['properties'].items():
if prop['type'] == JSON_TYPE_ARRAY:
@ -247,6 +253,9 @@ def augment_schema(schema: dict[str, any]) -> None:
key= lambda item: item["name"]
)
for i in range(len(property_array)):
property_array[i]["cppbitmaskexpression"] = "(1 << %d)" % i
if 0 != len(property_array):
property_array[0]["isfirst"] = True
property_array[len(property_array) - 1]["islast"] = True

View File

@ -30,10 +30,13 @@ HEADER_TEMPLATE = """
{{#referencedclasscpptypes}}#include "{{.}}.h"
{{/referencedclasscpptypes}}
class {{cppname}} {
public:
{{cppname}}();
virtual ~{{cppname}}();
void Reset();
{{#propertyarray}}{{#property.iscppscalartype}}
{{property.cpptype}} {{property.cppname}}();
void Set{{property.cppname}}({{property.cpptype}} value);
@ -52,8 +55,14 @@ public:
bool {{property.cppname}}IsNull();
{{/property.iscppnonscalarnoncollectiontype}}
{{/propertyarray}}
public:
{{#propertyarray}} static const uint16 k{{property.cppname}}Bitmask;
{{/propertyarray}}
private:
{{#propertyarray}} {{property.cpptype}}* {{property.cppmembername}};
uint16 fHasValueBitmask;
{{#propertyarray}} {{property.cpptype}}{{^property.iscppscalartype}}*{{/property.iscppscalartype}} {{property.cppmembername}};
{{/propertyarray}}
};
@ -68,58 +77,67 @@ IMPLEMENTATION_TEMPLATE = """
#include "{{cppname}}.h"
{{#propertyarray}}/*static*/ const uint16 {{cppname}}::k{{property.cppname}}Bitmask = {{cppbitmaskexpression}};
{{/propertyarray}}
{{cppname}}::{{cppname}}()
:
{{#propertyarray}} {{property.cppmembername}}(NULL){{^islast}},{{/islast}}
fHasValueBitmask(0),
{{#propertyarray}} {{property.cppmembername}}({{property.cppdefaultvalue}}){{^islast}},{{/islast}}
{{/propertyarray}}{
}
{{cppname}}::~{{cppname}}()
{
{{#propertyarray}}{{^property.isarray}} delete {{property.cppmembername}};
{{/property.isarray}}{{#property.isarray}} if ({{property.cppmembername}} != NULL) {
Reset();
}
void
{{cppname}}::Reset()
{
{{#propertyarray}}{{#property.isstring}} delete {{property.cppmembername}};
{{/property.isstring}}{{#property.isobject}} delete {{property.cppmembername}};
{{/property.isobject}}{{#property.isarray}}
if ({{property.cppmembername}} != NULL) {
for (int i = {{property.cppmembername}}->CountItems() - 1; i >= 0; i--)
delete {{property.cppmembername}}->ItemAt(i);
delete {{property.cppmembername}};
}
{{/property.isarray}}
{{/propertyarray}}}
{{/property.isarray}} {{property.cppmembername}} = {{property.cppdefaultvalue}};
{{/propertyarray}}
fHasValueBitmask = 0;
}
{{#propertyarray}}{{#property.iscppscalartype}}{{property.cpptype}}
{{cppobjectname}}::{{property.cppname}}()
{
if ({{property.cppname}}IsNull())
return {{property.cppdefaultvalue}};
return *{{property.cppmembername}};
return {{property.cppmembername}};
}
void
{{cppobjectname}}::Set{{property.cppname}}({{property.cpptype}} value)
{
if ({{property.cppname}}IsNull()) {
{{property.cppmembername}} = new {{property.cpptype}}[0];
}
{{property.cppmembername}}[0] = value;
fHasValueBitmask |= k{{property.cppname}}Bitmask;
{{property.cppmembername}} = value;
}
void
{{cppobjectname}}::Set{{property.cppname}}Null()
{
if ({{property.cppname}}IsNull()) {
delete {{property.cppmembername}};
{{property.cppmembername}} = NULL;
}
fHasValueBitmask &= ~k{{property.cppname}}Bitmask;
{{property.cppmembername}} = {{property.cppdefaultvalue}};
}
bool
{{cppobjectname}}::{{property.cppname}}IsNull()
{
return {{property.cppmembername}} == NULL;
return 0 == (fHasValueBitmask & k{{property.cppname}}Bitmask);
}
{{/property.iscppscalartype}}{{#property.isarray}}void

View File

@ -200,7 +200,7 @@ public:
protected:
{{cppname}}* fTarget;
BString fNextItemName;
uint16 fNextItemBitmask;
};
class {{cppname}}_List_Stacked{{toplevelcppname}}JsonListener : public AbstractStacked{{toplevelcppname}}JsonListener {
@ -247,7 +247,7 @@ public:
bool Handle(const BJsonEvent& event);
private:
BString fNextItemName;
uint16 fNextItemIsItems;
{{toplevel.cppname}}Listener* fItemListener;
};
@ -491,7 +491,10 @@ bool
HandleError(B_NOT_ALLOWED, JSON_EVENT_LISTENER_ANY_LINE, "illegal state - unexpected start of array");
break;
case B_JSON_OBJECT_NAME:
fNextItemName = event.Content();
fNextItemBitmask = 0;
{{#propertyarray}} if (0 == strcmp(event.Content(), "{{name}}"))
fNextItemBitmask = {{cppobjectname}}::k{{property.cppname}}Bitmask;
{{/propertyarray}}
break;
case B_JSON_OBJECT_END:
{
@ -501,53 +504,52 @@ bool
}
case B_JSON_STRING:
{
{{#propertyarray}} {{#property.isstring}}
if (fNextItemName == "{{name}}")
{{#propertyarray}} {{#property.isstring}} if (fNextItemBitmask == {{cppobjectname}}::k{{property.cppname}}Bitmask)
fTarget->Set{{property.cppname}}(new BString(event.Content()));
{{/property.isstring}}{{/propertyarray}}
fNextItemName.SetTo("");
fNextItemBitmask = 0;
break;
}
case B_JSON_TRUE:
{{#propertyarray}}{{#property.isboolean}} if (fNextItemName == "{{name}}")
{{#propertyarray}}{{#property.isboolean}} if (fNextItemBitmask == {{cppobjectname}}::k{{property.cppname}}Bitmask)
fTarget->Set{{property.cppname}}(true);
{{/property.isboolean}}{{/propertyarray}}
fNextItemName.SetTo("");
fNextItemBitmask = 0;
break;
case B_JSON_FALSE:
{{#propertyarray}}{{#property.isboolean}} if (fNextItemName == "{{name}}")
{{#propertyarray}}{{#property.isboolean}} if (fNextItemBitmask == {{cppobjectname}}::k{{property.cppname}}Bitmask)
fTarget->Set{{property.cppname}}(false);
{{/property.isboolean}}
{{/propertyarray}}
fNextItemName.SetTo("");
fNextItemBitmask = 0;
break;
case B_JSON_NULL:
{
{{#propertyarray}}{{^property.isarray}} if (fNextItemName == "{{name}}")
{{#propertyarray}}{{^property.isarray}} if (fNextItemBitmask == {{cppobjectname}}::k{{property.cppname}}Bitmask)
fTarget->Set{{property.cppname}}Null();
{{/property.isarray}}{{/propertyarray}}
fNextItemName.SetTo("");
fNextItemBitmask = 0;
break;
}
}
case B_JSON_NUMBER:
{
{{#propertyarray}}{{#property.isinteger}} if (fNextItemName == "{{name}}")
{{#propertyarray}}{{#property.isinteger}} if (fNextItemBitmask == {{cppobjectname}}::k{{property.cppname}}Bitmask)
fTarget->Set{{property.cppname}}(event.ContentInteger());
{{/property.isinteger}}
{{#property.isnumber}} if (fNextItemName == "{{name}}")
{{#property.isnumber}} if (fNextItemBitmask == {{cppobjectname}}::k{{property.cppname}}Bitmask)
fTarget->Set{{property.cppname}}(event.ContentDouble());
{{/property.isnumber}}
{{/propertyarray}}
fNextItemName.SetTo("");
fNextItemBitmask = 0;
break;
}
case B_JSON_OBJECT_START:
{
{{#propertyarray}}{{#property.isobject}} if (fNextItemName == "{{name}}") {
{{#propertyarray}}{{#property.isobject}} if (fNextItemBitmask == {{cppobjectname}}::k{{property.cppname}}Bitmask) {
GeneralObjectStacked{{toplevelcppname}}JsonListener* nextListener
= new GeneralObjectStacked{{toplevelcppname}}JsonListener(fMainListener, this);
Push(nextListener);
fNextItemName.SetTo("");
fNextItemBitmask = 0;
break;
}
{{/property.isobject}}{{/propertyarray}}
@ -556,22 +558,22 @@ bool
GeneralObjectStacked{{toplevelcppname}}JsonListener* nextListener
= new GeneralObjectStacked{{toplevelcppname}}JsonListener(fMainListener, this);
Push(nextListener);
fNextItemName.SetTo("");
fNextItemBitmask = 0;
break;
}
case B_JSON_ARRAY_START:
{
{{#propertyarray}}{{#property.isarray}} if (fNextItemName == "{{name}}") {
{{#propertyarray}}{{#property.isarray}} if (fNextItemBitmask == {{cppobjectname}}::k{{property.cppname}}Bitmask) {
{{#property.items.isstring}}
StringList{{toplevelcppname}}JsonListener* nextListener = new StringList{{toplevelcppname}}JsonListener(fMainListener, this);
fTarget->Set{{property.cppname}}(nextListener->Target());
{{/property.items.isstring}}{{^property.items.isstring}}
{{property.items.cppname}}_List_Stacked{{toplevelcppname}}JsonListener* nextListener =
new {{property.items.cppname}}_List_Stacked{{toplevelcppname}}JsonListener(fMainListener, this);
fTarget->Set{{property.cppname}}(nextListener->Target());
fTarget->Set{{property.cppname}}(nextListener->Target());
{{/property.items.isstring}}
Push(nextListener);
fNextItemName.SetTo("");
fNextItemBitmask = 0;
break;
}
{{/property.isarray}}{{/propertyarray}}
@ -580,7 +582,7 @@ bool
AbstractStacked{{toplevelcppname}}JsonListener* nextListener
= new GeneralArrayStacked{{toplevelcppname}}JsonListener(fMainListener, this);
Push(nextListener);
fNextItemName.SetTo("");
fNextItemBitmask = 0;
break;
}
}
@ -684,16 +686,17 @@ BulkContainerStacked{{toplevel.cppname}}JsonListener::Handle(const BJsonEvent& e
{
switch (event.EventType()) {
case B_JSON_ARRAY_END:
HandleError(B_NOT_ALLOWED, JSON_EVENT_LISTENER_ANY_LINE, "illegal state - unexpected start of array");
HandleError(B_NOT_ALLOWED, JSON_EVENT_LISTENER_ANY_LINE, "illegal state - unexpected end of array");
break;
case B_JSON_OBJECT_NAME:
fNextItemName = event.Content();
fNextItemIsItems = (0 == strcmp(event.Content(), "items"));
break;
case B_JSON_OBJECT_START:
Push(new GeneralObjectStacked{{toplevel.cppname}}JsonListener(fMainListener, this));
fNextItemIsItems = false;
break;
case B_JSON_ARRAY_START:
if (fNextItemName == "items")
if (fNextItemIsItems)
Push(new BulkContainerItemsStacked{{toplevel.cppname}}JsonListener(fMainListener, this, fItemListener));
else
Push(new GeneralArrayStacked{{toplevel.cppname}}JsonListener(fMainListener, this));
@ -705,7 +708,8 @@ BulkContainerStacked{{toplevel.cppname}}JsonListener::Handle(const BJsonEvent& e
return status;
}
default:
// ignore
// ignore any other fields
fNextItemIsItems = false;
break;
}