• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1'use strict';
2
3// test HTTP throughput in fragmented header case
4const common = require('../common.js');
5const net = require('net');
6
7const bench = common.createBenchmark(main, {
8  len: [1, 4, 8, 16, 32, 64, 128],
9  n: [5, 50, 500, 2000],
10  type: ['send'],
11});
12
13
14function main({ len, n }) {
15  let todo = [];
16  const headers = [];
17  // Chose 7 because 9 showed "Connection error" / "Connection closed"
18  // An odd number could result in a better length dispersion.
19  for (let i = 7; i <= 7 * 7 * 7; i *= 7)
20    headers.push('o'.repeat(i));
21
22  function WriteHTTPHeaders(channel, has_keep_alive, extra_header_count) {
23    todo = [];
24    todo.push('GET / HTTP/1.1');
25    todo.push('Host: localhost');
26    todo.push('Connection: keep-alive');
27    todo.push('Accept: text/html,application/xhtml+xml,' +
28              'application/xml;q=0.9,image/webp,*/*;q=0.8');
29    todo.push('User-Agent: Mozilla/5.0 (X11; Linux x86_64) ' +
30              'AppleWebKit/537.36 (KHTML, like Gecko) ' +
31              'Chrome/39.0.2171.71 Safari/537.36');
32    todo.push('Accept-Encoding: gzip, deflate, sdch');
33    todo.push('Accept-Language: en-US,en;q=0.8');
34    for (let i = 0; i < extra_header_count; i++) {
35      // Utilize first three powers of a small integer for an odd cycle and
36      // because the fourth power of some integers overloads the server.
37      todo.push(`X-Header-${i}: ${headers[i % 3]}`);
38    }
39    todo.push('');
40    todo.push('');
41    todo = todo.join('\r\n');
42    // Using odd numbers in many places may increase length coverage.
43    const chunksize = 37;
44    for (let i = 0; i < todo.length; i += chunksize) {
45      const cur = todo.slice(i, i + chunksize);
46      channel.write(cur);
47    }
48  }
49
50  const min = 10;
51  let size = 0;
52  const mod = 317;
53  const mult = 17;
54  const add = 11;
55  let count = 0;
56  const PIPE = process.env.PIPE_NAME;
57  const socket = net.connect(PIPE, () => {
58    bench.start();
59    WriteHTTPHeaders(socket, 1, len);
60    socket.setEncoding('utf8');
61    socket.on('data', (d) => {
62      let did = false;
63      let pattern = 'HTTP/1.1 200 OK\r\n';
64      if ((d.length === pattern.length && d === pattern) ||
65          (d.length > pattern.length &&
66           d.slice(0, pattern.length) === pattern)) {
67        did = true;
68      } else {
69        pattern = 'HTTP/1.1 ';
70        if ((d.length === pattern.length && d === pattern) ||
71            (d.length > pattern.length &&
72             d.slice(0, pattern.length) === pattern)) {
73          did = true;
74        }
75      }
76      size = (size * mult + add) % mod;
77      if (did) {
78        count += 1;
79        if (count === n) {
80          bench.end(count);
81          process.exit(0);
82        } else {
83          WriteHTTPHeaders(socket, 1, min + size);
84        }
85      }
86    });
87    socket.on('close', () => {
88      console.log('Connection closed');
89    });
90
91    socket.on('error', () => {
92      throw new Error('Connection error');
93    });
94  });
95}
96