title: Node.js - Socket.io performance
body: <p>I am using node.js and socket.io to run a multiplayer game I have made. It basically loops 30/sec and sends the data to all clients.</p>
  
  <p>I only send the necessary data for each client to the way I built my app was:
   - When a socket connects I store it on a global object
   - At the end of the every loop I loop through this object and I send the necessary that for each socket (data about players and other objects around him).</p>
  
  <p>I am not having any network problems I was able to make this game run with low bandwidth usage but to reduce the bandwidth usage I had to choose to use more CPU.</p>
  
  <p>Once I have around 40-50 players online I use about 50% of my CPU so the game becomes very slow. I would not really care if I could make it use 50% of the CPU without making the game slow if it is possible and anyone knows how to do that please tell me. I had created a CPU profile and for what I see the program is about 72% the time idle and the functions the consume more time are all from Socket.io so I can´t really improve them.</p>
  
  <p>I see that games like agar.io can handle 500 player per room, I would like to handle 100-150.</p>
  
  <p>Is socket.io using too much CPU because I loop through every socket and use socket.emit() for each one instead of using io.emit() and send the same data to everyone?</p>
  
  <p>What could I do to improve my server performance and reduce the CPU usage without having to consume more bandwith?</p>
  
  <p>I am running Ubuntu 16.04 LTS.</p>
  
  <p>Part of my server CPU profile (ordered by Self Time):</p>
  
  <p>Self time        -  Total time     - Function</p>
  
  <pre><code>10947.3 ms  10947.3 ms  (idle)(program):1   
  578.8 ms 14.28 %    612.1 ms 15.10 %    _hasBinary/home/daniel/server/node_modules/socket.io/node_modules/has-binary/index.js:25    
  559.0 ms 13.79 %    559.0 ms13.79 % write(program):1    
  375.8 ms 9.27 % 375.8 ms9.27 %  encodeAsString/home/daniel/server/node_modules/socket.io/node_modules/socket.io-parser/index.js:147 
  220.7 ms 5.45 % 220.7 ms 5.45 % writeBuffer(program):1  
  106.2 ms 2.62 % 106.2 ms 2.62 % (program)(program):1    
  83.3 ms 2.05 %  83.3 ms 2.05 %  self.inSameWindow/home/daniel/server/app.js:370 
  78.1 ms 1.93 %  152.0 ms 3.75 % Bufferbuffer.js:47  
  71.8 ms 1.77 %  1238.8 ms 30.57 %   Socket.emit/home/daniel/server/node_modules/socket.io/lib/socket.js:126 
  66.6 ms 1.64 %  250.9 ms 6.19 % self.updateSpeed/home/daniel/server/app.js:332  
  65.6 ms 1.62 %  65.6 ms 1.62 %  self.downBumper/home/daniel/server/app.js:145   
  64.5 ms 1.59 %  64.5 ms 1.59 %  self.rightBumper/home/daniel/server/app.js:142  
  64.5 ms 1.59 %  64.5 ms 1.59 %  self.leftBumper/home/daniel/server/app.js:139   
  59.3 ms 1.46 %  59.3 ms 1.46 %  self.upBumper/home/daniel/server/app.js:136 
  58.3 ms 1.44 %  172.8 ms 4.26 % self.fixOverCollision/home/daniel/server/app.js:151 
  58.3 ms 1.44 %  58.3 ms 1.44 %  self.updateSquat/home/daniel/server/app.js:323  
  58.3 ms 1.44 %  58.3 ms 1.44 %  self.updatePosition/home/daniel/server/app.js:59    
  55.2 ms 1.36 %  55.2 ms 1.36 %  self.updateSprite/home/daniel/server/app.js:305 
  55.2 ms 1.36 %  55.2 ms 1.36 %  self.getUpdatePack/home/daniel/server/app.js:394    
  51.0 ms 1.26 %  51.0 ms 1.26 %  addListenerevents.js:191    
  51.0 ms 1.26 %  2026.9 ms 50.01 %   (anonymous function)/home/daniel/server/app.js:681  
  39.6 ms 0.98 %  39.6 ms 0.98 %  byteLengthUtf8(program):1   
  39.6 ms 0.98 %  143.7 ms 3.54 % readableAddChunk_stream_readable.js:123 
  34.4 ms 0.85 %  153.0 ms 3.78 % emitNoneevents.js:65    
  34.4 ms 0.85 %  34.4 ms 0.85 %  (garbage collector)(program):1  
  32.3 ms 0.80 %  254.0 ms 6.27 % createWriteReqnet.js:697    
  31.2 ms 0.77 %  42.7 ms 1.05 %  Buffer.writebuffer.js:523   
  30.2 ms 0.74 %  78.1 ms 1.93 %  Readable.on_stream_readable.js:664  
  29.1 ms 0.72 %  30.2 ms 0.74 %  nextTicknode.js:477 
  29.1 ms 0.72 %  678.7 ms 16.75 %    PerMessageDeflate.compress/home/daniel/server/node_modules/socket.io/node_modules/engine.io/node_modules/ws/lib/PerMessageDeflate.js:289    
  28.1 ms 0.69 %  34.4 ms 0.85 %  module.exports.collidingBlock/home/daniel/server/server/map.js:213  
  27.1 ms 0.67 %  372.7 ms 9.20 % emitevents.js:117   
  26.0 ms 0.64 %  26.0 ms 0.64 %  slice
  </code></pre>
  
  <p>This is how I loop through every socket:</p>
  
  <pre><code> //LOOP
  var initPack = {player:[], bullet:[]};
  var removePack = {player:[], bullet:[]};
  setInterval(function(){
      var pack = {
          player: Player.update(),
          bullet: Bullet.update()
      };
      for(var i in SOCKET_LIST){
          var socket = SOCKET_LIST[i];
          var socket_pack = {
              player:[], 
              bullet:[]
          };
  
          if(initPack.player.length &gt; 0 || initPack.bullet.length &gt; 0)
              socket.emit("init", initPack);
  
          //Get the pack for specific socket
          if(typeof Player.list[i] != "undefined"){
              var player = Player.list[i];
              //Get players around
              for(var a = 0; a &lt; pack.player.length; a++){
                  if(player.inSameWindow(pack.player[a].x, pack.player[a].y))
                      socket_pack.player.push(pack.player[a]);
              }
              //Get bullets around
              for(var a = 0; a &lt; pack.bullet.length; a++){
                  if(player.inSameWindow(pack.bullet[a].x, pack.bullet[a].y))
                      socket_pack.bullet.push(pack.bullet[a]);
              }
          }
          socket.emit("update", socket_pack);
  
          if(removePack.player.length &gt; 0 || removePack.bullet.length &gt; 0)
              socket.emit("remove", removePack);
  
          if(Game.widgetDataChanged){
              socket.emit("widget", Game.getWidgetPack());
          }
      }
      Game.widgetDataChanged = false;
      initPack.player = [];
      initPack.bullet = [];
      removePack.player = [];
      removePack.bullet = [];
  
  }, 1000/30);
  </code></pre>