Oh, the slowness! I must be doing it wrong


#1

So slow! I must be doing it wrong.
Setup:
Chaiscript 6.0.0 (Release) without Threading
G++ 7.2.0 (-O3 -march=native -std=c++17)
ECS with a ScriptComponent
ScriptComponent has

std::function<void(anax::Entity &,const timestamp_t &)> tic;

Upon initialization a scripted function is assigned to tic.
Each frame/tic each entity’s tic() gets called.

This is rather slow, even a hand full of entities eat up a good chunk of cputime. I profiled up and down and am sure that it is within ChaiScript executing tic().
Below tic(), one of the hottest functions is

_strcmp_sse2_unaligned

called by ChaiScript’s stuff.

The tic function does not do much, and the bound c++ functions it calls don’t make a dent in the profiles. Now, even if i use a dummy like:

this.handlers["tic"] = fun(e,now) {
                        return;
}

it still comes up big in the profiles. In script the tic function is part of a Class, which i use to setup types of entities. These classes are singletons in script. Upon entity init i assign the handlers contained withing these classes to ScriptComponents like so (C++):

if(!s.tic) {
                const chaiscript::dispatch::Dynamic_Object & o = chaiscript::boxed_cast< chaiscript::dispatch::Dynamic_Object >(*s.type);
                const std::map<std::string,chaiscript::Boxed_Value> & m = chaiscript::boxed_cast< std::map<std::string,chaiscript::Boxed_Valu$
                if(m.count("tic")) {
                        s.tic = chaiscript::boxed_cast<std::function<void(anax::Entity &,const timestamp_t &)>>(m.at("tic"));
                }
        }

s.type above is declared as:

std::shared_ptr<chaiscript::Boxed_Value> type;

and holds the Class defining the scripted type of an entity as mentioned above. The default Class for entity-types is this:

class Default {
        attr name
        attr handlers
        def Default() {
                this.name = "Default";
                this.handlers = Map();

                this.handlers["tic"] = fun(e,now) {    
                        return;
                }

                this.handlers["init"] = fun(e,now) {
                        e.activate();
                        return true;
                }
        }
}
registerType("Default",Default());

Now i can’t figure out why calling tic() from c++ is so slow. I don’t have problems with ChaiScript being too slow overall.
I’ve uploaded a flamegraph of the thread using the dummy mentioned above: flamegraph (SVG)
(click on ScriptSystem::processTic to Zoom to function i’m talking about)
And thats for like 4 entities that have ScriptComponents and a tic-function. Called at 50hz.

Hopefully someone around here has a clue what’s going on with that.

EDIT: I shall SHAMELESSLY invite @lefticus to this topic.


#2

This might be related to the same issue I had here. Long story short, I assign a function from ChaiScript to be called in C++ in a loop and there is a progressive performance degradation over time:


#3

Hm, related maybe - however note that in my case i call c++ > chai, as you seem to call chai > c++ > chai.
And (at least i did not notice) no increasing utilization - it’s high from the go and stays that way.
Left a comment on your github issue. (Could reproduce your issues with that.)
Now what i found interesting is that your thing when calling ts.run from c++ isn’t as slow as the c++ > chai call in my code.
Even if there is nothing to it either way - just some simple dummy function in a std::function.
At least now for my part i know i most probably am doing it wrong =).


#4

I’ll mark this as answered for now - because i don’t think this is a bug.
rather it’s just “how it is” and probably a non-optimal use-case.
if i still struggle with this in a few versions, of my project as well as ChaiScript, i’ll open another thread.