diff options
Diffstat (limited to 'src/node/performance')
-rw-r--r-- | src/node/performance/benchmark_client.js | 365 | ||||
-rw-r--r-- | src/node/performance/benchmark_client_express.js | 287 | ||||
-rw-r--r-- | src/node/performance/benchmark_server.js | 189 | ||||
-rw-r--r-- | src/node/performance/benchmark_server_express.js | 96 | ||||
-rw-r--r-- | src/node/performance/generic_service.js | 40 | ||||
-rw-r--r-- | src/node/performance/histogram.js | 165 | ||||
-rw-r--r-- | src/node/performance/worker.js | 50 | ||||
-rw-r--r-- | src/node/performance/worker_service_impl.js | 183 |
8 files changed, 0 insertions, 1375 deletions
diff --git a/src/node/performance/benchmark_client.js b/src/node/performance/benchmark_client.js deleted file mode 100644 index 68afb8a633..0000000000 --- a/src/node/performance/benchmark_client.js +++ /dev/null @@ -1,365 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -/** - * Benchmark client module - * @module - */ - -'use strict'; - -var fs = require('fs'); -var path = require('path'); -var util = require('util'); -var EventEmitter = require('events'); - -var async = require('async'); -var _ = require('lodash'); -var PoissonProcess = require('poisson-process'); -var Histogram = require('./histogram'); - -var genericService = require('./generic_service'); - -var grpc = require('../../../'); -var serviceProto = grpc.load({ - root: __dirname + '/../../..', - file: 'src/proto/grpc/testing/services.proto'}).grpc.testing; - -/** - * Create a buffer filled with size zeroes - * @param {number} size The length of the buffer - * @return {Buffer} The new buffer - */ -function zeroBuffer(size) { - var zeros = new Buffer(size); - zeros.fill(0); - return zeros; -} - -/** - * Convert a time difference, as returned by process.hrtime, to a number of - * nanoseconds. - * @param {Array.<number>} time_diff The time diff, represented as - * [seconds, nanoseconds] - * @return {number} The total number of nanoseconds - */ -function timeDiffToNanos(time_diff) { - return time_diff[0] * 1e9 + time_diff[1]; -} - -/** - * The BenchmarkClient class. Opens channels to servers and makes RPCs based on - * parameters from the driver, and records statistics about those RPCs. - * @param {Array.<string>} server_targets List of servers to connect to - * @param {number} channels The total number of channels to open - * @param {Object} histogram_params Options for setting up the histogram - * @param {Object=} security_params Options for TLS setup. If absent, don't use - * TLS - */ -function BenchmarkClient(server_targets, channels, histogram_params, - security_params) { - var options = { - "grpc.max_receive_message_length": -1, - "grpc.max_send_message_length": -1 - }; - var creds; - if (security_params) { - var ca_path; - if (security_params.use_test_ca) { - ca_path = path.join(__dirname, '../test/data/ca.pem'); - var ca_data = fs.readFileSync(ca_path); - creds = grpc.credentials.createSsl(ca_data); - } else { - creds = grpc.credentials.createSsl(); - } - if (security_params.server_host_override) { - var host_override = security_params.server_host_override; - options['grpc.ssl_target_name_override'] = host_override; - options['grpc.default_authority'] = host_override; - } - } else { - creds = grpc.credentials.createInsecure(); - } - - this.clients = []; - var GenericClient = grpc.makeGenericClientConstructor(genericService); - this.genericClients = []; - - for (var i = 0; i < channels; i++) { - this.clients[i] = new serviceProto.BenchmarkService( - server_targets[i % server_targets.length], creds, options); - this.genericClients[i] = new GenericClient( - server_targets[i % server_targets.length], creds, options); - } - - this.histogram = new Histogram(histogram_params.resolution, - histogram_params.max_possible); - - this.running = false; - - this.pending_calls = 0; -}; - -util.inherits(BenchmarkClient, EventEmitter); - -/** - * Start every client in the list of clients by waiting for each to be ready, - * then starting outstanding_rpcs_per_channel calls on each of them - * @param {Array<grpc.Client>} client_list The list of clients - * @param {Number} outstanding_rpcs_per_channel The number of calls to start - * on each client - * @param {function(grpc.Client)} makeCall Function to make a single call on - * a single client - * @param {EventEmitter} emitter The event emitter to send errors on, if - * necessary - */ -function startAllClients(client_list, outstanding_rpcs_per_channel, makeCall, - emitter) { - var ready_wait_funcs = _.map(client_list, function(client) { - return _.partial(grpc.waitForClientReady, client, Infinity); - }); - async.parallel(ready_wait_funcs, function(err) { - if (err) { - emitter.emit('error', err); - return; - } - - _.each(client_list, function(client) { - _.times(outstanding_rpcs_per_channel, function() { - makeCall(client); - }); - }); - }); -} - -/** - * Start a closed-loop test. For each channel, start - * outstanding_rpcs_per_channel RPCs. Then, whenever an RPC finishes, start - * another one. - * @param {number} outstanding_rpcs_per_channel Number of RPCs to start per - * channel - * @param {string} rpc_type Which method to call. Should be 'UNARY' or - * 'STREAMING' - * @param {number} req_size The size of the payload to send with each request - * @param {number} resp_size The size of payload to request be sent in responses - * @param {boolean} generic Indicates that the generic (non-proto) clients - * should be used - */ -BenchmarkClient.prototype.startClosedLoop = function( - outstanding_rpcs_per_channel, rpc_type, req_size, resp_size, generic) { - var self = this; - - self.running = true; - - self.last_wall_time = process.hrtime(); - - self.last_usage = process.cpuUsage(); - - var makeCall; - - var argument; - var client_list; - if (generic) { - argument = zeroBuffer(req_size); - client_list = self.genericClients; - } else { - argument = { - response_size: resp_size, - payload: { - body: zeroBuffer(req_size) - } - }; - client_list = self.clients; - } - - if (rpc_type == 'UNARY') { - makeCall = function(client) { - if (self.running) { - self.pending_calls++; - var start_time = process.hrtime(); - client.unaryCall(argument, function(error, response) { - if (error) { - self.emit('error', new Error('Client error: ' + error.message)); - self.running = false; - return; - } - var time_diff = process.hrtime(start_time); - self.histogram.add(timeDiffToNanos(time_diff)); - makeCall(client); - self.pending_calls--; - if ((!self.running) && self.pending_calls == 0) { - self.emit('finished'); - } - }); - } - }; - } else { - makeCall = function(client) { - if (self.running) { - self.pending_calls++; - var call = client.streamingCall(); - var start_time = process.hrtime(); - call.write(argument); - call.on('data', function() { - var time_diff = process.hrtime(start_time); - self.histogram.add(timeDiffToNanos(time_diff)); - self.pending_calls--; - if (self.running) { - self.pending_calls++; - start_time = process.hrtime(); - call.write(argument); - } else { - call.end(); - if (self.pending_calls == 0) { - self.emit('finished'); - } - } - }); - call.on('error', function(error) { - self.emit('error', new Error('Client error: ' + error.message)); - self.running = false; - }); - } - }; - } - - startAllClients(client_list, outstanding_rpcs_per_channel, makeCall, self); -}; - -/** - * Start a poisson test. For each channel, this initiates a number of Poisson - * processes equal to outstanding_rpcs_per_channel, where each Poisson process - * has the load parameter offered_load. - * @param {number} outstanding_rpcs_per_channel Number of RPCs to start per - * channel - * @param {string} rpc_type Which method to call. Should be 'UNARY' or - * 'STREAMING' - * @param {number} req_size The size of the payload to send with each request - * @param {number} resp_size The size of payload to request be sent in responses - * @param {number} offered_load The load parameter for the Poisson process - * @param {boolean} generic Indicates that the generic (non-proto) clients - * should be used - */ -BenchmarkClient.prototype.startPoisson = function( - outstanding_rpcs_per_channel, rpc_type, req_size, resp_size, offered_load, - generic) { - var self = this; - - self.running = true; - - self.last_wall_time = process.hrtime(); - - self.last_usage = process.cpuUsage(); - - var makeCall; - - var argument; - var client_list; - if (generic) { - argument = zeroBuffer(req_size); - client_list = self.genericClients; - } else { - argument = { - response_size: resp_size, - payload: { - body: zeroBuffer(req_size) - } - }; - client_list = self.clients; - } - - if (rpc_type == 'UNARY') { - makeCall = function(client, poisson) { - if (self.running) { - self.pending_calls++; - var start_time = process.hrtime(); - client.unaryCall(argument, function(error, response) { - if (error) { - self.emit('error', new Error('Client error: ' + error.message)); - self.running = false; - return; - } - var time_diff = process.hrtime(start_time); - self.histogram.add(timeDiffToNanos(time_diff)); - self.pending_calls--; - if ((!self.running) && self.pending_calls == 0) { - self.emit('finished'); - } - }); - } else { - poisson.stop(); - } - }; - } else { - self.emit('error', new Error('Streaming Poisson benchmarks not supported')); - return; - } - - var averageIntervalMs = (1 / offered_load) * 1000; - - startAllClients(client_list, outstanding_rpcs_per_channel, function(client){ - var p = PoissonProcess.create(averageIntervalMs, function() { - makeCall(client, p); - }); - p.start(); - }, self); -}; - -/** - * Return curent statistics for the client. If reset is set, restart - * statistic collection. - * @param {boolean} reset Indicates that statistics should be reset - * @return {object} Client statistics - */ -BenchmarkClient.prototype.mark = function(reset) { - var wall_time_diff = process.hrtime(this.last_wall_time); - var usage_diff = process.cpuUsage(this.last_usage); - var histogram = this.histogram; - if (reset) { - this.last_wall_time = process.hrtime(); - this.last_usage = process.cpuUsage(); - this.histogram = new Histogram(histogram.resolution, - histogram.max_possible); - } - - return { - latencies: { - bucket: histogram.getContents(), - min_seen: histogram.minimum(), - max_seen: histogram.maximum(), - sum: histogram.getSum(), - sum_of_squares: histogram.sumOfSquares(), - count: histogram.getCount() - }, - time_elapsed: wall_time_diff[0] + wall_time_diff[1] / 1e9, - time_user: usage_diff.user / 1000000, - time_system: usage_diff.system / 1000000 - }; -}; - -/** - * Stop the clients. - * @param {function} callback Called when the clients have finished shutting - * down - */ -BenchmarkClient.prototype.stop = function(callback) { - this.running = false; - this.on('finished', callback); -}; - -module.exports = BenchmarkClient; diff --git a/src/node/performance/benchmark_client_express.js b/src/node/performance/benchmark_client_express.js deleted file mode 100644 index 815843fede..0000000000 --- a/src/node/performance/benchmark_client_express.js +++ /dev/null @@ -1,287 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -/** - * Benchmark client module - * @module - */ - -'use strict'; - -var fs = require('fs'); -var path = require('path'); -var util = require('util'); -var EventEmitter = require('events'); -var http = require('http'); -var https = require('https'); - -var async = require('async'); -var _ = require('lodash'); -var PoissonProcess = require('poisson-process'); -var Histogram = require('./histogram'); - -/** - * Convert a time difference, as returned by process.hrtime, to a number of - * nanoseconds. - * @param {Array.<number>} time_diff The time diff, represented as - * [seconds, nanoseconds] - * @return {number} The total number of nanoseconds - */ -function timeDiffToNanos(time_diff) { - return time_diff[0] * 1e9 + time_diff[1]; -} - -function BenchmarkClient(server_targets, channels, histogram_params, - security_params) { - var options = { - method: 'PUT', - headers: { - 'Content-Type': 'application/json' - } - }; - var protocol; - if (security_params) { - var ca_path; - protocol = https; - this.request = _.bind(https.request, https); - if (security_params.use_test_ca) { - ca_path = path.join(__dirname, '../test/data/ca.pem'); - var ca_data = fs.readFileSync(ca_path); - options.ca = ca_data; - } - if (security_params.server_host_override) { - var host_override = security_params.server_host_override; - options.servername = host_override; - } - } else { - protocol = http; - } - - this.request = _.bind(protocol.request, protocol); - - this.client_options = []; - - for (var i = 0; i < channels; i++) { - var host_port; - host_port = server_targets[i % server_targets.length].split(':'); - var new_options = _.assign({hostname: host_port[0], port: +host_port[1]}, options); - this.client_options[i] = new_options; - } - - this.histogram = new Histogram(histogram_params.resolution, - histogram_params.max_possible); - - this.running = false; - - this.pending_calls = 0; -} - -util.inherits(BenchmarkClient, EventEmitter); - -function startAllClients(client_options_list, outstanding_rpcs_per_channel, - makeCall, emitter) { - _.each(client_options_list, function(client_options) { - _.times(outstanding_rpcs_per_channel, function() { - makeCall(client_options); - }); - }); -} - -BenchmarkClient.prototype.startClosedLoop = function( - outstanding_rpcs_per_channel, rpc_type, req_size, resp_size, generic) { - var self = this; - - var options = {}; - - self.running = true; - - if (rpc_type == 'UNARY') { - options.path = '/serviceProto.BenchmarkService.service/unaryCall'; - } else { - self.emit('error', new Error('Unsupported rpc_type: ' + rpc_type)); - } - - if (generic) { - self.emit('error', new Error('Generic client not supported')); - } - - self.last_wall_time = process.hrtime(); - self.last_usage = process.cpuUsage(); - - var argument = { - response_size: resp_size, - payload: { - body: '0'.repeat(req_size) - } - }; - - function makeCall(client_options) { - if (self.running) { - self.pending_calls++; - var start_time = process.hrtime(); - function finishCall(success) { - if (success) { - var time_diff = process.hrtime(start_time); - self.histogram.add(timeDiffToNanos(time_diff)); - } - makeCall(client_options); - self.pending_calls--; - if ((!self.running) && self.pending_calls == 0) { - self.emit('finished'); - } - } - var req = self.request(client_options, function(res) { - var res_data = ''; - res.on('data', function(data) { - res_data += data; - }); - res.on('end', function() { - JSON.parse(res_data); - finishCall(true); - }); - }); - req.write(JSON.stringify(argument)); - req.end(); - req.on('error', function(error) { - if (error.code === 'ECONNRESET' || error.code === 'ETIMEDOUT') { - finishCall(false); - return; - } - self.emit('error', new Error('Client error: ' + error.message)); - self.running = false; - }); - } - } - - startAllClients(_.map(self.client_options, _.partial(_.assign, options)), - outstanding_rpcs_per_channel, makeCall, self); -}; - -BenchmarkClient.prototype.startPoisson = function( - outstanding_rpcs_per_channel, rpc_type, req_size, resp_size, offered_load, - generic) { - var self = this; - - var options = {}; - - self.running = true; - - if (rpc_type == 'UNARY') { - options.path = '/serviceProto.BenchmarkService.service/unaryCall'; - } else { - self.emit('error', new Error('Unsupported rpc_type: ' + rpc_type)); - } - - if (generic) { - self.emit('error', new Error('Generic client not supported')); - } - - self.last_wall_time = process.hrtime(); - self.last_usage = process.cpuUsage(); - - var argument = { - response_size: resp_size, - payload: { - body: '0'.repeat(req_size) - } - }; - - function makeCall(client_options, poisson) { - if (self.running) { - self.pending_calls++; - var start_time = process.hrtime(); - var req = self.request(client_options, function(res) { - var res_data = ''; - res.on('data', function(data) { - res_data += data; - }); - res.on('end', function() { - JSON.parse(res_data); - var time_diff = process.hrtime(start_time); - self.histogram.add(timeDiffToNanos(time_diff)); - self.pending_calls--; - if ((!self.running) && self.pending_calls == 0) { - self.emit('finished'); - } - }); - }); - req.write(JSON.stringify(argument)); - req.end(); - req.on('error', function(error) { - self.emit('error', new Error('Client error: ' + error.message)); - self.running = false; - }); - } else { - poisson.stop(); - } - } - - var averageIntervalMs = (1 / offered_load) * 1000; - - startAllClients(_.map(self.client_options, _.partial(_.assign, options)), - outstanding_rpcs_per_channel, function(opts){ - var p = PoissonProcess.create(averageIntervalMs, function() { - makeCall(opts, p); - }); - p.start(); - }, self); -}; - -/** - * Return curent statistics for the client. If reset is set, restart - * statistic collection. - * @param {boolean} reset Indicates that statistics should be reset - * @return {object} Client statistics - */ -BenchmarkClient.prototype.mark = function(reset) { - var wall_time_diff = process.hrtime(this.last_wall_time); - var usage_diff = process.cpuUsage(this.last_usage); - var histogram = this.histogram; - if (reset) { - this.last_wall_time = process.hrtime(); - this.last_usage = process.cpuUsage(); - this.histogram = new Histogram(histogram.resolution, - histogram.max_possible); - } - - return { - latencies: { - bucket: histogram.getContents(), - min_seen: histogram.minimum(), - max_seen: histogram.maximum(), - sum: histogram.getSum(), - sum_of_squares: histogram.sumOfSquares(), - count: histogram.getCount() - }, - time_elapsed: wall_time_diff[0] + wall_time_diff[1] / 1e9, - time_user: usage_diff.user / 1000000, - time_system: usage_diff.system / 1000000 - }; -}; - -/** - * Stop the clients. - * @param {function} callback Called when the clients have finished shutting - * down - */ -BenchmarkClient.prototype.stop = function(callback) { - this.running = false; - this.on('finished', callback); -}; - -module.exports = BenchmarkClient; diff --git a/src/node/performance/benchmark_server.js b/src/node/performance/benchmark_server.js deleted file mode 100644 index 8d3a2b9049..0000000000 --- a/src/node/performance/benchmark_server.js +++ /dev/null @@ -1,189 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -/** - * Benchmark server module - * @module - */ - -'use strict'; - -var fs = require('fs'); -var path = require('path'); -var EventEmitter = require('events'); -var util = require('util'); - -var genericService = require('./generic_service'); - -var grpc = require('../../../'); -var serviceProto = grpc.load({ - root: __dirname + '/../../..', - file: 'src/proto/grpc/testing/services.proto'}).grpc.testing; - -/** - * Create a buffer filled with size zeroes - * @param {number} size The length of the buffer - * @return {Buffer} The new buffer - */ -function zeroBuffer(size) { - var zeros = new Buffer(size); - zeros.fill(0); - return zeros; -} - -/** - * Handler for the unary benchmark method. Simply responds with a payload - * containing the requested number of zero bytes. - * @param {Call} call The call object to be handled - * @param {function} callback The callback to call with the response - */ -function unaryCall(call, callback) { - var req = call.request; - var payload = {body: zeroBuffer(req.response_size)}; - callback(null, {payload: payload}); -} - -/** - * Handler for the streaming benchmark method. Simply responds to each request - * with a payload containing the requested number of zero bytes. - * @param {Call} call The call object to be handled - */ -function streamingCall(call) { - call.on('data', function(value) { - var payload = {body: zeroBuffer(value.response_size)}; - call.write({payload: payload}); - }); - call.on('end', function() { - call.end(); - }); -} - -function makeUnaryGenericCall(response_size) { - var response = zeroBuffer(response_size); - return function unaryGenericCall(call, callback) { - callback(null, response); - }; -} - -function makeStreamingGenericCall(response_size) { - var response = zeroBuffer(response_size); - return function streamingGenericCall(call) { - call.on('data', function(value) { - call.write(response); - }); - call.on('end', function() { - call.end(); - }); - }; -} - -/** - * BenchmarkServer class. Constructed based on parameters from the driver and - * stores statistics. - * @param {string} host The host to serve on - * @param {number} port The port to listen to - * @param {boolean} tls Indicates whether TLS should be used - * @param {boolean} generic Indicates whether to use the generic service - * @param {number=} response_size The response size for the generic service - */ -function BenchmarkServer(host, port, tls, generic, response_size) { - var server_creds; - var host_override; - if (tls) { - var key_path = path.join(__dirname, '../test/data/server1.key'); - var pem_path = path.join(__dirname, '../test/data/server1.pem'); - - var key_data = fs.readFileSync(key_path); - var pem_data = fs.readFileSync(pem_path); - server_creds = grpc.ServerCredentials.createSsl(null, - [{private_key: key_data, - cert_chain: pem_data}]); - } else { - server_creds = grpc.ServerCredentials.createInsecure(); - } - - var options = { - "grpc.max_receive_message_length": -1, - "grpc.max_send_message_length": -1 - }; - - var server = new grpc.Server(options); - this.port = server.bind(host + ':' + port, server_creds); - if (generic) { - server.addService(genericService, { - unaryCall: makeUnaryGenericCall(response_size), - streamingCall: makeStreamingGenericCall(response_size) - }); - } else { - server.addService(serviceProto.BenchmarkService.service, { - unaryCall: unaryCall, - streamingCall: streamingCall - }); - } - this.server = server; -} - -util.inherits(BenchmarkServer, EventEmitter); - -/** - * Start the benchmark server. - */ -BenchmarkServer.prototype.start = function() { - this.server.start(); - this.last_wall_time = process.hrtime(); - this.last_usage = process.cpuUsage(); - this.emit('started'); -}; - -/** - * Return the port number that the server is bound to. - * @return {Number} The port number - */ -BenchmarkServer.prototype.getPort = function() { - return this.port; -}; - -/** - * Return current statistics for the server. If reset is set, restart - * statistic collection. - * @param {boolean} reset Indicates that statistics should be reset - * @return {object} Server statistics - */ -BenchmarkServer.prototype.mark = function(reset) { - var wall_time_diff = process.hrtime(this.last_wall_time); - var usage_diff = process.cpuUsage(this.last_usage); - if (reset) { - this.last_wall_time = process.hrtime(); - this.last_usage = process.cpuUsage(); - } - return { - time_elapsed: wall_time_diff[0] + wall_time_diff[1] / 1e9, - time_user: usage_diff.user / 1000000, - time_system: usage_diff.system / 1000000 - }; -}; - -/** - * Stop the server. - * @param {function} callback Called when the server has finished shutting down - */ -BenchmarkServer.prototype.stop = function(callback) { - this.server.tryShutdown(callback); -}; - -module.exports = BenchmarkServer; diff --git a/src/node/performance/benchmark_server_express.js b/src/node/performance/benchmark_server_express.js deleted file mode 100644 index 73e54091a4..0000000000 --- a/src/node/performance/benchmark_server_express.js +++ /dev/null @@ -1,96 +0,0 @@ -/* - * - * Copyright 2016 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -/** - * Benchmark server module - * @module - */ - -'use strict'; - -var fs = require('fs'); -var path = require('path'); -var http = require('http'); -var https = require('https'); -var EventEmitter = require('events'); -var util = require('util'); - -var express = require('express'); -var bodyParser = require('body-parser'); - -function unaryCall(req, res) { - var reqObj = req.body; - var payload = {body: '0'.repeat(reqObj.response_size)}; - res.json(payload); -} - -function BenchmarkServer(host, port, tls, generic, response_size) { - var app = express(); - app.use(bodyParser.json()); - app.put('/serviceProto.BenchmarkService.service/unaryCall', unaryCall); - this.input_host = host; - this.input_port = port; - if (tls) { - var credentials = {}; - var key_path = path.join(__dirname, '../test/data/server1.key'); - var pem_path = path.join(__dirname, '../test/data/server1.pem'); - - var key_data = fs.readFileSync(key_path); - var pem_data = fs.readFileSync(pem_path); - credentials['key'] = key_data; - credentials['cert'] = pem_data; - this.server = https.createServer(credentials, app); - } else { - this.server = http.createServer(app); - } -} - -util.inherits(BenchmarkServer, EventEmitter); - -BenchmarkServer.prototype.start = function() { - var self = this; - this.server.listen(this.input_port, this.input_hostname, function() { - self.last_wall_time = process.hrtime(); - self.last_usage = process.cpuUsage(); - self.emit('started'); - }); -}; - -BenchmarkServer.prototype.getPort = function() { - return this.server.address().port; -}; - -BenchmarkServer.prototype.mark = function(reset) { - var wall_time_diff = process.hrtime(this.last_wall_time); - var usage_diff = process.cpuUsage(this.last_usage); - if (reset) { - this.last_wall_time = process.hrtime(); - this.last_usage = process.cpuUsage(); - } - return { - time_elapsed: wall_time_diff[0] + wall_time_diff[1] / 1e9, - time_user: usage_diff.user / 1000000, - time_system: usage_diff.system / 1000000 - }; -}; - -BenchmarkServer.prototype.stop = function(callback) { - this.server.close(callback); -}; - -module.exports = BenchmarkServer; diff --git a/src/node/performance/generic_service.js b/src/node/performance/generic_service.js deleted file mode 100644 index 8e76c50d58..0000000000 --- a/src/node/performance/generic_service.js +++ /dev/null @@ -1,40 +0,0 @@ -/* - * - * Copyright 2016 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -var _ = require('lodash'); - -module.exports = { - 'unaryCall' : { - path: '/grpc.testing.BenchmarkService/UnaryCall', - requestStream: false, - responseStream: false, - requestSerialize: _.identity, - requestDeserialize: _.identity, - responseSerialize: _.identity, - responseDeserialize: _.identity - }, - 'streamingCall' : { - path: '/grpc.testing.BenchmarkService/StreamingCall', - requestStream: true, - responseStream: true, - requestSerialize: _.identity, - requestDeserialize: _.identity, - responseSerialize: _.identity, - responseDeserialize: _.identity - } -}; diff --git a/src/node/performance/histogram.js b/src/node/performance/histogram.js deleted file mode 100644 index a03f2c13a2..0000000000 --- a/src/node/performance/histogram.js +++ /dev/null @@ -1,165 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -/** - * Histogram module. Exports the Histogram class - * @module - */ - -'use strict'; - -/** - * Histogram class. Collects data and exposes a histogram and other statistics. - * This data structure is taken directly from src/core/support/histogram.c, but - * pared down to the statistics needed for client stats in - * test/proto/benchmarks/stats.proto. - * @constructor - * @param {number} resolution The histogram's bucket resolution. Must be positive - * @param {number} max_possible The maximum allowed value. Must be greater than 1 - */ -function Histogram(resolution, max_possible) { - this.resolution = resolution; - this.max_possible = max_possible; - - this.sum = 0; - this.sum_of_squares = 0; - this.multiplier = 1 + resolution; - this.count = 0; - this.min_seen = max_possible; - this.max_seen = 0; - this.buckets = []; - for (var i = 0; i < this.bucketFor(max_possible) + 1; i++) { - this.buckets[i] = 0; - } -} - -/** - * Get the bucket index for a given value. - * @param {number} value The value to check - * @return {number} The bucket index - */ -Histogram.prototype.bucketFor = function(value) { - return Math.floor(Math.log(value) / Math.log(this.multiplier)); -}; - -/** - * Get the minimum value for a given bucket index - * @param {number} The bucket index to check - * @return {number} The minimum value for that bucket - */ -Histogram.prototype.bucketStart = function(index) { - return Math.pow(this.multiplier, index); -}; - -/** - * Add a value to the histogram. This updates all statistics with the new - * value. Those statistics should not be modified except with this function - * @param {number} value The value to add - */ -Histogram.prototype.add = function(value) { - // Ensure value is a number - value = +value; - this.sum += value; - this.sum_of_squares += value * value; - this.count++; - if (value < this.min_seen) { - this.min_seen = value; - } - if (value > this.max_seen) { - this.max_seen = value; - } - this.buckets[this.bucketFor(value)]++; -}; - -/** - * Get the mean of all added values - * @return {number} The mean - */ -Histogram.prototype.mean = function() { - return this.sum / this.count; -}; - -/** - * Get the variance of all added values. Used to calulate the standard deviation - * @return {number} The variance - */ -Histogram.prototype.variance = function() { - if (this.count == 0) { - return 0; - } - return (this.sum_of_squares * this.count - this.sum * this.sum) / - (this.count * this.count); -}; - -/** - * Get the standard deviation of all added values - * @return {number} The standard deviation - */ -Histogram.prototype.stddev = function() { - return Math.sqrt(this.variance); -}; - -/** - * Get the maximum among all added values - * @return {number} The maximum - */ -Histogram.prototype.maximum = function() { - return this.max_seen; -}; - -/** - * Get the minimum among all added values - * @return {number} The minimum - */ -Histogram.prototype.minimum = function() { - return this.min_seen; -}; - -/** - * Get the number of all added values - * @return {number} The count - */ -Histogram.prototype.getCount = function() { - return this.count; -}; - -/** - * Get the sum of all added values - * @return {number} The sum - */ -Histogram.prototype.getSum = function() { - return this.sum; -}; - -/** - * Get the sum of squares of all added values - * @return {number} The sum of squares - */ -Histogram.prototype.sumOfSquares = function() { - return this.sum_of_squares; -}; - -/** - * Get the raw histogram as a list of bucket sizes - * @return {Array.<number>} The buckets - */ -Histogram.prototype.getContents = function() { - return this.buckets; -}; - -module.exports = Histogram; diff --git a/src/node/performance/worker.js b/src/node/performance/worker.js deleted file mode 100644 index d0fb3bcb28..0000000000 --- a/src/node/performance/worker.js +++ /dev/null @@ -1,50 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -'use strict'; - -var console = require('console'); -var WorkerServiceImpl = require('./worker_service_impl'); - -var grpc = require('../../../'); -var serviceProto = grpc.load({ - root: __dirname + '/../../..', - file: 'src/proto/grpc/testing/services.proto'}).grpc.testing; - -function runServer(port, benchmark_impl) { - var server_creds = grpc.ServerCredentials.createInsecure(); - var server = new grpc.Server(); - server.addService(serviceProto.WorkerService.service, - new WorkerServiceImpl(benchmark_impl, server)); - var address = '0.0.0.0:' + port; - server.bind(address, server_creds); - server.start(); - console.log('running QPS worker on %s', address); - return server; -} - -if (require.main === module) { - Error.stackTraceLimit = Infinity; - var parseArgs = require('minimist'); - var argv = parseArgs(process.argv, { - string: ['driver_port', 'benchmark_impl'] - }); - runServer(argv.driver_port, argv.benchmark_impl); -} - -exports.runServer = runServer; diff --git a/src/node/performance/worker_service_impl.js b/src/node/performance/worker_service_impl.js deleted file mode 100644 index a73d77efc3..0000000000 --- a/src/node/performance/worker_service_impl.js +++ /dev/null @@ -1,183 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -'use strict'; - -var os = require('os'); -var console = require('console'); -var BenchmarkClient = require('./benchmark_client'); -var BenchmarkServer = require('./benchmark_server'); - -module.exports = function WorkerServiceImpl(benchmark_impl, server) { - var BenchmarkClient; - var BenchmarkServer; - switch (benchmark_impl) { - case 'grpc': - BenchmarkClient = require('./benchmark_client'); - BenchmarkServer = require('./benchmark_server'); - break; - case 'express': - BenchmarkClient = require('./benchmark_client_express'); - BenchmarkServer = require('./benchmark_server_express'); - break; - default: - throw new Error('Unrecognized benchmark impl: ' + benchmark_impl); - } - - this.quitWorker = function quitWorker(call, callback) { - callback(null, {}); - server.tryShutdown(function() {}); - }; - - this.runClient = function runClient(call) { - var client; - call.on('data', function(request) { - var stats; - switch (request.argtype) { - case 'setup': - var setup = request.setup; - console.log('ClientConfig %j', setup); - client = new BenchmarkClient(setup.server_targets, - setup.client_channels, - setup.histogram_params, - setup.security_params); - client.on('error', function(error) { - call.emit('error', error); - }); - var req_size, resp_size, generic; - switch (setup.payload_config.payload) { - case 'bytebuf_params': - req_size = setup.payload_config.bytebuf_params.req_size; - resp_size = setup.payload_config.bytebuf_params.resp_size; - generic = true; - break; - case 'simple_params': - req_size = setup.payload_config.simple_params.req_size; - resp_size = setup.payload_config.simple_params.resp_size; - generic = false; - break; - default: - call.emit('error', new Error('Unsupported PayloadConfig type' + - setup.payload_config.payload)); - return; - } - switch (setup.load_params.load) { - case 'closed_loop': - client.startClosedLoop(setup.outstanding_rpcs_per_channel, - setup.rpc_type, req_size, resp_size, generic); - break; - case 'poisson': - client.startPoisson(setup.outstanding_rpcs_per_channel, - setup.rpc_type, req_size, resp_size, - setup.load_params.poisson.offered_load, generic); - break; - default: - call.emit('error', new Error('Unsupported LoadParams type' + - setup.load_params.load)); - return; - } - stats = client.mark(); - call.write({ - stats: stats - }); - break; - case 'mark': - if (client) { - stats = client.mark(request.mark.reset); - call.write({ - stats: stats - }); - } else { - call.emit('error', new Error('Got Mark before ClientConfig')); - } - break; - default: - throw new Error('Nonexistent client argtype option: ' + request.argtype); - } - }); - call.on('end', function() { - client.stop(function() { - call.end(); - }); - }); - }; - - this.runServer = function runServer(call) { - var server; - call.on('data', function(request) { - var stats; - switch (request.argtype) { - case 'setup': - console.log('ServerConfig %j', request.setup); - var setup = request.setup; - var resp_size, generic; - if (setup.payload_config) { - switch (setup.payload_config.payload) { - case 'bytebuf_params': - resp_size = setup.payload_config.bytebuf_params.resp_size; - generic = true; - break; - case 'simple_params': - resp_size = setup.payload_config.simple_params.resp_size; - generic = false; - break; - default: - call.emit('error', new Error('Unsupported PayloadConfig type' + - setup.payload_config.payload)); - return; - } - } - server = new BenchmarkServer('[::]', request.setup.port, - request.setup.security_params, - generic, resp_size); - server.on('started', function() { - stats = server.mark(); - call.write({ - stats: stats, - port: server.getPort() - }); - }); - server.start(); - break; - case 'mark': - if (server) { - stats = server.mark(request.mark.reset); - call.write({ - stats: stats, - port: server.getPort(), - cores: 1 - }); - } else { - call.emit('error', new Error('Got Mark before ServerConfig')); - } - break; - default: - throw new Error('Nonexistent server argtype option'); - } - }); - call.on('end', function() { - server.stop(function() { - call.end(); - }); - }); - }; - - this.coreCount = function coreCount(call, callback) { - callback(null, {cores: os.cpus().length}); - }; -}; |