English function is lagging

16 replies
Goto Page
To the start Previous 1 Next To the start
02.01.17 05:52:15 pm
Up
francis007
BANNED
Offline Off
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?

Code:
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
02.01.17 06:08:31 pm
Up
Yates
Reviewer
Offline Off
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
02.01.17 06:09:41 pm
Up
Starkkz
Moderator
Offline Off
Does it still work?

Code:
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.
lol
02.01.17 06:35:33 pm
Up
francis007
BANNED
Offline Off
@user Starkkz There are still fps drops.
02.01.17 06:44:27 pm
Up
Bowlinghead
User
Offline Off
Do you have constant lags or just every minute (when the function is called)?
hat Windows aus einer VM installiert
02.01.17 06:48:33 pm
Up
francis007
BANNED
Offline Off
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.
02.01.17 06:59:17 pm
Up
Starkkz
Moderator
Offline Off
Code:
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?
lol
02.01.17 08:20:52 pm
Up
francis007
BANNED
Offline Off
@user Starkkz It's worse now.

Image
02.01.17 08:31:12 pm
Up
Rainoth
Moderator
Online On
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.
MAL • Carnage • DeviantArt •
Quote:
Dude, come on, realism isn't always what people like. Just ask people enjoying hentai.
02.01.17 11:57:07 pm
Up
Starkkz
Moderator
Offline Off
@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.
Code:
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.
lol
03.01.17 12:31:29 am
Up
francis007
BANNED
Offline Off
@user Starkkz Nothing happens if i call the function, thanks anyway i'll use your first code.
03.01.17 12:40:11 am
Up
Rainoth
Moderator
Online On
Okay, you got me interested.
What is this code supposed to do, user francis007?
MAL • Carnage • DeviantArt •
Quote:
Dude, come on, realism isn't always what people like. Just ask people enjoying hentai.
03.01.17 01:20:10 am
Up
francis007
BANNED
Offline Off
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.
Code:
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"
}
}
03.01.17 02:41:30 am
Up
Rainoth
Moderator
Online On
Code:
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.
MAL • Carnage • DeviantArt •
Quote:
Dude, come on, realism isn't always what people like. Just ask people enjoying hentai.
03.01.17 02:41:31 pm
Up
Starkkz
Moderator
Offline Off
@user francis007: You could try placing the entitylist() call outside the loop, cs2d lua cmd entitylist is a expensive function.

Code:
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
lol
13.02.17 12:57:34 am
Up
VADemon
User
Offline Off
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
14.02.17 06:28:24 pm
Up
MikuAuahDark
User
Offline Off
Why do you not localize the global function which is used in loop (like cs2d lua cmd entity)? They'll faster to access when localized.
AuahDark strikes again for one more time in Pixel Art server.
To the start Previous 1 Next To the start