Optimisation Discussions Advises Experiences Ideas Etc
Moderator: Forum Moderators
Re: Optimisation Discussions Advises Experiences Ideas Etc
well maybe i done mistake somewhere, you may try to test it on your machine.. plus it might be different on different version of wesnoth and different operating system.. I assume. Also maybe if u own a latest processor the results will show something like "1,1,1,1" for all these tests so the difference would be neglectable...gfgtdf wrote:Hmm this does suprise me a little. Of course [store_locations] interally useswesnoth.get_locations
so it cannot be faster than that. And [store_locations] also have to store the locations and the terrain codes in wml vaiables. But i still expected this difference to be neglectable, this test though, shows that it takes nearly twice as long.
At the moment I stuck with my tests a little bit.. maybe..
My code should be:
Code: Select all
wesnoth.fire("store_locations",
{ x=xbegin-xend, y=ybegin-yend, { "not", { terrain="_off^_usr" }}, variable="ns_cube"})
wesnoth.fire("store_locations",
{ find_in="ns_cube", terrain="M*,M*^*", variable="ns_mountains"})
wesnoth.get_locations
and the problem is that if I dolocal loc_storage1 = wesnoth.get_locations { x=xbegin-xend, y=ybegin-yend, { "not", { terrain="_off^_usr" }} }
I can not do local loc_storage2 = wesnoth.get_locations {
find_in="loc_storage2"
, terrain="M*,M*^*"}Any simple ideas? Or the only way to count how many mountains was inside the loc_storage1 is to use
for i,... if loc_storage1[i].terrain == Mm.....
of course I have no idea how to extract elements from the table.. I will read a lot of helps.. but not sure if it's there.. might need to google lua programming language in internet to find out.. unless somebody could help? How to count amount of mountains, including impassable imountains, snow mountains etc.. (M*,M*^*) from the lua table which has many different terrains?I realized I could work around it and shorten the top 2 rows into 1, so instead of
Code: Select all
wesnoth.fire("store_locations",
{ x=xbegin-xend, y=ybegin-yend, { "not", { terrain="_off^_usr" }}, variable="ns_cube"})
wesnoth.fire("store_locations",
{ find_in="ns_cube", terrain="M*,M*^*", variable="ns_mountains"})
Code: Select all
wesnoth.get_locations { x=xbegin-xend, y=ybegin-yend, { "not", { terrain="_off^_usr" }}, terrain="M*,M*^*"}
- Pentarctagon
- Project Manager
- Posts: 5592
- Joined: March 22nd, 2009, 10:50 pm
- Location: Earth (occasionally)
Re: Optimisation Discussions Advises Experiences Ideas Etc
If you're running into problems, the Lua Labs or WML Workshop(depending on the problem) would be a better place to ask than this thread.
99 little bugs in the code, 99 little bugs
take one down, patch it around
-2,147,483,648 little bugs in the code
take one down, patch it around
-2,147,483,648 little bugs in the code
Re: Optimisation Discussions Advises Experiences Ideas Etc
Well I converted whole WML into LUA, without using
So the only untested part and I assume the bottleneck is this code:
vs
plus i found some other issues in code.. and I will have a new question in my lua topic..
PS. corrected some issues and now it looks like lua actually does have a speed gain.. speed gain depends on conditions.. So there is a tiny tiny gain if part of the code with random generation is used, and a massive huge gain if it is not used.. also in some circumstances it is still slower than wml.. and i dont understand why. tired for today, everything was buggy as a nightmare
wesnoth.fire
and there is no speed gain.. they seem to perform the same despite lua cycles usually 20 times faster.. and wesnoth.get_locations is at least 2 times faster.. here are 3 cycles while
and 2 wesnoth.get_locations
and the code takes LONG to perform.. on a map like conquest- Jel'wanSo the only untested part and I assume the bottleneck is this code:
Code: Select all
local NS_HIT_X = helper.rand(xbegin..".."..xend)
local NS_HIT_Y = helper.rand(ybegin..".."..yend)
Code: Select all
{VARIABLE_OP NS_HIT_X rand $xbegin..$xend}
{VARIABLE_OP NS_HIT_Y rand $ybegin..$yend}
PS. corrected some issues and now it looks like lua actually does have a speed gain.. speed gain depends on conditions.. So there is a tiny tiny gain if part of the code with random generation is used, and a massive huge gain if it is not used.. also in some circumstances it is still slower than wml.. and i dont understand why. tired for today, everything was buggy as a nightmare
Last edited by enclave on June 23rd, 2017, 2:13 am, edited 1 time in total.
Re: Optimisation Discussions Advises Experiences Ideas Etc
In wesnoth 1.12
helper.rand
is indeed expected to be slightly slower than the wml counterpart ([set_variable] rand=
). This has changed in wesnoth 1.13 where wesnoth.random was added and the wesnoth.set_vaiable implementation was moved to lua.Scenario with Robots SP scenario (1.11/1.12), allows you to build your units with components, PYR No preperation turn 1.12 mp-mod that allows you to select your units immideately after the game begins.
- Pentarctagon
- Project Manager
- Posts: 5592
- Joined: March 22nd, 2009, 10:50 pm
- Location: Earth (occasionally)
Re: Optimisation Discussions Advises Experiences Ideas Etc
I'd also recommend putting all the code for your tests in your first post as well, so people can see it without needing to scroll through the entire thread. Tests that have a significant difference in performance between the implementations(macro vs fire_event, WML vs lua, etc) might also make decent unit tests.
99 little bugs in the code, 99 little bugs
take one down, patch it around
-2,147,483,648 little bugs in the code
take one down, patch it around
-2,147,483,648 little bugs in the code
Re: Optimisation Discussions Advises Experiences Ideas Etc
Testing
Please have a look at codes, I could make mistakes.. specially in synchronize_choice.
very interesting.. I guess math random has a disadvantage of inability to select random from non-number.. can't pick a string from list of strings.. etc and is faster.. even if synchronized after.. (if i used synchronization code correctly)
So we have some conclusion thoughts.. 1) do not use
Now testing
vs
So we get some more speed if we don't save it as WML variable (looks like saving variable consumes 120 units of speed in 65k loop), so
not sure how
helper.rand
vs math.random
vs math.random wesnoth.synchronize_choice
vs wesnoth.fire("set_variable", {rand...})
with a rule: to save result as wml variable.Please have a look at codes, I could make mistakes.. specially in synchronize_choice.
Code: Select all
#define RAND1
[lua]
code = <<
for j=0,65000,1 do
local NS_HIT_X = helper.rand("10..100")
wesnoth.set_variable("wml_rand",NS_HIT_X)
end
>>
[/lua]
#enddef
#define RAND2
[lua]
code = <<
for j=0,65000,1 do
local NS_HIT_X = math.random(10,100)
wesnoth.set_variable("wml_rand",NS_HIT_X)
end
>>
[/lua]
#enddef
#define RAND3
[lua]
code = <<
for j=0,65000,1 do
local NS_HIT_X = math.random(10,100)
wesnoth.set_variable("wml_rand",wesnoth.synchronize_choice(function() return { value = NS_HIT_X } end).value)
end
>>
[/lua]
#enddef
#define RAND4
[lua]
code = <<
for j=0,65000,1 do
wesnoth.fire("set_variable", {name="wml_rand",rand="10..100"})
end
>>
[/lua]
#enddef
helper.rand
1908,1922,1914,1964math.random
150,181,177,170math.random wesnoth.synchronize_choice
1077,1066,1053,1044wesnoth.fire("set_variable", {rand...})
1560,1556,1580,1579very interesting.. I guess math random has a disadvantage of inability to select random from non-number.. can't pick a string from list of strings.. etc and is faster.. even if synchronized after.. (if i used synchronization code correctly)
So we have some conclusion thoughts.. 1) do not use
helper.rand
if you are on wesnoth 1.12 and if you need fast speed, where you cycle through random generated numbers.. 2) better use wesnoth.fire
instead.. because WML [set_variable] rand
is quicker than lua helper.rand (according to my previous tests wesnoth.fire
is same speed as WML corresponsing tag) 3) If you don't need synchronization for some reason (and only dealing with numbers).. for example using random generation for animation, use math.random
its 10 times faster than any alternative. 4) and if you need synchronization and not afraid to mess with synchronization and need speed, use math.random, then synchronize the result.. you will still win some 50% speed, am i right?Now testing
math.random wesnoth.set_variable
162,164,169,159vs
math.random local
40,54,45,48So we get some more speed if we don't save it as WML variable (looks like saving variable consumes 120 units of speed in 65k loop), so
helper.rand local
could be 120 units speed faster than helper.rand wesnoth.set_variable
if you don't need to save it as WML.. but it will still be quite significantly slower than wesnoth.fire("set_variable", {rand...})
variable.. not sure how
helper.rand local
would be compared vs wesnoth.fire("set_variable", {rand...}) wesnoth.get_variable
, assume helper would still be slower a bit..Re: Optimisation Discussions Advises Experiences Ideas Etc
Well I finally found what was slowing lua code down...
And I don't understand why...
This lua code above is much MUCH much MUCH slower than WML version of it:
Tested on Jel'wan (conquest minus add-on) map. In a small cycle (lua is 400 speed units faster WITHOUT this code, and 600 speed units slower WITH this code). BUT if map is covered with Gg everywhere lua code is faster again. On 2p Arcanclave Citadel (default era map) lua code is faster with or without this code.. So something makes it very slow on complicated maps like Jel'wan!
Any ideas? (I will post 65k loop of both codes in a minute...)
Test results without a loop... performed 1 time on a single cell.. filters are slow..
10.10 is Gs^Ft (forested grass)
{LOCS1} 44,42,36,40
{LOCS2} 40,46,36,48
{LOCS3} 49,39,39,78
{LOCS4} 36,44,40,38
10.10 is Gg (plain grassland)
{LOCS1} 36,45,43,45
{LOCS2} 38,46,35,41
{LOCS3} 39,42,23,42
{LOCS4} 46,45,29,33
Other complicated terrains like impassable or villages shown same speeds as forested grass test.
So now I will compare the wesnoth.get_locations without set_variable in a 100 times loop vs wesnoth.fire("store_locations"..), 65k loop just never seem to end..vs
10.10 is Gs^Ft (forested grass) 100 times loop
{LOCS1} 2019,2080,2031
{LOCS3} 2035,2036,2045
{LOCS4} 2023,2027,2032
10.10 is Gg (plain grassland) 100 times loop (normal Jel'wan map as it comes)
{LOCS1} 2028,2036,2071
{LOCS3} 2027,2066,2075
{LOCS4} 2032,2015,2036
And now a stupid thing Whole map is covered with Gg and we are doing same 100 times loop test would color it into red if was allowed because it needs attention...
10.10 is Gg (plain grassland) 100 times loop (whole map is only Gg)
{LOCS1} 632,628,628
{LOCS3} 614,624,622
{LOCS4} 610,615,627
So.. idk.. no comments. Just look the bottom 2 tests where the only difference was the whole map was Gg and in the other one it wasnt.. ?????
And I don't understand why...
Code: Select all
local ns_check_if_wrong_terrain = #wesnoth.get_locations { x=NS_HIT_X, y=NS_HIT_Y, { "not", { terrain="M*,W*,M*^*,W*^*,Ai*,Ai*^*,Rrc,Q*,X*,Q*^*,X*^*,Iwr,Rp^Ecf,Rp^Dr,_off^_usr"}}}
if ns_check_if_wrong_terrain>0 then
wesnoth.set_terrain(NS_HIT_X, NS_HIT_Y, "Mm")
end
Code: Select all
[store_locations]
x,y=$NS_HIT_X,$NS_HIT_Y
[not]
terrain=M*,W*,M*^*,W*^*,Ai*,Ai*^*,Rrc,Q*,X*,Q*^*,X*^*,Iwr,Rp^Ecf,Rp^Dr,_off^_usr
[/not]
variable=ns_check_if_wrong_terrain
[/store_locations]
[if]
[variable]
name=ns_check_if_wrong_terrain.length
greater_than=0
[/variable]
[then]
{MODIFY_TERRAIN Mm $NS_HIT_X $NS_HIT_Y}
[/then]
[/if]
Any ideas? (I will post 65k loop of both codes in a minute...)
Test results without a loop... performed 1 time on a single cell.. filters are slow..
Code: Select all
#define LOCS1
[lua]
code = <<
local x1 = 10
local y1 = 10
local ns_check_if_wrong_terrain = #wesnoth.get_locations { x=x1, y=y1, { "not", { terrain="M*,W*,M*^*,W*^*,Ai*,Ai*^*,Rrc,Q*,X*,Q*^*,X*^*,Iwr,Rp^Ecf,Rp^Dr,_off^_usr"}}}
>>
[/lua]
#enddef
#define LOCS2
[lua]
code = <<
local x1 = 10
local y1 = 10
local ns_check_if_wrong_terrain = #wesnoth.get_locations { x=x1, y=y1, { "not", { terrain="M*,W*,M*^*,W*^*,Ai*,Ai*^*,Rrc,Q*,X*,Q*^*,X*^*,Iwr,Rp^Ecf,Rp^Dr,_off^_usr"}}}
wesnoth.set_variable("ns_check_if_wrong_terrain", ns_check_if_wrong_terrain)
>>
[/lua]
#enddef
#define LOCS3
[lua]
code = <<
local x1 = 10
local y1 = 10
wesnoth.fire("store_locations",
{ x=x1, y=y1, { "not", { terrain="M*,W*,M*^*,W*^*,Ai*,Ai*^*,Rrc,Q*,X*,Q*^*,X*^*,Iwr,Rp^Ecf,Rp^Dr,_off^_usr"}}, variable="ns_check_if_wrong_terrain"})
>>
[/lua]
#enddef
#define LOCS4
[store_locations]
x,y=10,10
[not]
terrain=M*,W*,M*^*,W*^*,Ai*,Ai*^*,Rrc,Q*,X*,Q*^*,X*^*,Iwr,Rp^Ecf,Rp^Dr,_off^_usr
[/not]
variable=ns_check_if_wrong_terrain
[/store_locations]
#enddef
{LOCS1} 44,42,36,40
wesnoth.get_locations
{LOCS2} 40,46,36,48
wesnoth.get_locations set_variable
{LOCS3} 49,39,39,78
wesnoth.fire("store_locations"..)
{LOCS4} 36,44,40,38
[store_locations]
10.10 is Gg (plain grassland)
{LOCS1} 36,45,43,45
wesnoth.get_locations
{LOCS2} 38,46,35,41
wesnoth.get_locations set_variable
{LOCS3} 39,42,23,42
wesnoth.fire("store_locations"..)
{LOCS4} 46,45,29,33
[store_locations]
Other complicated terrains like impassable or villages shown same speeds as forested grass test.
So now I will compare the wesnoth.get_locations without set_variable in a 100 times loop vs wesnoth.fire("store_locations"..), 65k loop just never seem to end..
Code: Select all
local ns_check_if_wrong_terrain = wesnoth.get_locations { x=x1, y=y1, { "not", { terrain="M*,W*,M*^*,W*^*,Ai*,Ai*^*,Rrc,Q*,X*,Q*^*,X*^*,Iwr,Rp^Ecf,Rp^Dr,_off^_usr"}}}
Code: Select all
wesnoth.fire("store_locations",
{ x=x1, y=y1, { "not", { terrain="M*,W*,M*^*,W*^*,Ai*,Ai*^*,Rrc,Q*,X*,Q*^*,X*^*,Iwr,Rp^Ecf,Rp^Dr,_off^_usr"}}, variable="ns_check_if_wrong_terrain"})
{LOCS1} 2019,2080,2031
wesnoth.get_locations
{LOCS3} 2035,2036,2045
wesnoth.fire("store_locations"..)
{LOCS4} 2023,2027,2032
[store_locations]
via {REPEAT}10.10 is Gg (plain grassland) 100 times loop (normal Jel'wan map as it comes)
{LOCS1} 2028,2036,2071
wesnoth.get_locations
{LOCS3} 2027,2066,2075
wesnoth.fire("store_locations"..)
{LOCS4} 2032,2015,2036
[store_locations]
via {REPEAT}And now a stupid thing Whole map is covered with Gg and we are doing same 100 times loop test would color it into red if was allowed because it needs attention...
10.10 is Gg (plain grassland) 100 times loop (whole map is only Gg)
{LOCS1} 632,628,628
wesnoth.get_locations
{LOCS3} 614,624,622
wesnoth.fire("store_locations"..)
{LOCS4} 610,615,627
[store_locations]
via {REPEAT}So.. idk.. no comments. Just look the bottom 2 tests where the only difference was the whole map was Gg and in the other one it wasnt.. ?????
Re: Optimisation Discussions Advises Experiences Ideas Etc
Very very very strange behaviour... when testing wesnoth.get_locations 1v1 against [store_locations] it shows same speed.. but when used together with "other lua" it becomes slower.. I don't understand it!!!!! And "other lua" is much faster than "other wml" when I remove "wesnoth.get_locations" from it. And wesnoth.fire("store_locations"..) also becomes slower for some reason. I see no point to try to optimise WML using lua anymore, at least when dealing with terrains.
Example is this code, try it on map like "Jel'wan" or "Valeria", can be found in New Setters add-on.
Lua version, slower than WML: (shortcut with:
WML version, faster than LUA: (shorcut with:
LUA speed on Jel'wan is: 2125
WML speed is: 1488
LUA speed without
WML speed without
it all just makes no sense.
PS. after looking at my WML code I shortened it and it became even faster, while lua remains crap - 2 times slower!!!!.
Example is this code, try it on map like "Jel'wan" or "Valeria", can be found in New Setters add-on.
Lua version, slower than WML: (shortcut with:
{LUA_SETTLERS_FILL_MAP_WITH_MISSING_TERRAINS 8 1 0 1 0 1 1}
)
Code: Select all
#define LUA_SETTLERS_FILL_MAP_WITH_MISSING_TERRAINS SIZE COMPARISON1 REPEAT_FOREST COMPARISON2 REPEAT_HILLS COMPARISON3 REPEAT_MOUNTAINS
{VARIABLE ns_size {SIZE}}
{VARIABLE ns_comparison1 {COMPARISON1}}
{VARIABLE ns_comparison2 {COMPARISON2}}
{VARIABLE ns_comparison3 {COMPARISON3}}
{VARIABLE ns_repeat_forest {REPEAT_FOREST}}
{VARIABLE ns_repeat_hills {REPEAT_HILLS}}
{VARIABLE ns_repeat_mountains {REPEAT_MOUNTAINS}}
[lua]
code = <<
local comparison1 wesnoth.get_variable("ns_comparison1")
local comparison2 wesnoth.get_variable("ns_comparison2")
local comparison3 wesnoth.get_variable("ns_comparison3")
local w,h,b = wesnoth.get_map_size()
local ns_size = wesnoth.get_variable("ns_size")
local ns_repeat_mountains = wesnoth.get_variable("ns_repeat_mountains")
local ybegin = 1
local yend = ns_size
while (ybegin<=h)
do
local xbegin = 1
local xend = ns_size
while (xbegin<=w)
do
local ns_mountains = #wesnoth.get_locations { x=tostring(xbegin).."-"..tostring(xend), y=tostring(ybegin).."-"..tostring(yend), terrain="M*,M*^*"}
if ns_mountains<tonumber(wesnoth.get_variable("ns_comparison3")) then
for j=0,tonumber(ns_repeat_mountains),1 do
local NS_HIT_X = math.random(xbegin,xend)
NS_HIT_X = wesnoth.synchronize_choice(function() return { value = NS_HIT_X } end).value
local NS_HIT_Y = math.random(ybegin,yend)
NS_HIT_Y = wesnoth.synchronize_choice(function() return { value = NS_HIT_Y } end).value
local ns_check_if_wrong_terrain = #wesnoth.get_locations { x=NS_HIT_X, y=NS_HIT_Y, { "not", { terrain="M*,W*,M*^*,W*^*,Ai*,Ai*^*,Rrc,Q*,X*,Q*^*,X*^*,Iwr,Rp^Ecf,Rp^Dr,_off^_usr"}}}
if ns_check_if_wrong_terrain>0 then
wesnoth.set_terrain(NS_HIT_X, NS_HIT_Y, "Mm")
end
end
end
xbegin = xbegin + ns_size
xend = xend + ns_size
if xend > w then
xend = w
end
end
ybegin = ybegin + ns_size
yend = yend + ns_size
if yend > h then
yend = h
end
end
>>
[/lua]
{CLEAR_VARIABLE ns_size}
{CLEAR_VARIABLE ns_comparison1}
{CLEAR_VARIABLE ns_comparison2}
{CLEAR_VARIABLE ns_comparison3}
{CLEAR_VARIABLE ns_repeat_forest}
{CLEAR_VARIABLE ns_repeat_hills}
{CLEAR_VARIABLE ns_repeat_mountains}
#enddef
{WML_SETTLERS_FILL_MAP_WITH_MISSING_TERRAINS 8 (less_than=1) 0 (less_than=1) 0 (less_than=1) 1}
)
Code: Select all
#define WML_SETTLERS_FILL_MAP_WITH_MISSING_TERRAINS SIZE COMPARISON1 REPEAT_FOREST COMPARISON2 REPEAT_HILLS COMPARISON3 REPEAT_MOUNTAINS
[store_map_dimensions]
variable=ns_map_size
[/store_map_dimensions]
##
{VARIABLE ybegin 1}
{VARIABLE yend {SIZE}}
##
[while]
[variable]
name=ybegin
less_than_equal_to=$ns_map_size.height
[/variable]
[do]
{VARIABLE xbegin 1}
{VARIABLE xend {SIZE}}
##
[while]
[variable]
name=xbegin
less_than_equal_to=$ns_map_size.width
[/variable]
[do]
##
[store_locations]
x=$xbegin-$xend
y=$ybegin-$yend
[not]
terrain=_off^_usr
[/not]
variable=ns_cube
[/store_locations]
##
{FIND_IF_ANY_MOUNTAINS_ADD_MOUNTAINS {COMPARISON3} {REPEAT_MOUNTAINS}}
##
{VARIABLE_OP xbegin add {SIZE}}
{VARIABLE_OP xend add {SIZE}}
[/do]
[/while]
{VARIABLE_OP ybegin add {SIZE}}
{VARIABLE_OP yend add {SIZE}}
[/do]
[/while]
##
{CLEAR_VARIABLE ns_cube}
{CLEAR_VARIABLE xend}
{CLEAR_VARIABLE xbegin}
{CLEAR_VARIABLE ybegin}
{CLEAR_VARIABLE yend}
#enddef
#define FIND_IF_ANY_MOUNTAINS_ADD_MOUNTAINS COMPARISON REPEATS
[store_locations]
find_in=ns_cube
terrain=M*,M*^*
variable=ns_mountains
[/store_locations]
##
[if]
[variable]
name=ns_mountains.length
{COMPARISON}
[/variable]
[then]
{REPEAT {REPEATS} (
{VARIABLE_OP NS_HIT_X rand $xbegin..$xend}
{VARIABLE_OP NS_HIT_Y rand $ybegin..$yend}
########################
[store_locations]
x,y=$NS_HIT_X,$NS_HIT_Y
[not]
terrain=M*,W*,M*^*,W*^*,Ai*,Ai*^*,Rrc,Q*,X*,Q*^*,X*^*,Iwr,Rp^Ecf,Rp^Dr,_off^_usr
[/not]
variable=ns_check_if_wrong_terrain
[/store_locations]
[if]
[variable]
name=ns_check_if_wrong_terrain.length
greater_than=0
[/variable]
[then]
########################
{MODIFY_TERRAIN Mm $NS_HIT_X $NS_HIT_Y}
########################
[/then]
[/if]
{CLEAR_VARIABLE ns_check_if_wrong_terrain}
########################
)}
[/then]
[/if]
##
{CLEAR_VARIABLE ns_mountains}
{CLEAR_VARIABLE NS_HIT_X}
{CLEAR_VARIABLE NS_HIT_Y}
#enddef
WML speed is: 1488
LUA speed without
wesnoth.get_locations
: 24
Spoiler:
store_locations
: 415
Spoiler:
PS. after looking at my WML code I shortened it and it became even faster, while lua remains crap - 2 times slower!!!!.
Re: Optimisation Discussions Advises Experiences Ideas Etc
Ok, I found it..
This is silly but..
I can't believe its trully working..!
I replaced:
with
and instead of my fastest speed that I could achieve with WML: 1000
it does it on the fly, with speed of 14 !!!!!!!!!!! all you can do is blink and its done!
When you need to check the specific coordinate, DO NOT USE
This is silly but..
I can't believe its trully working..!
I replaced:
Code: Select all
local ns_check_if_wrong_terrain = #wesnoth.get_locations { x=NS_HIT_X, y=NS_HIT_Y, { "not", { terrain="M*,W*,M*^*,W*^*,Ai*,Ai*^*,Rrc,Q*,X*,Q*^*,X*^*,Iwr,Rp^Ecf,Rp^Dr,_off^_usr"}}}
if ns_check_if_wrong_terrain>0 then
wesnoth.set_terrain(NS_HIT_X, NS_HIT_Y, "Mm")
end
Code: Select all
local bool ns_check_if_wrong_terrain = wesnoth.match_location(NS_HIT_X, NS_HIT_Y, { terrain="M*,W*,M*^*,W*^*,Ai*,Ai*^*,Rrc,Q*,X*,Q*^*,X*^*,Iwr,Rp^Ecf,Rp^Dr,_off^_usr"})
if ns_check_if_wrong_terrain == false then
wesnoth.set_terrain(NS_HIT_X, NS_HIT_Y, "Mm")
end
it does it on the fly, with speed of 14 !!!!!!!!!!! all you can do is blink and its done!
When you need to check the specific coordinate, DO NOT USE
wesnoth.get_locations
, use wesnoth.match_location
or whatever else, but NOT wesnoth.get_locations!Re: Optimisation Discussions Advises Experiences Ideas Etc
Tried to do [fire_event] using {REPEAT} macro 2000 times and speed result was 200.. Which is not extremely bad.. It means that you may sometimes mix lua with fire_events.. but if you need huge speed boost I would not recommend fire_events firing more than 2000 times.. If you plan to make a fast code that calculates more than 2000 things via fire events then better find the other way, don't use fire_event.. use pure lua. Even 1000 fire events may significantly slow things down.
Just for comparison, lua can perform quite a big code with speed of 20.. VERY FAST. (it may include more than 2000 calculations of 1 line or longer)
1000 fire events of tiny TINY TINY code (like 1 line size) would be around 5 times slower, around speed of 100.. and I guess (not sure) that every 1000 speed is 1 second. 1 second is something you will most likely notice! (like a little lag or delay between actions..) I think that less than 200 would be unnoticed for human eye in most cases and around 500 would be acceptable. But keep in mind that every user has different computer.. if an AMD 6 core may show it as speed of 200.. some strong i7 may perform it with speed of 1, maybe... and some old dual core AMD or single core Pentium.. would give you a much bigger delay I assume.. Never tested this, only assuming, as I can not test it, or rather say don't want to test it now.. But will test it some day and put here for comparison.. It should be interesting.. how different devices or operating systems perform same calculations.
Just for comparison, lua can perform quite a big code with speed of 20.. VERY FAST. (it may include more than 2000 calculations of 1 line or longer)
1000 fire events of tiny TINY TINY code (like 1 line size) would be around 5 times slower, around speed of 100.. and I guess (not sure) that every 1000 speed is 1 second. 1 second is something you will most likely notice! (like a little lag or delay between actions..) I think that less than 200 would be unnoticed for human eye in most cases and around 500 would be acceptable. But keep in mind that every user has different computer.. if an AMD 6 core may show it as speed of 200.. some strong i7 may perform it with speed of 1, maybe... and some old dual core AMD or single core Pentium.. would give you a much bigger delay I assume.. Never tested this, only assuming, as I can not test it, or rather say don't want to test it now.. But will test it some day and put here for comparison.. It should be interesting.. how different devices or operating systems perform same calculations.
Re: Optimisation Discussions Advises Experiences Ideas Etc
Optimization problems when converting macros into fire events..
All seems simple.. you have a lot of code.. you have macros inside macros.. you want to cut the savefile size or increase performance, you know what you are doing.. you done it a lot of times.. but!
From time to time.. your game turns into a mess!
It is known that when you fire event from some event.. then the fired event inherits the parent event variables...
For example:
This will work perfectly fine.. same as if you would just done it WITHOUT fire event like below:
Yeah, nothing changes.. you could convert macros into fire event.. and use $owner_side inside your fired event.. same as inside macro.. COOL!
BUT if you write this:
What do you think you will get? CRAP.. lot of crap.. specially if your code is not only delivering a silly message..
The message without fire event will be saying "without fire event: side 2 lost a village at 13,14"
The message inside fired event will be saying "fire_event_1: side 2 lost a village at 0,0"
So fire events inherit something from parent event.. BUT some things, like $x1 $y1 get eaten.. and turned into ZEROES.
When you convert your code into fire events, make sure to replace all coordinates with your own variables!!!
For example this should work fine:
But trust me, this may create a lot of headache if you ignore this.. Stderr.txt will not show any errors, owner_side will be working fine.. side_number will be working fine.. you will be wondering what went wrong.. and this is as simple as stupid as this.. $x1=0 $y1=0
So when you convert your macros into fire events, make sure to change $x1 and $y1, do NOT reply on them!!
Good luck!
All seems simple.. you have a lot of code.. you have macros inside macros.. you want to cut the savefile size or increase performance, you know what you are doing.. you done it a lot of times.. but!
From time to time.. your game turns into a mess!
It is known that when you fire event from some event.. then the fired event inherits the parent event variables...
For example:
Code: Select all
[event]
name=capture
first_time_only=no
{FIRE_EVENT message_which_side_lost_a_village} ## keep in mind that this macro {FIRE_EVENT} doesn't exist by default, you need to create it.
[/event]
[event]
name=message_which_side_lost_a_village
first_time_only=no
[message]
message="fire_event_1: side $owner_side lost a village"
[/message]
[/event]
Code: Select all
[event]
name=capture
first_time_only=no
[message]
message="without fire event: side $owner_side lost a village"
[/message]
[/event]
BUT if you write this:
Code: Select all
[event]
name=capture
first_time_only=no
[message]
message="without fire event: side $owner_side lost a village at $x1,$y1
[/message]
{FIRE_EVENT message_which_side_lost_a_village}
[/event]
[event]
name=message_which_side_lost_a_village
first_time_only=no
[message]
message="fire_event_1: side $owner_side lost a village at $x1,$y1
[/message]
[/event]
The message without fire event will be saying "without fire event: side 2 lost a village at 13,14"
The message inside fired event will be saying "fire_event_1: side 2 lost a village at 0,0"
So fire events inherit something from parent event.. BUT some things, like $x1 $y1 get eaten.. and turned into ZEROES.
When you convert your code into fire events, make sure to replace all coordinates with your own variables!!!
For example this should work fine:
Code: Select all
[event]
name=capture
first_time_only=no
{VARIABLE xx $x1}
{VARIABLE yy $y1}
{FIRE_EVENT message_which_side_lost_a_village}
[/event]
[event]
name=message_which_side_lost_a_village
first_time_only=no
[message]
message="fire_event_1: side $owner_side lost a village at $xx,$yy
[/message]
{CLEAR_VARIABLE xx}
{CLEAR_VARIABLE yy}
[/event]
So when you convert your macros into fire events, make sure to change $x1 and $y1, do NOT reply on them!!
Good luck!
Re: Optimisation Discussions Advises Experiences Ideas Etc
Try adding this to your FIRE_EVENT definition:
Code: Select all
[primary_unit]
x,y=$x1,$y1
[/primary_unit]
http://www.wesnoth.org/wiki/User:Sapient... "Looks like your skills saved us again. Uh, well at least, they saved Soarin's apple pie."
Re: Optimisation Discussions Advises Experiences Ideas Etc
Another test of WML against lua in speed comparison.
Storing locations and loops are the main subjects of comparison..
So codes below will be doing exactly the same thing and they are coded quite like a mirror, they will remove all leaders from map and then put them back on map with distance between them set according to settings, with only 1 rule that the leaders should appear on land, not water or impassable.
WML
LUA
And the result speeds were:
WML - 17k (I assume it equals to 17 seconds) Really slow, waiting clock appears, gives a feeling that game is lagging and will crash or never unfreeze.
lua - 0.7k (less than a second then..) Really quick.. doesn't give you time to think about anything really..
So 20 times faster with lua..
Storing locations and loops are the main subjects of comparison..
So codes below will be doing exactly the same thing and they are coded quite like a mirror, they will remove all leaders from map and then put them back on map with distance between them set according to settings, with only 1 rule that the leaders should appear on land, not water or impassable.
WML
Code: Select all
[event]
name=start
first_time_only=yes
{TT_BEGIN} ##timer begin
##############################
{VARIABLE ns_min_dist $NS_preload_options_shuffled_sides_minimal_distance}
##########################
[if]
[variable]
name=ns_min_dist
not_equals=0
[/variable]
[then]
[store_locations]
[not]
terrain=W*,W*^*,Xv,_off^_usr
[/not]
variable=ns_test_locations
[/store_locations]
[if]
[variable]
name=ns_test_locations.length
greater_than=$ns_min_dist
[/variable]
[then]
[store_unit]
kill=yes
[filter]
canrecruit=yes
[/filter]
variable=ns_all_kings_stored
[/store_unit]
{VARIABLE ns_king_rand_start_counter 0}
{FOREACH ns_test_locations ntl_i}
[if]
[variable]
name=ns_king_rand_start_counter
less_than=$ns_all_kings_stored.length
[/variable]
[then]
[store_locations]
x,y=$ns_test_locations[$ntl_i].x,$ns_test_locations[$ntl_i].y
[and]
[not]
[filter]
canrecruit=yes
[/filter]
radius=$ns_min_dist
[/not]
[/and]
variable=ns_test_inner_locations
[/store_locations]
[if]
[variable]
name=ns_test_inner_locations.length
greater_than=0
[/variable]
[then]
[unstore_unit]
x,y=$ns_test_locations[$ntl_i].x,$ns_test_locations[$ntl_i].y
variable=ns_all_kings_stored[$ns_king_rand_start_counter]
animate=no
[/unstore_unit]
{VARIABLE_OP ns_king_rand_start_counter add 1}
{CLEAR_VARIABLE ns_test_inner_locations}
[/then]
[else]
{CLEAR_VARIABLE ns_test_inner_locations}
[/else]
[/if]
[/then]
[/if]
{NEXT ntl_i}
[/then]
[/if]
[/then]
[/if]
{CLEAR_VARIABLE ns_all_kings_stored}
{CLEAR_VARIABLE ns_test_locations}
{CLEAR_VARIABLE ns_test_inner_locations}
{CLEAR_VARIABLE ns_king_rand_start_counter}
{TT_END} ##timer end
[/event]
Code: Select all
[event]
name=start
first_time_only=yes
{TT_BEGIN} ##timer begin
[lua]
code = <<
local ns_min_dist = wesnoth.get_variable("NS_preload_options_shuffled_sides_minimal_distance")
if ns_min_dist ~= 0 then
local ns_test_locations = wesnoth.get_locations { {"not", { terrain = "W*,W*^*,Xv,_off^_usr" } }}
local w,h,b = wesnoth.get_map_size()
if (w > ns_min_dist) or (h>ns_min_dist) then
wesnoth.fire("store_unit",{kill="yes", {"filter", {canrecruit=true}},variable="ns_all_kings_stored"})
local ns_king_rand_start_counter = 0
for i, ns_pairs_locations in ipairs(ns_test_locations) do
if ns_king_rand_start_counter<wesnoth.get_variable("ns_all_kings_stored.length") then
local ns_test_inner_locations = wesnoth.match_location(ns_pairs_locations[1], ns_pairs_locations[2], { radius=ns_min_dist , { "filter", { canrecruit=true } } })
if ns_test_inner_locations == false then
wesnoth.fire("unstore_unit",{animate=no,x=ns_pairs_locations[1],y=ns_pairs_locations[2],variable="ns_all_kings_stored["..ns_king_rand_start_counter.."]"})
ns_king_rand_start_counter = ns_king_rand_start_counter + 1
end
end
end
end
end
>>
[/lua]
{TT_END} ##timer end
[/event]
WML - 17k (I assume it equals to 17 seconds) Really slow, waiting clock appears, gives a feeling that game is lagging and will crash or never unfreeze.
lua - 0.7k (less than a second then..) Really quick.. doesn't give you time to think about anything really..
So 20 times faster with lua..
Re: Optimisation Discussions Advises Experiences Ideas Etc
For the record, I consider the experiment of releasing preprocessed ageless success. My testing showed 3x faster loading, and player feedback has been positive.
Re: Optimisation Discussions Advises Experiences Ideas Etc
Hi Ravana, thats great!Ravana wrote:For the record, I consider the experiment of releasing preprocessed ageless success. My testing showed 3x faster loading, and player feedback has been positive.
Maybe you could tell in a little bit more details then what exactly the situation was before and what has changed now? 3x faster loading is a massive speed gain! How did you manage to achieve that?
(For those who doesn't know, we are talking about add-on called "ageless", it has a massive amount of custom units and images, therefore it has a size of more than 50MB, in other words it's HUGE! One of the biggest add-ons at least!)