C++ versions of props.nas setValues/setChildren()
Improve performance of Nasal properties access by implementing the setValues/setChildren props.nas functions in C++. Naive implementation effectively copying the Nasal versions verbatim. However, on a test suite writing 1000 Canvas paths, results in a 50% reduction in runtime, and significant reductions in memory occupancy. On a much larger task (5500 paths) results in a 30% reduction, probably due to Nasal GC.
This commit is contained in:
parent
553212df1a
commit
386f8b87b5
1 changed files with 96 additions and 14 deletions
|
@ -299,19 +299,10 @@ T makeVecFromVector(naRef vector)
|
|||
return vec;
|
||||
}
|
||||
|
||||
|
||||
// Set the value of a node; returns true if it succeeded or
|
||||
// Helper function to set the value of a node; returns true if it succeeded or
|
||||
// false if it failed. <val> can be a string, number, or a
|
||||
// vector or numbers (for SGVec3D/4D types).
|
||||
// Forms:
|
||||
// props.Node.setValue(string relative_path,
|
||||
// val);
|
||||
// props.Node.setValue(val);
|
||||
static naRef f_setValue(naContext c, naRef me, int argc, naRef* args)
|
||||
{
|
||||
NODEARG();
|
||||
MOVETARGET(naVec_size(argv) > 1, true);
|
||||
naRef val = naVec_get(argv, 0);
|
||||
static naRef f_setValueHelper(naContext c, SGPropertyNode_ptr node, naRef val) {
|
||||
bool result = false;
|
||||
if(naIsString(val)) {
|
||||
result = node->setStringValue(naStr_data(val));
|
||||
|
@ -336,6 +327,22 @@ static naRef f_setValue(naContext c, naRef me, int argc, naRef* args)
|
|||
return naNum(result);
|
||||
}
|
||||
|
||||
|
||||
// Set the value of a node; returns true if it succeeded or
|
||||
// false if it failed. <val> can be a string, number, or a
|
||||
// vector or numbers (for SGVec3D/4D types).
|
||||
// Forms:
|
||||
// props.Node.setValue(string relative_path,
|
||||
// val);
|
||||
// props.Node.setValue(val);
|
||||
static naRef f_setValue(naContext c, naRef me, int argc, naRef* args)
|
||||
{
|
||||
NODEARG();
|
||||
MOVETARGET(naVec_size(argv) > 1, true);
|
||||
naRef val = naVec_get(argv, 0);
|
||||
return f_setValueHelper(c, node, val);
|
||||
}
|
||||
|
||||
static naRef f_setIntValue(naContext c, naRef me, int argc, naRef* args)
|
||||
{
|
||||
NODEARG();
|
||||
|
@ -377,6 +384,79 @@ static naRef f_setDoubleValue(naContext c, naRef me, int argc, naRef* args)
|
|||
return naNum(node->setDoubleValue(r.num));
|
||||
}
|
||||
|
||||
// Forward declaration
|
||||
static naRef f_setChildrenHelper(naContext c, SGPropertyNode_ptr node, char* name, naRef val);
|
||||
|
||||
static naRef f_setValuesHelper(naContext c, SGPropertyNode_ptr node, naRef hash)
|
||||
{
|
||||
if (!naIsHash(hash)) {
|
||||
naRuntimeError(c, "props.setValues() with non-hash");
|
||||
}
|
||||
|
||||
naRef keyvec = naNewVector(c);
|
||||
naHash_keys(keyvec, hash);
|
||||
naRef ret;
|
||||
|
||||
for (int i = 0; i < naVec_size(keyvec); i++) {
|
||||
naRef key = naVec_get(keyvec, i);
|
||||
if (! naIsScalar(key)) {
|
||||
naRuntimeError(c, "props.setValues() with non-scalar key value");
|
||||
}
|
||||
char* keystr = naStr_data(naStringValue(c, key));
|
||||
ret = f_setChildrenHelper(c, node, keystr, naHash_cget(hash, keystr));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static naRef f_setValues(naContext c, naRef me, int argc, naRef* args)
|
||||
{
|
||||
NODEARG();
|
||||
MOVETARGET(naVec_size(argv) > 1, true);
|
||||
naRef val = naVec_get(argv, 0);
|
||||
return f_setValuesHelper(c, node, val);
|
||||
}
|
||||
|
||||
static naRef f_setChildrenHelper(naContext c, SGPropertyNode_ptr node, char* name, naRef val)
|
||||
{
|
||||
naRef ret;
|
||||
try {
|
||||
SGPropertyNode_ptr subnode = node->getNode(name, true);
|
||||
|
||||
if (naIsScalar(val)) {
|
||||
ret = f_setValueHelper(c, subnode, val);
|
||||
} else if (naIsHash(val)) {
|
||||
ret = f_setValuesHelper(c, subnode, val);
|
||||
} else if (naIsVector(val)) {
|
||||
for (int i = 0; i < naVec_size(val); i++) {
|
||||
char newname[sizeof(name) + 3];
|
||||
sprintf(newname, "%s[%i]", name, i);
|
||||
ret = f_setChildrenHelper(c, node, newname, naVec_get(val, i));
|
||||
}
|
||||
} else if (naIsNil(val)) {
|
||||
// Nil value OK - no-op
|
||||
} else {
|
||||
naRuntimeError(c, "props.setChildren() with unknown type");
|
||||
}
|
||||
} catch(const string& err) {
|
||||
naRuntimeError(c, (char *)err.c_str());
|
||||
return naNil();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static naRef f_setChildren(naContext c, naRef me, int argc, naRef* args)
|
||||
{
|
||||
NODEARG();
|
||||
if(! naIsString(naVec_get(argv, 0))) {
|
||||
naRuntimeError(c, "props.setChildren() with non-string first argument");
|
||||
}
|
||||
|
||||
char* name = naStr_data(naVec_get(argv, 0));
|
||||
naRef val = naVec_get(argv, 1);
|
||||
return f_setChildrenHelper(c, node, name, val);
|
||||
}
|
||||
|
||||
// Get the parent of this node as a ghost.
|
||||
// Forms:
|
||||
|
@ -681,6 +761,7 @@ static struct {
|
|||
{ f_equals, "_equals" },
|
||||
{ f_getValue, "_getValue" },
|
||||
{ f_setValue, "_setValue" },
|
||||
{ f_setValues, "_setValues" },
|
||||
{ f_setIntValue, "_setIntValue" },
|
||||
{ f_setBoolValue, "_setBoolValue" },
|
||||
{ f_setDoubleValue, "_setDoubleValue" },
|
||||
|
@ -692,6 +773,7 @@ static struct {
|
|||
{ f_removeChild, "_removeChild" },
|
||||
{ f_removeChildren, "_removeChildren" },
|
||||
{ f_removeAllChildren, "_removeAllChildren" },
|
||||
{ f_setChildren, "_setChildren" },
|
||||
{ f_alias, "_alias" },
|
||||
{ f_unalias, "_unalias" },
|
||||
{ f_getAliasTarget, "_getAliasTarget" },
|
||||
|
|
Loading…
Add table
Reference in a new issue