gamedig / node-gamedig

Query game servers and not only! Node.JS/Deno/Bun or Bash (via the CLI).
https://www.npmjs.com/package/gamedig
MIT License
607 stars 146 forks source link

Higher CPU usage on v2.0.20 vs v1.0.49 #176

Closed bbashy closed 3 years ago

bbashy commented 4 years ago

Hi,

So yesterday I updated my scanning tool to use the latest gamedig (v2.0.20) having used v1.0.49 for ages. I'm now getting much higher CPU usage to scan the same number of game servers.

Scanning 90 servers through queued jobs using Redis (as before) now pushes around 80% CPU for a a few seconds while scanning 10 at a time. Before this was around 30% CPU usage for the same amount of game servers.

Is there anything I can do to reduce the CPU resources this needs?

mmorrisontx commented 4 years ago

Gamedig shouldn't use anywhere near that much cpu. The vast majority of the request time is spent waiting for network IO, and compared to that, the actual cpu processing should just be a flash in the pan. Are you able to connect the nodejs chrome inspector and get a cpu usage flame chart? It should make it pretty clear where the cpu is getting used in your specific case.

bbashy commented 4 years ago

Thanks for the reply. I've since moved to a more powerful server (from 4c/8t to 8c/16t) and now using NVMe instead of slow old HDDs in RAID 1. Also upgraded from nodejs v10 to v12.

It seems to only use 2-3% per scan process so I may try upgrade gamedig again and see what I get.

Will update you when I do it.

bbashy commented 4 years ago

Updated to gamedig@2.0.23 and while I'm not scanning as many game servers (22), it's around 4-5% per instance now.

See how it goes but I think it was CSGO causing it mainly. The wait time to get the response is 2s?

$ time gamedig --type csgo 123.123.123.123:14334
{"name":"Test - free @ fshost.me","map":"de_mirage","password":true,"raw":{"protocol":17,"folder":"csgo","game":"Counter-Strike: Global Offensive","steamappid":730,"numplayers":3,"numbots":0,"listentype":"d","environment":"l","secure":1,"version":"1.37.6.8","steamid":"652653939220220315","tags":"secure","gameid":"730","rules":{}},"maxplayers":12,"players":[{"name":"xxx","score":25,"time":2605.57861328125},{"name":"xxx","score":41,"time":2604.6728515625},{"name":"xxx","score":22,"time":1793.701904296875}],"bots":[],"connect":"123.123.123.123:14334","ping":29}

gamedig --type csgo 123.123.123.123:14334  0.09s user 0.01s system 4% cpu 2.177 total
mmorrisontx commented 4 years ago

Can you run it with --debug? 2 seconds doesn't seem too unreasonable, since it includes the nodejs process startup, and the srcds query protocol requires several round trips.

Are you running every query separately using the cli? Starting up nodejs probably accounts for most of the cpu time you are showing in your example above. If your application was written in node and made multiple calls to the library without having to restart, it would be basically 0 cpu for each additional query.

bbashy commented 4 years ago

Yeah I understand it's not going to be ultra low CPU and it's been fine with 2s delay but if it can be faster, it always helps.

CoD and CS1.6 are fine (200ms total).

Yes, I use it single cli commands through PHP (symfony/console).

$ time gamedig --type csgo 123.123.123.123:15767 --debug
Q#0 Query is running with options: {
  socketTimeout: 2000,
  attemptTimeout: 10000,
  maxAttempts: 1,
  port: 15767,
  protocol: 'valve',
  type: 'csgo',
  host: '123.123.123.123',
  debug: true
}
Q#0 DNS Lookup: 123.123.123.123
Q#0 Raw IP Address: 123.123.123.123
Q#0 Requesting info ...
Q#0 123.123.123.123:15767 UDP-->
Q#0 Buffer length: 25 bytes
ff ff ff ff 54 53 6f 75 72 63 65 20 45 6e 67 69 6e 65 20 51 75
            T  S  o  u  r  c  e     E  n  g  i  n  e     Q  u
65 72 79 00
e  r  y

