Advertisement

speed up function calls.

Started by August 29, 2022 02:28 PM
7 comments, last by WitchLord 2 years, 2 months ago

Hi everyone.

I want to add some scripting features to my C++ app (Qt).

What I need is executing small functions (both in C++ and script), sometimes millions of times per second, so I need speed.

I first tried with QtScript, it provides great integration with QObejcts (which I don't really need) but it is very slow.

Then I tried LUA and it is really fast, but there are a few thing I don't like.

Now I found AngelScript and I like it, seems exactly what I need and it is very fast but still slower than LUA.

So I'm not yet decided: I would like to use AngelScript, it is much better suited for my purposes and has everything I need, but speed is really needed.

Note that I'm just evaluating which scripting language to use, so I only know the very basics to make the simplest example.

Doing some profiling I found that the bottleneck is in function calls, specially script calls. Specially: context->Prepare and asPushActiveContext whithin execute() are very expensive.

So I would like to know if it is possible to speed up script function calls, by saving contexts or avoiding some of these steps. Note that some script functions are called over and over again without calls to other script functions.

I'm not asking for the concrete implementation, I just want to know If it is possible and if so what kind of speed up could I get.

None

I can't help but notice your approach strikes me as rather unorthodox. From my perspective (dealing almost exclusively in gamedev), every tick of the engine you run a script ( Update() ) function exactly once, meanwhile in this one function a lot of stuff happens. While I don't exactly know what your goal is, is it not viable to do a similar approach?

Advertisement

Hi and thanks for your reply.

This is not a game, I'm using AngelScript for other purposes, or I should say: I'm evaluating if AS is suitable for my purpose.

Somehow it works in a similar way, but my engine can call "update()" several million times per second.

The code inside the "update()" function is usually just a few lines, but is is called many many times, so the call itself becomes the bottleneck.

I already found that just disabling thread safety increases context->Execute() call speed dramatically:

From around 2800 instructions to just 495, now it is more than 2 times faster than what I got from LUA (but I didn't try to optimize LUA calls).

context->Prepare() is still very expensive, but I guess I can call this only once per function.

Maybe having a context exclusive for critical functions or something like that.

But as I said, I still have no idea how AS works.

In any case, with the speed I'm getting now in context->Execute() I think I'm decided to use AngelScript.

I still need to figure out how to optimize Script->C++ calls and whatever I can optimize for speed, So any idea is very welcome.

None

I found that context->Prepare() is relatively slow only the first time it is called on a function, subsequent calls on the same function are much faster, so the 2 main issues are clear now… I'm 100% with AngelScript.

None

You may want to check out the article in the manual about fine tuning: http://www.angelcode.com/angelscript/sdk/docs/manual/doc_finetuning.html

Also, if you're running on x86/64 CPUs you can use the JIT compiler from BlindMind to improve the performance even further. Unfortunately, BlindMind are no longer actively maintaining the JIT compiler so I can't ascertain if it works 100% with the latest version of AngelScript, though if there is any problem it should be only small tweaks. And possibly, those tweaks have already been done by someone else, just as BlueCat did in their fork. http://www.angelcode.com/angelscript/resources.html

If by any chance you identify some way of optimizing AngelScript I'd gladly hear about it so it can be improved for everyone's use.

Regards,
Andreas

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

Hi Andreas, thanks for the information. The article about fine tuning was very useful.

I will try the JIT compiler, it will help in any case, and I guess that it can make a difference in Script→C++ calls (my other bottleneck).

In any case it is already quite fast, specially considering that it provides most C/C++ capabilities, types, etc. , I'm really happy.

If I find some some way of optimizing AngelScript I will let you know. By now I only got to save a bunch of instructions by deleting calls to IsNested() in Prepare() because I'm not using nested calls (but I don't really know what I'm doing), just a hack right now and it is barely noticeable even in my case .

To get an idea of my case, this is the main function in a simple script I created to test the whole thing (everything working like a charm):

void extClock()  // Function called from C++ 1e6 times per sec.
{
    if( cycles == 0 )
    {
        cycles = component.readPGM( PC++ );                  // call C++ func
        
        if( cycles == 0 ) PC = 0;
        else              ampli = component.readPGM( PC++ ); // call C++ func
    }
    else cycles--;
    
    double input  = component.getPinVoltage( InputPin );     // call C++ func
    double output = input*ampli/255;
    
    component.setPinVoltage( outputPin, output );            // call C++ func
}

None

Advertisement

Tried the JIT compiler (BlueCat), the only thing is lots of warnings in gcc 9.4.0, maybe it needs an update.

I didn't try any of the JIT optimizations.

It's working ok and made a big difference, context->Execute() is 4 times faster running the code above, and the overall speed calling script function increased 3.3 times. This is calling the same function a few million times, if other script functions are called then context->Prepare() adds some overhead.

Note that the difference was only measured for one specific case. The method: profiling with callgrind to count the total number of instruction reads and dividing by number of calls.

None

Thanks for letting us know. It is good to know the JIT compiler is still working well.

Once you start building your system and feel you're getting performance slowed down by in any particular case don't hesitate to tell me. I may not always have the bandwidth to actually do something about it, but I would still like to know where potential bottlenecks are in AngelScript so I can address them in the future.

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