Forum

> > CS2D > Scripts > function is lagging
Forums overviewCS2D overview Scripts overviewLog in to reply

English function is lagging

16 replies
To the start Previous 1 Next To the start

old function is lagging

francis007
BANNED Off Offline

Quote
I call this funtion with minute hook every minute but the functions drops the fps and lag. Can someone tell me how to fix the lag?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
function openshops()     
for they = 1,#shops do
for _,e in pairs(entitylist()) do
if entity(e.x,e.y,"name") == shops[they].button  then
buttonentityx2,buttonentityy2 = e.x,e.y
end
end
if not entity(buttonentityx2,buttonentityy2,"state") then 
if entity(shops[they].gatex,shops[they].gatey,"state") == false then
parse("trigger "..entity(shops[they].gatex,shops[they].gatey,"name"))
end   
for lala= 1,#shops[they].doors do
for _,e in pairs(entitylist()) do
if entity(e.x,e.y,"name") == shops[they].doors[lala] then
entdoorx,entdoory = e.x,e.y
if not tile(entdoorx,entdoory,"walkable") then
parse("trigger "..shops[they].doors[lala])
end
end
end
end 
end
end
end

old Re: function is lagging

Yates
Reviewer Off Offline

Quote
Because you have 4 loops 2 of which are inside another loop. You could probably shorten this into just 2.

As for the lag or fps drop goes. How many items are there in both the shops table and entity list? I'm betting the parse trigger is being called a lot.
edited 3×, last 02.01.17 06:11:07 pm

old Re: function is lagging

Starkkz
Moderator Off Offline

Quote
Does it still work?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
function openshops()
 
	for they, shop in pairs(shops) do
	
		local EntityList = entitylist()
		local Entity
	
		for _, e in pairs( EntityList ) do

			if entity(e.x, e.y, "name") == shop.button  then
			
				Entity = e
				
				break
				
			end
			
		end
		
		if Entity and not entity(Entity.x, Entity.y, "state") then 
	
			if entity(shop.gatex, shop.gatey, "state") == false then
			
				parse("trigger " .. entity(shop.gatex, shop.gatey, "name") )
				
			end   
		
			for _, door in pairs(shop.doors) do
			
				for _, e in pairs( EntityList ) do
				
					if entity(e.x, e.y, "name") == door and not tile(e.x, e.y, "walkable") then
						
						-- Func_DynWall ?
						
						parse("trigger "..door)
						
					end
					
				end
				
			end 
		
		end
	end
	
end

Accessing globals like you were doing just causes a massive overhead, you were constantly using shops[they] where you could've defined a local variable shop to shops[they] and just use shop instead.

old Re: function is lagging

francis007
BANNED Off Offline

Quote
im using shop[id] for look which player have the which shop but this functions is for only if player remove the shop and leave it with closed doors .

shops[shop[id]]


EDIT: @user Bowlinghead Only if i call the function.

old Re: function is lagging

Starkkz
Moderator Off Offline

Quote
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
function shop_loop()

	for i = 1, 3 do

		local they, shop = shop_iterator()
		
		if not they or not shop then
			
			shop_iterator = nil
			
			freehook("ms100", "shop_loop")
			
			return nil
			
		end
		
		local EntityList = entitylist()
		local Entity
		
		for _, e in pairs( EntityList ) do

			if entity(e.x, e.y, "name") == shop.button  then
			
				Entity = e
				
				break
				
			end
			
		end
		
		if Entity and not entity(Entity.x, Entity.y, "state") then 
		
			if entity(shop.gatex, shop.gatey, "state") == false then
			
				parse("trigger " .. entity(shop.gatex, shop.gatey, "name") )
				
			end   
		
			for _, door in pairs(shop.doors) do
			
				for _, e in pairs( EntityList ) do
				
					if entity(e.x, e.y, "name") == door and not tile(e.x, e.y, "walkable") then
						
						-- Func_DynWall ?
						
						parse("trigger "..door)
						
					end
					
				end
				
			end 
		
		end
		
	end

end

function openshops()

	shop_iterator = pairs(shops)
	
	addhook("ms100", "shop_loop")
	
end

How about now?

old Re: function is lagging

Rainoth
Moderator Off Offline

Quote
I believe this is meant to open shop doors, correct? I don't see the point in checking for state of the game every 5 frames when you can check it whenever the state of entity changes (for example on use of a button).

TL;DR try using use button in place of ms100.

old Re: function is lagging

Starkkz
Moderator Off Offline

Quote
@user Rainoth: The 'ms100' was intended to be a temporary hook, which is later removed with 'freehook' so instead of performing the heavy task in one call, it performs it within more calls every 100 milliseconds until the task is complete.

But if it's a CPU eating process you will probably require to use a coroutine & a hook to automatically slow that process.

