timetocode / node-game-loop

node.js accurate game loop
MIT License
40 stars 5 forks source link

Using process.nextTick #1

Open kutase opened 7 years ago

kutase commented 7 years ago

Hi! What about using process.nextTick instead of setTimeout?

timetocode commented 7 years ago

nextTick is a viable alternative to setImmediate, the difference being that nextTick schedules a function to run before i/o, and setImmediate runs after. In truth, their names should be inverted. setImmediate really means 'do it next, after everything else' and nextTick really means 'do it immediately.'

I might experiment with nextTick in a multiplayer game to see how it goes, I haven't tried it. In theory nextTick would run the game loop prior to handling the inbound websocket messages -- which sounds suboptimal but might have its advantages.

Also worth mentioning is that I've been using this game loop for a multiplayer game and I run multiple instances of the game server per vps. The game is throttled down to 10 ticks per second (it has ~600 moving entities and up to ~180 concurrent players). In this scenario I feel like setTimeout, despite its inaccuracy, is much better at sharing the CPU than setImmediate (and in theory nextTick as well).

Also a correction about setTimeout (and setInterval) -- these occur every 4 ms now, not ever 16 ms.

crazyyi commented 7 years ago

@timetocode Hi I have used your method, and tried another slightly modified version of your method node-gameloop but no matter which one I use, my server will be slow as hell after 20 hours. The game will be unplayable by then.

The CPU usage is 30% at the beginning then goes up to 120-140% after 20 hours. There are only less than 100 moving entities in my game and only one or two player will join the game during that time. So it shouldn't be too stretched out.

When I profiled the code it points to the timer.js which is using most of the CPU. I think it is because the setImmediate function is chewing up the CPU. But why is it so? If you can use it in your game without any problem there shouldn't be problem in mine.

Do you have any suggestions? Should I just use setTimeout and forget about the inaccuracy? If not, how to apply the 4ms in the code? I have tried to replace that 16ms in the code with 4ms but the result is unsatisfied. It just looked as if nothing has changed. Server not responding, unable to play...

timetocode commented 7 years ago

This sounds a lot like a leak of entities or physics. Something is probably being created but not removed, such that over time the update loop is iterating through more and more items... gradually degrading performance until it fully freezes or crashes.

Is it really the timer using the CPU? or the function being invoked by the timer that uses CPU?

setTimeout is certainly fine too, it will use a little less cpu

crazyyi commented 7 years ago

@timetocode thanks for your input. I have thought about that before. But even after I skip the 'update' method in gameloop, which means the server does nothing but calculating time and calling itself inside the gameloop function, the CPU usage still stays the same. I've also found that it uses 20% of the CPU on my MacBook Pro at the beginning , but on remote VPS, which is a 4 core Xeon Linux machine, it consumes 35% of CPU at its lowest point.

I really would like to fix the resource leak if I can locate them, but now all the profile methods put timer.js as the top CPU consumer, so I can't any other useful information.

crazyyi commented 7 years ago

@timetocode Oh I have fixed my game crash issue! Thank you for your reply. It is indeed a memory leak that causes the CPU to run GC non-stop. I have searched through so many websites, asked it on many forums and found no clue of the reason of the server crash and I nearly give up using Node.js for my game. But you pointed it out straightaway. Ignore my previous comment, please. I am so happy that my game is alive again.