123.123.123.123:15767 <--UDP
Buffer length: 144 bytes
ff ff ff ff 49 11 44 6f 6f 20 44 6f 6f 20 44 6f 6f 20 2d 20 66
            I     T  e  s     T  x  x     x  x  x     -     f
72 65 65 20 40 20 66 73 68 6f 73 74 2e 6d 65 00 2f 31 32 31 32
r  e  e     @     f  s  h  o  s  t  .  m  e     /  1  2  1  2
36 37 33 33 39 39 2f 64 65 5f 73 68 6f 72 74 64 75 73 74 00 63
6  7  3  3  9  9  /  d  e  _  s  h  o  r  t  d  u  s  t     c
73 67 6f 00 43 6f 75 6e 74 65 72 2d 53 74 72 69 6b 65 3a 20 47
s  g  o     C  o  u  n  t  e  r  -  S  t  r  i  k  e  :     G
6c 6f 62 61 6c 20 4f 66 66 65 6e 73 69 76 65 00 da 02 05 0c 00
l  o  b  a  l     O  f  f  e  n  s  i  v  e
64 6c 01 01 31 2e 33 37 2e 36 2e 38 00 b1 97 3d 1f 3c 1e 00 00
d  l        1  .  3  7  .  6  .  8           =     <
00 30 01 73 65 63 75 72 65 00 da 02 00 00 00 00 00 00
   0     s  e  c  u  r  e

Q#0 Registered RTT: 29ms
Q#0 Received full packet
Q#0 Received 49 expected 49
Q#0 UDP send finished by callback
Q#0 INFO:  {
  protocol: 17,
  folder: 'csgo',
  game: 'Counter-Strike: Global Offensive',
  steamappid: 730,
  numplayers: 5,
  numbots: 0,
  listentype: 'd',
  environment: 'l',
  secure: 1,
  version: '1.37.6.8',
  steamid: '652653939220220315',
  tags: 'secure',
  gameid: '730'
}
Q#0 Requesting player list ...
Q#0 123.123.123.123:15767 UDP-->
Q#0 Buffer length: 9 bytes
ff ff ff ff 55 ff ff ff ff
            U

123.123.123.123:15767 <--UDP
Buffer length: 9 bytes
ff ff ff ff 41 11 5f 7a 0c
            A     _  z

Q#0 Registered RTT: 28ms
Q#0 Received full packet
Q#0 Received 41 expected 44
Q#0 Received new challenge key: 209346321
Q#0 Challenge key changed -- allowing query retry if needed
Q#0 UDP send finished by callback
Q#0 123.123.123.123:15767 UDP-->
Q#0 Buffer length: 9 bytes
ff ff ff ff 55 11 5f 7a 0c
            U     _  z

123.123.123.123:15767 <--UDP
Buffer length: 98 bytes
ff ff ff ff 44 05 00 44 6f 6f 6d 47 75 79 00 27 00 00 00 87 09
            x        x  x  x  x  x  x  x     x
95 44 00 43 52 55 53 48 2e 6d 70 34 00 16 00 00 00 c0 e6 94 44
   x     x  x  x  x  x  x  x  x  x                          x
00 47 6f 64 7a 69 6c 6c 61 00 10 00 00 00 66 dc 93 44 00 53 68
   x  x  x  x  x  x  x  x                 x        x     x  x
65 72 69 66 66 37 31 00 2c 00 00 00 22 e4 88 44 00 41 6c 70 68
x  x  x  x  x  x  x     x           x        x     x  x  x  x
61 20 5a 75 78 00 0c 00 00 00 5a f6 dc 43
x     x  x  x                 x        x

Q#0 Registered RTT: 31ms
Q#0 Received full packet
Q#0 Received 44 expected 44
Q#0 UDP send finished by callback
Q#0 Found player: xxx 39 1192.2977294921875
Q#0 Found player: xxx 22 1191.2109375
Q#0 Found player: xxx 16 1182.887451171875
Q#0 Found player: xxx 44 1095.129150390625
Q#0 Found player: xxx 12 441.92462158203125
Q#0 Requesting rules ...
Q#0 123.123.123.123:15767 UDP-->
Q#0 Buffer length: 9 bytes
ff ff ff ff 56 11 5f 7a 0c
            V     _  z

