English Time-critical code or not?

6 replies
Goto Page
To the start Previous 1 Next To the start
13.05.20 10:32:32 am
Up
Gaios
Security Supporter
Offline Off
Hello,

I'm really curious if this really make sense in CS2D Scripts. I know that there's something like code optimization and https://springrts.com/wiki/Lua_Performance. Does it really important in CS2D Scripts?

The most important thing I ask about is
for _, i in pairs() do
to measure the real difference.
I have made online test code:
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
local tab = {}
for i = 1, 1000 do
  tab[i] = { a = false }
end

local x

x = os.clock()
for i = 1, 10 do
  for _, i in pairs(tab) do i.a = _ end
end
print(string.format("elapsed time: %.4f\n", os.clock() - x))
x = os.clock()
for i = 1, 10 do
  for i = 1, #tab do tab[i].a = i end
end
print(string.format("elapsed time: %.4f\n", os.clock() - x))


Looping like 1000 elements, 10x times per second. The results was:
elapsed time: 0.0013
elapsed time: 0.0010

Almost no difference.

I wonder if CS2D Servers will freeze to calculate similar stuff for large data...? like looping 500 custom mobs and do math calculations in ms100 event.

Other data results:
pairs: 3.078 (217%)
ipairs: 3.344 (236%)

for i=1,x do: 1.422 (100%)
for i=1,#atable do 1.422 (100%)
for i=1,atable_length do: 1.562 (110%)
13.05.20 02:46:40 pm
Up
MikuAuahDark
User
Offline Off
I've learned much about Lua optimization since I start using LOVE and I'll share what I know from experience.

For that specific case like iterating over 500 custom mobs and performing calculation in cs2d lua hook ms100, it shouldn't be a problem, unless the code also interacts with any CS2D function. Interaction between CS2D's Lua API is slow so you may want to avoid that in performance-critical code. It also depends on how your calculation whetever you perform complex operation or simple arithmetic operations.

EDIT: Optimization tips, if you perform lots of cs2d lua cmd parse, consider batching all the command and fire them up in one go, as described in thread cs2d 【東方】Bad Apple!! 【影絵】 in CS2D

For your benchmark example like pairs vs ipairs, in plain Lua, pairs is faster. Actually, pairs is implemented like this.
Code:
1
2
3
function pairs(t)
     return next, t, nil
end
.
I still have no idea why ipairs is slower, but you can look how both those functions implemented in here.

Note that it assume plain Lua 5.1.4, the one CS2D uses. The story is completely different if you involve file cs2d LuaJIT for Dedicated Server (11).
edited 2×, last 13.05.20 03:36:21 pm
file cs2d LuaJIT for Dedicated Server (11) JIT POWER! | Know your Lua errors! | Draw stuff at Pixelize Art --xx-- server!
13.05.20 06:42:18 pm
Up
DC
Admin
Offline Off
Yes, slow Lua scripts will freeze CS2D because CS2D run in just one single thread (no multithreading).
More specifically the game server. So for clients that will mean they will get lags. It will be especially noticeable if you run a listen server (client and game server in one) and play in it as you will also see FPS drops.

So optimizing makes sense.
But there's that nice quote "Premature optimization is the root of all evil". Just don't waste time with optimizing stuff when there's no real need to optimize stuff.
www.UnrealSoftware.de | www.CS2D.com | www.CarnageContest.com | Use the forum & avoid PMs!
14.05.20 05:10:07 am
Up
VADemon
User
Offline Off
For loop, pairs, ipairs all have different purposes. Always use for-loop if you need to iterate over numbers in a table, pairs over all elements (number keys + all other types of keys). And basically: don't use ipairs.

user MikuAuahDark has written:
EDIT: Optimization tips, if you perform lots of cs2d lua cmd parse, consider batching all the command and fire them up in one go, as described in thread cs2d 【東方】Bad Apple!! 【影絵】 in CS2D

