benchmark_server.js 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. /*
  2. *
  3. * Copyright 2015, Google Inc.
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions are
  8. * met:
  9. *
  10. * * Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. * * Redistributions in binary form must reproduce the above
  13. * copyright notice, this list of conditions and the following disclaimer
  14. * in the documentation and/or other materials provided with the
  15. * distribution.
  16. * * Neither the name of Google Inc. nor the names of its
  17. * contributors may be used to endorse or promote products derived from
  18. * this software without specific prior written permission.
  19. *
  20. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  21. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  22. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  23. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  24. * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  25. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  26. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  27. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  28. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  29. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  30. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  31. *
  32. */
  33. /**
  34. * Benchmark server module
  35. * @module
  36. */
  37. 'use strict';
  38. var fs = require('fs');
  39. var path = require('path');
  40. var EventEmitter = require('events');
  41. var util = require('util');
  42. var genericService = require('./generic_service');
  43. var grpc = require('../../../');
  44. var serviceProto = grpc.load({
  45. root: __dirname + '/../../..',
  46. file: 'src/proto/grpc/testing/services.proto'}).grpc.testing;
  47. /**
  48. * Create a buffer filled with size zeroes
  49. * @param {number} size The length of the buffer
  50. * @return {Buffer} The new buffer
  51. */
  52. function zeroBuffer(size) {
  53. var zeros = new Buffer(size);
  54. zeros.fill(0);
  55. return zeros;
  56. }
  57. /**
  58. * Handler for the unary benchmark method. Simply responds with a payload
  59. * containing the requested number of zero bytes.
  60. * @param {Call} call The call object to be handled
  61. * @param {function} callback The callback to call with the response
  62. */
  63. function unaryCall(call, callback) {
  64. var req = call.request;
  65. var payload = {body: zeroBuffer(req.response_size)};
  66. callback(null, {payload: payload});
  67. }
  68. /**
  69. * Handler for the streaming benchmark method. Simply responds to each request
  70. * with a payload containing the requested number of zero bytes.
  71. * @param {Call} call The call object to be handled
  72. */
  73. function streamingCall(call) {
  74. call.on('data', function(value) {
  75. var payload = {body: zeroBuffer(value.response_size)};
  76. call.write({payload: payload});
  77. });
  78. call.on('end', function() {
  79. call.end();
  80. });
  81. }
  82. function makeStreamingGenericCall(response_size) {
  83. var response = zeroBuffer(response_size);
  84. return function streamingGenericCall(call) {
  85. call.on('data', function(value) {
  86. call.write(response);
  87. });
  88. call.on('end', function() {
  89. call.end();
  90. });
  91. };
  92. }
  93. /**
  94. * BenchmarkServer class. Constructed based on parameters from the driver and
  95. * stores statistics.
  96. * @param {string} host The host to serve on
  97. * @param {number} port The port to listen to
  98. * @param {boolean} tls Indicates whether TLS should be used
  99. * @param {boolean} generic Indicates whether to use the generic service
  100. * @param {number=} response_size The response size for the generic service
  101. */
  102. function BenchmarkServer(host, port, tls, generic, response_size) {
  103. var server_creds;
  104. var host_override;
  105. if (tls) {
  106. var key_path = path.join(__dirname, '../test/data/server1.key');
  107. var pem_path = path.join(__dirname, '../test/data/server1.pem');
  108. var key_data = fs.readFileSync(key_path);
  109. var pem_data = fs.readFileSync(pem_path);
  110. server_creds = grpc.ServerCredentials.createSsl(null,
  111. [{private_key: key_data,
  112. cert_chain: pem_data}]);
  113. } else {
  114. server_creds = grpc.ServerCredentials.createInsecure();
  115. }
  116. var server = new grpc.Server();
  117. this.port = server.bind(host + ':' + port, server_creds);
  118. if (generic) {
  119. server.addService(genericService, {
  120. streamingCall: makeStreamingGenericCall(response_size)
  121. });
  122. } else {
  123. server.addProtoService(serviceProto.BenchmarkService.service, {
  124. unaryCall: unaryCall,
  125. streamingCall: streamingCall
  126. });
  127. }
  128. this.server = server;
  129. }
  130. util.inherits(BenchmarkServer, EventEmitter);
  131. /**
  132. * Start the benchmark server.
  133. */
  134. BenchmarkServer.prototype.start = function() {
  135. this.server.start();
  136. this.last_wall_time = process.hrtime();
  137. this.emit('started');
  138. };
  139. /**
  140. * Return the port number that the server is bound to.
  141. * @return {Number} The port number
  142. */
  143. BenchmarkServer.prototype.getPort = function() {
  144. return this.port;
  145. };
  146. /**
  147. * Return current statistics for the server. If reset is set, restart
  148. * statistic collection.
  149. * @param {boolean} reset Indicates that statistics should be reset
  150. * @return {object} Server statistics
  151. */
  152. BenchmarkServer.prototype.mark = function(reset) {
  153. var wall_time_diff = process.hrtime(this.last_wall_time);
  154. if (reset) {
  155. this.last_wall_time = process.hrtime();
  156. }
  157. return {
  158. time_elapsed: wall_time_diff[0] + wall_time_diff[1] / 1e9,
  159. // Not sure how to measure these values
  160. time_user: 0,
  161. time_system: 0
  162. };
  163. };
  164. /**
  165. * Stop the server.
  166. * @param {function} callback Called when the server has finished shutting down
  167. */
  168. BenchmarkServer.prototype.stop = function(callback) {
  169. this.server.tryShutdown(callback);
  170. };
  171. module.exports = BenchmarkServer;