Our game project ( Dustforce ) is getting larger (~35,000 lines of AngelScript ) and as a result has started to take a long time to compile ( ~19 seconds )
19 seconds isn't too bad, but being able to quickly make changes and test the results is important for gameplay programming.
So I had a quick look at where that time was getting spent.
More than half the time was spent in [font="Lucida Console"]asCScriptEngine::ParseToken[/font] which didn't really surprise me.
But the line that was spending all the time did...
if( stringLength == 0 )
stringLength = strlen(string);
I traced the source back to the script builder add-on, and there's a few places where [font="Courier New"]ParseToken[/font] is called with 0 as the length which causes the length to be calculated again for every single token...
Fixing that got my compile time down to ~9 seconds which was exciting.
Another big one was [font="Courier New"]asCTokenizer::IsKeyWord[/font][font="Arial"] which I optimised away by making a [/font][font="Courier New"]std::map<string, eTokenType>[/font][font="Arial"] from the [/font][font="Courier New"]tokenWords[/font][font="Arial"] array and searching the map for the token starting at length of the longest element and working down ( to avoid !is missing !isTrue etc ) and also replaced all the linear searches on that array where I could.[/font]
[font="Arial"]Here's my code:[/font][font="Arial"]
bool asCTokenizer::IsKeyWord()
{
int maxLength = sourceLength > 9? 9:sourceLength;
while( maxLength > 0 )
{
char test[10];
memcpy( test, source, maxLength );
test[ maxLength ] = '\0';
map<string, eTokenType>::iterator tokenI = tokenWordsMap.find( test );
if ( tokenI != tokenWordsMap.end() )
{
tokenType = tokenI->second;
tokenLength = maxLength;
return true;
}
maxLength--;
}
return false;
}
[/font]
[font="Arial"]This cut the compile time down to ~6 seconds which is pretty good.[/font]
The remaining 6 seconds doesn't look quite as easy to cut down, but a good amout of it appears to be spent in linear searches.
I understand that compile performance isn't really a priority for AngelScript at the moment, but these small changes might be useful for people with larger projects.
The ParseToken thing in CScriptBuilder should probably be fixed, I can try to work out how to submit a patch if you'd like. Otherwise I think you can just find-replace
[font="Courier New"]engine->ParseToken(&modifiedScript[pos], 0, &len);[/font]
with
[font="Courier New"]engine->ParseToken(&modifiedScript[pos], (int)modifiedScript.length() - pos, &len);[/font]
[font="Arial"]in scriptbuilder.cpp[/font]
And if anyone has any ideas on how to improve performance further, let me know!
Thanks.
-Matt