title: Why is gRPC so much slower than an HTTP API sending an array
body: <p>I'm doing load tests between services implemented in Node.JS, both services on the same machine connected through <code>localhost</code>.</p>
  <p>There are REST and gRPC client &amp; server files. The main goal is to prove that gRPC is faster than an HTTP call because the use of HTTP/2, the use of protocol buffers that are more efficient than code/decode JSON...</p>
  <p>But in my tests (sending an integer array) gRPC is so much slower.</p>
  <p>The code is very simple for boths implementations, I have an auxiliar class to generate objects with sizes (in MB): 0.125, 0.25, 0.5, 1, 2, 5, 20. REST and gRPC server uses this auxiliar class so the object to send is the same.</p>
  <p>The object send in the payload is like this:</p>
  <pre class="lang-js prettyprint-override"><code>{
    message: &quot;Hello world&quot;,
    array: []
  }
  </code></pre>
  <p>Where the array is filled with numbers until get the desired size.</p>
  <p>And my .proto is like this:</p>
  <pre class="lang-protobuf prettyprint-override"><code>syntax = &quot;proto3&quot;;
  
  service ExampleService {
      rpc GetExample (Size) returns (Example) {}
  }
  
  message Size {
      int32 size = 1;
  }
  
  message Example {
     string message = 1;
     repeated int32 array = 2;
  }
  </code></pre>
  <p>Also I've running the application measuring only one call, to not create a loop and find the average, and also to not handle measuring time with callbacks. So I'm running the application 10 times and calculating the average.</p>
  <p>REST server:</p>
  <pre class="lang-js prettyprint-override"><code>app.get('/:size',(req,res) =&gt; {
      const size = req.params.size
      res.status(200).send(objects[size])
  })
  </code></pre>
  <p>REST client:</p>
  <pre class="lang-js prettyprint-override"><code>const start = performance.now()
  const response = await axios.get(`http://localhost:8080/${size}`)
  const end = performance.now()
  </code></pre>
  <p>gRPC server:</p>
  <pre class="lang-js prettyprint-override"><code>getExample:(call, callback) =&gt; {
      callback(null, objects.objects[call.request.size])
  }
  </code></pre>
  <p>And gRPC client:</p>
  <pre class="lang-js prettyprint-override"><code>const start = performance.now()
  client.getExample({ size: size }, (error, response) =&gt; {
      const end = performance.now()
  })
  </code></pre>
  <p>To do more efficently I have tried:</p>
  <ol>
  <li>Compress data like this:</li>
  </ol>
  <pre class="lang-js prettyprint-override"><code>let server = new grpc.Server({
      'grpc.default_compression_level': 3, // (1-&gt;Low -- 3-&gt;High)
  });
  </code></pre>
  <p>I know I can use <code>streaming</code> to get data and iterate over the array but I want to prove the &quot;same call&quot; in both methods.</p>
  <p>And the difference is so big.</p>
  <p>Other thing I've seen is that times using REST way are more &quot;lineal&quot; the difference between times is small, but using gRPC one call sending 2MB can be 220ms and the next one 500ms.</p>
  <p>Here is the final comparision, as you can see the difference is considerably big.</p>
  <p>Data:</p>
  <div class="s-table-container">
  <table class="s-table">
  <thead>
  <tr>
  <th>Size (MB)</th>
  <th>REST (ms)</th>
  <th>gRPC (ms)</th>
  </tr>
  </thead>
  <tbody>
  <tr>
  <td>0,125</td>
  <td>37.98976998329162</td>
  <td>35.5489800453186</td>
  </tr>
  <tr>
  <td>0,25</td>
  <td>40.03781998157501</td>
  <td>46.077759981155396</td>
  </tr>
  <tr>
  <td>0,5</td>
  <td>51.35283002853394</td>
  <td>59.37109994888306</td>
  </tr>
  <tr>
  <td>1</td>
  <td>63.4725800037384</td>
  <td>166.7616500457128</td>
  </tr>
  <tr>
  <td>2</td>
  <td>95.76031665007274</td>
  <td>394.2442199707031</td>
  </tr>
  <tr>
  <td>5</td>
  <td>261.9365399837494</td>
  <td>804.1371199131012</td>
  </tr>
  <tr>
  <td>20</td>
  <td>713.1867599964141</td>
  <td>5492.330539941788</td>
  </tr>
  </tbody>
  </table>
  </div>
  <p><a href="https://i.stack.imgur.com/m4eJW.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/m4eJW.png" alt="enter image description here" /></a></p>
  <p>But I thought... maybe the array field can't be decode in an efficient way, maybe is the integer number which is not heavy for JSON... I don't know, so I'm going to try to send a string, a very huge large string.</p>
  <p>So my proto file now looks like this:</p>
  <pre class="lang-protobuf prettyprint-override"><code>syntax = &quot;proto3&quot;;
  
  service ExampleService {
      rpc GetExample (Size) returns (Example) {}
  }
  
  message Size {
      int32 size = 1;
  }
  
  message Example {
     string message = 1;
     string array = 2;
  }
  </code></pre>
  <p>Now the object send is like this:</p>
  <pre class="lang-js prettyprint-override"><code>{
    message: &quot;Hello world&quot;,
    array: &quot;text to reach the desired MB&quot;
  }
  </code></pre>
  <p>And results are so differents, now gRPC is much more efficient.</p>
  <p>Data:</p>
  <div class="s-table-container">
  <table class="s-table">
  <thead>
  <tr>
  <th>Size (MB)</th>
  <th>REST (ms)</th>
  <th>gRPC (ms)</th>
  </tr>
  </thead>
  <tbody>
  <tr>
  <td>0,125</td>
  <td>30.672580003738403</td>
  <td>25.028959941864013</td>
  </tr>
  <tr>
  <td>0,25</td>
  <td>33.568540048599246</td>
  <td>25.366739988327026</td>
  </tr>
  <tr>
  <td>0,5</td>
  <td>37.19938006401062</td>
  <td>27.539460039138795</td>
  </tr>
  <tr>
  <td>1</td>
  <td>46.4020166794459</td>
  <td>28.798949996630352</td>
  </tr>
  <tr>
  <td>2</td>
  <td>57.50188330809275</td>
  <td>35.45066670576731</td>
  </tr>
  <tr>
  <td>5</td>
  <td>107.39933327833812</td>
  <td>48.90079998970032</td>
  </tr>
  <tr>
  <td>20</td>
  <td>313.4138665994008</td>
  <td>136.4138500293096</td>
  </tr>
  </tbody>
  </table>
  </div>
  <p><a href="https://i.stack.imgur.com/oYoC3.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/oYoC3.png" alt="enter image description here" /></a></p>
  <p>And the question: So, why sending an integer array is not as efficient as sending an string? Is the way protobuf encode/decode arrays? Is not efficient send <code>repeated</code> values?  Is related with the language (JS)?</p>