I don't know if it's going to work.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
function shop_loop()

	local EntityList = entitylist()

	for they, shop in pairs(shops) do

		local Entity

		for _, e in pairs( EntityList ) do

			if entity(e.x, e.y, "name") == shop.button  then

				Entity = e

				break

			end

		end

		if Entity and not entity(Entity.x, Entity.y, "state") then

			if entity(shop.gatex, shop.gatey, "state") == false then

				parse("trigger " .. entity(shop.gatex, shop.gatey, "name") )

			end

			for _, door in pairs(shop.doors) do

				for _, e in pairs( EntityList ) do

					if entity(e.x, e.y, "name") == door and not tile(e.x, e.y, "walkable") then

						-- Func_DynWall ?

						parse("trigger "..door)

					end

				end

			end

		end

	end

end

function shop_hook()

	coroutine.yield()

end

function openshops()

	shop_coro = coroutine.create(shop_loop)

	debug.sethook(shop_coro, shop_hook, "l", 100)

end

addhook("ms100", "shop_process")
function shop_process()

	if shop_coro then

		if coroutine.status(shop_coro) == "dead" then

			shop_coro = nil

		else

			coroutine.resume(shop_coro)

		end

	end

end

Edit: Just realized that entitylist() is a expensive task too, and you were calling it every time inside the shops loop.

old Re: function is lagging

francis007
BANNED Off Offline

Quote
It will open the shop if none is the owner and the door is closed.

@user Yates All shops are the same. two doors, one env_hurt and a green button for taking the shop.
1
2
3
4
5
6
7
8
9
10
11
12
13
shops = {}
shops[0] = {doors={}} 
 
shops[1] = {
gatex = 43,
gatey = 10,
button = "shop1",
name = "Rifle Shop",
doors = {
[1] = "sh",
[2] = "sh1"
}
}

old Re: function is lagging

Rainoth
Moderator Off Offline

Quote
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
shops = {}

for k,v in pairs (entitylist()) do
	if entity(v.x,v.y,"name"):sub(1,4)=="shop" and entity(v.x,v.y,"type")~= 93 then
		table.insert(shops,tonumber(entity(x,y,"name"):sub(5,6)),{x,y})
	end
end

function openShop(shopID)
	local shop = shops[shopID] -- our shop
	if shop then -- if the shop exists
		for k,v in pairs(shop) do -- our shop's triggers all the doors it has
			if entity(v.x, v.y, "state")==false then -- trigger them if needed
				parse("trigger "..entity(v.x, v.y, "name"))
			end
		end
	end
end

addhook("usebutton","_ub")
function _ub(id,x,y)
	if entity(x,y,"name"):sub(1,4) == "shop" then
		openShop(tonumber(entity(x,y,"name"):sub(5,6)))
	end
end

--[[ 
Essentially what this does is when you start the script (in other words, when the map is loaded) it'll go through all entities once and if
any of them contain the name "shop", it'll add them to 'shops' table
Example of a dyn_wall entity for a shop
	Name: shop01aaa
	Trigger: 
Another example of a dyn_wall entity for a shop
	Name: shop01gate
	Trigger: 
	
This works with all entities except for buttons (since you'll be using those to trigger other things)
So you're not constrained to just using the walls.
The limit of shops is 99.
]]
So something like this? See if it works. Oh and for the record, I left line 13 the same as yours since while reading documentation DC had written there that this variable is fcked so I didn't bother to test it out and see what value it gets when dyn walls are closed/open.

old Re: function is lagging

Starkkz
Moderator Off Offline

Quote
@user francis007: You could try placing the entitylist() call outside the loop, cs2d lua cmd entitylist is a expensive function.

1
2
3
4
5
6
7
8
9
function openshops()

	local EntityList = entitylist()
 
	for they, shop in pairs(shops) do

		local Entity
     
		for _, e in pairs( EntityList ) do

old lulzmath

VADemon
User Off Offline

Quote
This thread should be pinned to a Hall of Fame.

His "algorithm" (laggorithm) does:
(#shops * #entities) + (#shops * #shopDoors * #entities)
iterations. That is 256050 iterations for the worst-worster-worstestest case if I'm correct.

In numbers:
The latest map that fulfills the requirements should be
• GP.Roleplay_V7.5 with 2845 entities
• Suppose 5-15 shops
• Suppose 1-5 doors per shop

° Calls of entitylist() =
#shops + (#shop * #shopDoors)

      > min 10 - max 90
° Calls of entity() =
#shops * #entities + #shops

     
or = (#shops * #entities) + #shops*2 + (#shops * #doors * #entities)

      > min 14230 - max 42690
      > or: min 28460 - max 256080

90 calls of cs2d lua cmd entitylist take 400ms of time on my potato-ish PC (which is surely still twice as fast as his UltraPotatoOnion)
14230 calls of cs2d lua cmd entity for "name": 270ms
28460 calls of cs2d lua cmd entity for "name": 520ms (^ alternatively)
42675 (15*2845) calls of cs2d lua cmd entity for "state": 780ms

The resulting freeze is beyond limits of my imagination.

properly tabbed Laggorithm >
edited 1×, last 13.02.17 01:26:10 am
To the start Previous 1 Next To the start
Log in to reply Scripts overviewCS2D overviewForums overview