Q#0 UDP timeout detected
Q#0 UDP timeout resolved by callback
Q#0 Size of players array: 5
Q#0 Size of bots array: 0
Q#0 Query was successful
{
  "name": "Test - free @ fshost.me",
  "map": "/1212673399/de_shortdust",
  "password": true,
  "raw": {
    "protocol": 17,
    "folder": "csgo",
    "game": "Counter-Strike: Global Offensive",
    "steamappid": 730,
    "numplayers": 5,
    "numbots": 0,
    "listentype": "d",
    "environment": "l",
    "secure": 1,
    "version": "1.37.6.8",
    "steamid": "652653939220220315",
    "tags": "secure",
    "gameid": "730",
    "rules": {}
  },
  "maxplayers": 12,
  "players": [
    {
      "name": "xxx",
      "score": 39,
      "time": 1192.2977294921875
    },
    {
      "name": "xxx",
      "score": 22,
      "time": 1191.2109375
    },
    {
      "name": "xxx",
      "score": 16,
      "time": 1182.887451171875
    },
    {
      "name": "xxx",
      "score": 44,
      "time": 1095.129150390625
    },
    {
      "name": "xxx",
      "score": 12,
      "time": 441.92462158203125
    }
  ],
  "bots": [],
  "connect": "123.123.123.123:15767",
  "ping": 28
}
gamedig --type csgo 123.123.123.123:15767 --debug  0.08s user 0.02s system 4% cpu 2.185 total
mmorrisontx commented 4 years ago

CS:GO occasionally does not send a response to the rules query. This is documented here: https://developer.valvesoftware.com/wiki/Server_queries#A2S_RULES

 Warning:   CS:GO Rules reply is broken since update CSGO 1.32.3.0 (Feb 21, 2014). Before the update rules got truncated when exceeding MTU, after the update rules reply is not sent at all. You can also see a console message: [NET] Cannot send connectionless packet to xxx.xxx.xxx.xxx:xxxxx '0x45' exceeding MTU (2644)

If gamedig doesn't receive a response to this request, we continue the query and just leave the rules out of the result. Unfortunately, we do have to wait 2 seconds for the response in order to determine whether or not to throw it out.

If you are certain you don't need any of the state.raw.rules data, you can comment out await this.queryRules(state); in valve.js and save those two seconds when it would otherwise be waiting for the timeout.

bbashy commented 4 years ago

Makes sense. Could we work out something for removing the rules based on a cli param or a way to override your own protocols from games_custom.txt?

The rules never come out for me anyway on CS:GO.

Getting an error when commenting out that (looks like it's to do with the Battalion change I requested before :P);

Q#0 Query failed with error TypeError: Cannot use 'in' operator to search for 'bat_name_s' in undefined
    at Valve.cleanup (node_modules/gamedig/protocols/valve.js:197:26)
mmorrisontx commented 4 years ago

Maybe we should just never query for rules on csgo? I just tried a bunch of popular servers, and only got rules back from one of them. state.raw.rules is part of our unstable api, so changing it between patch releases is acceptable.

bbashy commented 4 years ago

I personally don’t need/use the rules for any games I query so I’d say so.

Make it opt in for rules?

bbashy commented 3 years ago

Thank you for v3 with no rules, CS:GO response time is now 0.338 total instead of 2.177 total as above.

Scanning/doing checks on 140 games servers now only takes around 20 seconds instead of 50-60 seconds.

$ time gamedig --type csgo 123.123.123.123:12345
{"name":"Test - free @ fshost.me","map":"de_nuke","password":true,"raw":{"protocol":17,"folder":"csgo","game":"Counter-Strike: Global Offensive","appId":730,"numplayers":0,"numbots":0,"listentype":"d","environment":"l","secure":1,"version":"1.37.8.3","steamid":"85568392922020866","tags":"empty,secure"},"maxplayers":14,"players":[],"bots":[],"connect":"123.123.123.123:12345","ping":33}
gamedig --type csgo 123.123.123.123:12345  0.10s user 0.02s system 36% cpu 0.338 total