Inconsistent pathing CPU cost



  • Room.findPath has extremely erratic timings in terms of cpu cost. Executing the following line in the console will return results between 2.5 and 17 ms:
    var a = Game.getUsedCpu(); Game.rooms.E3S12.getPositionAt(7,43).findPathTo(46,2); Game.getUsedCpu() - a;

    Since the pathing should be deterministic, and the room configuration doesn't drastically change from one tick to the next, it's very strange that there should be any substantial variation in the timings of the call.

    There are similar issues with Room.lookAt (lookAtArea for a particular entire room take 3-20 ms), and very possibly many other API functions.

    The random spikes in cost for pathing and looking at room tiles makes it very difficult to produce a consistent cpu usage.


  • SUN

    According to my own measures, any piece of code (any method) has a chance to slow down dramatically.
    This becomes evident, when you measure any CPU-hungry methods like findPath or require.

    Administrators' position was the following: the delays are caused by node.js and it's code-optimisation routines. I have another position: the delays may be caused caused by the 'garbage collection' routines that do pause the script implementation for a while to make it's job done.

    Anyway, this script delay effect doesn't make me happy, since it takes away my full control over the script's execution time.

    Despite the fact, that it's probably normal for NODE.JS engine to generate that delays, this effect dramatically clashes with the Screeps monetization model, where CPU usage is expected to be under player's control.

    The random spikes in cost for pathing and looking at room tiles makes it very difficult to produce a consistent cpu usage

    ^Yes, that's true^



  • The periodic CPU spikes are unlikely to combat within the current infrastructure built on JavaScript and Node.js. It’s worth remembering that JavaScript is an interpreted script language which has its limitations. It would be possible to achieve the consistent CPU usage only when all the players wrote their scripts in bytecode (or a language close to it) and the costs were measured in executed processor instructions. But in the case of a high-level interpreted language, there are multiple factors that create a considerable level of uncertainty.

    However, it is exactly in order to soften the gameplay consequences that we introduced the cumulative CPU bucket and the capability to regularly use resources exceeding your limit. Thanks to it, the periodic spikes are offset in the long-term.

    In any case, we will certainly keep improving our server script engine.



  • I am rather familiar with scripting languages and their general behaviors in realtime environments, though I'm less familiar with Javascripts' implementations. Spiking during execution is only typical of a Garbage Collection pass for most script languages, but given the nature of the execution environment, I would expect the GC to be disabled - you must be sandboxing everything our scripts produce and deleting it once the script ends anyway, correct?

    If that's correct, then if possible, could you tune or disable the GC so that it is unlikely to need to run during the execution of our scripts?

    On a semi-related note, the spiking is somewhat mitigated by the bucket, but our scripts don't have enough information to take full advantage of it. Right now, the only data given to the scripts is Game.cpuLimit (ranging from 0-500). Spikes can cause a rather large variance in actual cpu used, so the script needs to stay well out of the way of that limit. Unfortunately, while the limit is at 500, there's no way to tell if the bucket is just above 500 or nearly full.

    If there's no way to mitigate the spiking, I would ask that you expose three things:
    Game.cpuBucket, So the script can try to keep itself within a consistent cpu limit, but still have the full 500 limit available when needed.
    Game.cpuBudget, The limit set by the player, regardless of the moment-to-moment limit available.
    Game.setCpuBudget(ms), So the script can dynamically alter how many resources it's being given. This should probably be rate limited, perhaps one change per hour or so.


  • SUN

    The periodic CPU spikes are unlikely to combat within the current infrastructure built on JavaScript and Node.js.
    ...
    In the case of a high-level interpreted language, there are multiple factors that create a considerable level of uncertainty.

    That's a clear argument. Since CPU spikes affect every player, it may be reasonable and fair to inform us about a "considerable level of uncertainty" by publishing that info at the official Screeps documentation.

    I'm still not happy with the fact, that there is no way to full control my script's execution time, but ... the disclosure of the "CPU spikes" fact by the means of the documentation may correct players' expectations аnd avoid unpleasent frustration (that motivates ThyReaper and me to discuss this subject here)



  • I’m unaware of any methods of disabling garbage collection during execution of a specific code fragment (if you know them, please share). You can manually execute only non-incremental major GC runs that take very long time, and if you run them after each player script is over, it can easily make ticks 2 times slower and even more.

    Besides, another problem apart from the GC is runtime code optimizations that the V8 executes when analyzing code. They are very dependent on usage patterns that can vary from tick to tick, and various optimizations can behave differently.

    As for the API methods relating to CPU controlling – yes, we consider adding them in the future.