This guy is a genuis too with his memory (I don't know how he still remembers it)! Yeah, any calls to CS2D API are really slow. I thought of a system to cache all values at the beginning of a new tick (on cs2d lua hook always), but it would only be useless overhead in 99.99% cases. Just try to be smart about how often you need to get/refresh values from the game if you have hundreds of entities.

user Gaios has written:
like looping 500 custom mobs and do math calculations in ms100 event.

Meh idea. You will have this one single frame that's either ≤20ms (good) or if you have too many entities it will be >20ms and become this single "freeze frame". Ideally (if you can), distribute the computation across many frames. E.g. cs2d lua hook always but you only do math on 1/5th of mobs, this way it's the same load as with ms100, but done in small parts over 5 frames - prevents the issue of a single slow frame.

The most important part is actually the algorithm. AVOID O(n²) - that is, e.g. for target finding you iterate each mob against every other mob (=n*n mobs). You can split the mobs using something like https://en.wikipedia.org/wiki/Octree (that's for 3D space, but 2D is similar). Most descriptions won't be easy to understand, just try to find and read a couple explanations until you get it. Use your own pen and paper to visualise.

Except for the API overhead + network crash (timeout) I don't see anything elsee you'd need to worry about.
14.05.20 09:19:59 am
Up
Gaios
Security Supporter
Offline Off
Ok.. let's see... The Mob Engine will use lua image functions to animate (...
tween_move()
) and
object()
to get positions. Well.. I think I don't need to fetch the positions if I will store it in mob properties eg. on each
setPos(x, y)
method. The problem comes when I will use
tween_move()
, or sth similar to this.. I need to update Mob Position eg. from
object()
API but as we already know it's very slow and not recommened. Ok.. I can do like Lua loop to try to iterate the positions by myself with math. (Probably I will just set the next position to current one because I move the Mob 100ms forward).

> The other problem is that I need to animate Mob with
tween_move()
and other and it's also related to CS2D API, and I believe I can't bypass it.

And if you talk about the loop.. I was just curious on what will you say, but anyway I have made Chunk System that helps me to divide map to small parts
14.05.20 01:56:51 pm
Up
MikuAuahDark
User
Offline Off
You can approximate movement by cs2d lua cmd tween_move (actually any
tween_*
in general) by performing linear interpolation in cs2d lua cmd always hook and using
os.clock()
as your delta time. For your "chunk system", that sounds good. I'll assume the principle is same as spatial hash in game development.

Also I agree with user VADemon that you should only use numerical loop to iterate non-sparse arrays. Not only it fast but it also has consistent performance even when LuaJIT comes into play, where when you already out of things to optimize, then setting up file cs2d LuaJIT for Dedicated Server (11) in your server should give you (slight) performance boost.

Of course LuaJIT won't help you improve the performance of the CS2D Lua API. Some time ago, out of my curiosity, I hacked some memory address with LuaJIT FFI to call cs2d cmd settile directly, bypassing cs2d lua cmd parse and the result is neligible compared when you batch cs2d cmd settile in cs2d lua cmd parse

user VADemon has written:
This guy is a genuis too with his memory (I don't know how he still remembers it)! Yeah, any calls to CS2D API are really slow. I thought of a system to cache all values at the beginning of a new tick (on cs2d lua hook always), but it would only be useless overhead in 99.99% cases. Just try to be smart about how often you need to get/refresh values from the game if you have hundreds of entities.

Nah it pops into my mind few months ago when I challenge myself to rewrite and optimize w0w citylife server in 1 week with my Lua capabilities and to test LuaJIT stability in CS2D. It sort of success but I can't activate the server for long because the server got DDoS'd multiple times, so I create pixel art server instead.
file cs2d LuaJIT for Dedicated Server (11) JIT POWER! | Know your Lua errors! | Draw stuff at Pixelize Art --xx-- server!
15.05.20 05:54:06 am
Up
VADemon
User
Offline Off
os.clock()
makes a system call - this could be potentially another bottleneck (especially if you are on an Intel processor with vulnerability mitigations enabled).

I'd like to know what performance figures you come up with, user Gaios, after all the benchmarks and evaluations. I'm honestly too lazy to do it "just for fun" now
To the start Previous 1 Next To the start