Advertisement

QtScript vs AngelScript

Started by September 20, 2014 07:22 PM
17 comments, last by WitchLord 9 years, 7 months ago

On a high level, that is exactly the idea on how to make the element access without a function call.

The difficult part is on how to do this without making hard-coded assumptions on the layout of the registered array type. I don't want to make a solution that would only work if you implement the array type precisely like the CScriptArray. :)

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game


assumptions on the layout of the registered array type

I was going to say that an array is, by definition, a contiguous buffer... but I suppose you could be thinking of something like a ring vector/circular buffer, where the given index is a logical one and needs to be transformed by some logic?

If you maintain the existing functionality and only apply the optimization when the type has explicitly stated (via a binding function call) that it has/desires this behavior, shouldn't that be OK?

Advertisement

Of course. I'm not going to remove the existing opIndex method call. The direct access would only be an alternative way of providing the access to elements through the index operator.

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

Probably I'll do something similar to what I did for supporting initialization lists, i.e. provide a sort of meta-language for explaining to the compiler how to access elements. Perhaps something like this:


// dynamic templated array (e.g. CScriptArray)
engine->RegisterObjectIndexOp("array<T>", "length=offset(8),uint;element=offset(16),deref,sizeof(T),T");
 
// fixed array (e.g. matrix4x4)
engine->RegisterObjectIndexOp("matrix4x4", "length=16;element=offset(0),,4,float");

With this the compiler would be able to understand that when accessing an element of the dynamic array it will find the length of the array at offset 8 from the object pointer, and to access the elements it should first offset the pointer with 16, then dereference the pointer, then offset with the index times the size of type T, and finally the accessed type will be T.

For the fixed array, it would know that the length is always 16, and that the element is accessed by directly offsetting the object pointer with the index times 4 and the accessed type will be a float.

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

This would be awesome: elements accessed thru this specific opIndex would just be accessed like class members in fact, right?

The syntax in the script would be identical to the current opIndex operator. Behind the scenes the compiler would generate the bytecode to access the elements without making a function call.

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

Advertisement

I implemented a special bytecode instruction for calling registered class methods with signature 'type &obj::func(int)' in revision 2147. With this there are almost no runtime decisions that has to be made when making the function call, so the overhead is greatly reduced.

In my tests, a script that accesses array members 20 million times took about 1.2 seconds without this new bytecode instruction, and with it it was reduced to about 0.4 seconds.

In comparison, the same logic implemented directly in C++, takes about 0.04 seconds. So the script is approximately 10 times slower than C++ now. With the use of a JIT compiler this difference should be reduced even further (though I haven't tried it).

---

I did experiment with implementing the opIndex call as direct access by inlining the call as bytecode instructions, and the performance was about the same as with the new bytecode instruction. For now I've decided to put this option on hold, as the effort to get it to work is too great compared to the benefits it will have.

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

Thanks! In order to validate the performance improvement with a JIT I guess this requires the new instruction to be implemented as part of the JIT, right?

Correct. The current version of the JIT will not recognize the new byte code instruction, thus it will fallback to using the VM.

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

This topic is closed to new replies.

Advertisement