Nodejs: Getting average number of requests - javascript

I need to send X requests to http://date.jsontest.com/ where X is an argument to my program. I've managed to get the latency for one request but now need to calculate the average time in milliseconds for multiple requests. I have an array responseTimes[] where I'd like to store the response times. How do I possibly add the multiple response times and get the average? Any help? Do I need to use the setTimeout function in the first place?
I'm using node v8.9.4 if fetchURL does not work on your end.
Here's my code
var fetchUrl = require("fetch").fetchUrl;
fetchUrl("http://date.jsontest.com", function(error, meta, body){
const start = new Date();
const responseTimes = [];
let count = 0;
setTimeout(function (argument) {
// execution time simulated with setTimeout function
var end = new Date() - start;
console.log("Execution time: %dms", end);
});
});

You need to put the start variable outside the request.
var fetchUrl = require("fetch").fetchUrl;
var start = new Date();
fetchUrl("http://date.jsontest.com", function(error, meta, body){
const requests = [];
let count = 0;
// execution time simulated with setTimeout function
var end = new Date() - start;
console.log("Execution time: %dms", end);
});

If you're storing responseTime[] then with that you can store count of requests. So at any point in time, you can get average by the following function -
function getAvg(timeArr, count){
let sum = 0;
for(let i=0; i<timeArr.length; i++){
sum += timeArr[i];
}
return sum/count;
}
Also, It's not necessary to store responseTime[]. You can just calculate avg on each request and store only the average and count If you just need average.
var fetchUrl = require("fetch").fetchUrl;
let responseTime = [];
let count = 0;
fetchUrl("http://date.jsontest.com", function(error, meta, body){
const start = new Date();
const requests = [];
let count = 0;
setTimeout(function (argument) {
// execution time simulated with setTimeout function
var end = new Date() - start;
console.log("Execution time: %dms", end);
responseTime.push(end);
count++;
let averageNow = getAvg(responseTime, count);
console.log(averageNow);// this is your average
});
});

You can use Artillery npm module to get the average response time of an API.

Related

Calculate total execution time of a function

const {performance} = require('perf_hooks');
let startTime = performance.now();
const extractedData = await readFunction()
let endTime = performance.now();
let timeTaken = endTime-startTime
I want to calculate time taken to execute readFunction(). Is this good approach to calculate total time taken to execute readFunction? Also on console.log(startTime) it gives some value instead of starting from 0.
So to get precise value should I do the following step or above step is enough to get precise time in milisecond.
const {performance} = require('perf_hooks');
let startTime = 0
const extractedData = await readFunction()
let endTime = performance.now();
let timeTaken = endTime-startTime
Is timeTaken value in milisecond? If anyone needs any further information please let me know.
function calculateTime(yourFunction) {
console.time();
yourFunction();
return console.timeEnd();
}
async function calculateTimeForPromises(yourPromise) {
console.time();
await yourPromise();
return console.timeEnd();
}
Is that helpful?

How do I setup a "rolling window"?

I'm trying to figure out the way I can set up a rolling window for a variable.
The variable will record a number increasing # amount of times from the minute before.
My basic interval timer
var kp123 = Number('1');
var myInt = setInterval(function () {
kp123 = 1;
}, 60000);
Whenever a specific command is sent, kp123 gets increased by 1:
kp123++;
This variable may increase 20 times every second, or only 2-3 times every second.
Right now how the system is set up, it records the variable # every minute, however, the data gets reset when the interval timer reaches one minute.
var kp123 = Number('1');
var kp123History = []; // The history of kp123 is stored in this variable each minute
var myInt = setInterval(function () {
kp123History.push(kp123);
kp123 = 1;
console.log(kp123History); // You can see the results in the console each minute like this
}, 60000);
or if you only want the previous value, and not the full history, try this
var kp123 = Number('1');
var prevKp123 = null; // The previous value of kp123 is stored in this variable each minute
var myInt = setInterval(function () {
prevKp123 = kp123;
kp123 = 1;
}, 60000);
It sounds like (per the comments) you want a rolling average (wiki). You don't really show enough of your code for me to give a specific answer to you, but in general, you can't deduce a rolling average from just averages, you'll need to know actual values and their timestamps. I.e. you can't summarize your data and throw away the timestmaps.
class RollingAverage {
constructor(windowMs = 1000) {
this.windowMs_ = windowMs;
this.values_ = [];
}
addValue(value = 1) {
let time = Date.now();
this.values_.push({value, time});
}
get average() {
let now = Date.now();
this.values_ = this.values_.filter(({time}) => now - time <= this.windowMs_ * 1000);
return this.values_
.map(({value}) => value)
.reduce((a, b) => a + b)
/ this.values_.length;
}
}
let test = async () => {
let sleep = ms => new Promise(r => setTimeout(r, ms));
let avg = new RollingAverage();
avg.addValue(1);
console.log(avg.average); // 1
await sleep(600);
console.log(avg.average); // 1
avg.addValue(3);
console.log(avg.average); // 2
await sleep(600);
console.log(avg.average); // 3
avg.addValue(5);
console.log(avg.average); // 4
}
test();

Measure process time with Node Js?

I would like to do the following:
console.time("processA");
for(let i; i < 10000; i++) {
// Just to simulate the process
}
console.timeEnd("processA");
but I want to capture the time end and use my own logger of information with it.
Is it possible to handle the console output of the timeEnd?
How can I measure the time interval of a process in nodejs?
Since you are targeting nodejs, you can use process.hrtime as stated in the docs
The process.hrtime() method returns the current high-resolution real time in a [seconds, nanoseconds] tuple Array, where nanoseconds is the remaining part of the real time that can't be represented in second precision.
So you can measure timings up to nanosecond, something that console.time can't, as you can see in your example console.time or Date difference measures 0s.
For example:
const NS_PER_SEC = 1e9;
const MS_PER_NS = 1e-6
const time = process.hrtime();
for (let i; i < 10000; i++) {
// Just to simulate the process
}
const diff = process.hrtime(time);
console.log(`Benchmark took ${diff[0] * NS_PER_SEC + diff[1]} nanoseconds`);
console.log(`Benchmark took ${ (diff[0] * NS_PER_SEC + diff[1]) * MS_PER_NS } milliseconds`);
Since I'm using timers in multiple places, I wrote a simple class based on Alex's answer:
const t = new Timer('For Loop')
// your code
t.runtimeMs() // => 1212.34
t.runtimeMsStr() // => 'For Loop took 1232.34 milliseconds'
Here's the code:
class Timer {
// Automatically starts the timer
constructor(name = 'Benchmark') {
this.NS_PER_SEC = 1e9;
this.MS_PER_NS = 1e-6
this.name = name;
this.startTime = process.hrtime();
}
// returns the time in ms since instantiation
// can be called multiple times
runtimeMs() {
const diff = process.hrtime(this.startTime);
return (diff[0] * this.NS_PER_SEC + diff[1]) * this.MS_PER_NS;
}
// retuns a string: the time in ms since instantiation
runtimeMsStr() {
return `${this.name} took ${this.runtimeMs()} milliseconds`;
}
}
Starting from Node v8.5, you can use browser-equivalent performance.now() which is easier to use than process.hrtime because it outputs the time in milliseconds directly, therefore you don't have to do a conversion as in process.hrtime
const { performance } = require("perf_hooks");
const start = performance.now();
doSomething();
const end = performance.now();
console.log(`time taken: ${end - start}ms`);
You can find more info from Node.js Docs on Performance API.
var startTime = new Date();
for(let i; i < 10000; i++) {
// Just to simulate the process
}
var endTime = new Date() - startTime;
You will get the total time that it takes to complete the operation
See here https://alligator.io/js/console-time-timeend/
var begin=console.time('t');
for(let i; i < 100000; i++) {
// Just to simulate the process
}
var end= console.timeEnd('t');
var timeSpent=(end-begin) / 1000 + "secs";

Wait on async method in while loop

I have a while loop that loops from one date to the other date. And I want to submit some data to the firebase realtime database.
I want to submit, and wait till the result is back. And then go to the next iteration.
var loop = moment(startDate, 'MM-DD-YYYY').toDate();
var end = moment(endDate, 'MM-DD-YYYY').toDate();
while(loop <= end){
firebaseAdmin.database().ref('test/data').set({}).then(function(){
}).catch(function(error) {
});
const newDate = loop.setDate(loop.getDate() + 1);
loop = new Date(newDate);
}
The firebase database uses promises. How can I use them to go further in the loop when the insert is done. And how do I know that everything is done so I can return?
You can do this recursively, given that you want to continue only if your current request succeeded, like this:
var loop = moment(startDate, 'MM-DD-YYYY').toDate();
var end = moment(endDate, 'MM-DD-YYYY').toDate();
function fetchDataRec(loop, end)
{
if(loop <= end) return;
firebaseAdmin.database().ref('test/data').set({}).then(function(){
if(/*check if you want to continue*/) {
const newDate = loop.setDate(loop.getDate() + 1);
loop = new Date(newDate);
fetchDataRec(loop, end);// loop while refactored to recursion
}
}).catch(function(error) {
});
}
fetchDataRec(loop, end);
https://www.sitepoint.com/recursion-functional-javascript/
There are several ways (you could use .reduce() to create a chain of promises for example)
But the best way these days is to use an async function:
async function insertMany(startDate, endDate) {
var loop = moment(startDate, 'MM-DD-YYYY').toDate();
var end = moment(endDate, 'MM-DD-YYYY').toDate();
while(loop <= end){
try {
await firebaseAdmin.database().ref('test/data').set({});
// bla bla
} catch (e) {
// bla bla
}
const newDate = loop.setDate(loop.getDate() + 1);
loop = new Date(newDate);
}
return 'all done!';
}
Or something similar to that, I didn't run it.

Can't get `count` from Asynchronous function

I have the below code where d3.json is an asynchronous function. I am trying to run it in a loop while my count is equal to 100. My while loop stops after the first iteration, because the count is happening inside the asynchronous function, so I don't run it as many times as I should. How can I get the correct count so my while loop keeps executing while keeping the asynchronous trait?
$(document).ready(function() {
$('button').click(function() {
var start = new Date().getTime();
while(count == 100){
console.log("first iteration");
count = 0;
d3.json("/api/messages/" + offset, function(error, json) {
if (error) return console.warn(error);
data = json;
for(var i = 0; i < data.messages.length; i++){
console.log(data.messages[i].date);
count++;
console.log(count);
}
});
offset += 100;
}
var end = new Date().getTime();
var time = end - start;
console.log("Time to execute : " + time);
});
});
EDIT: I'm trying for my calls to be as shown below. At each call you would check and make sure that there are 100 items(count) returned , and if not, you would stop the while loop
/api/messages/0
/api/messages/100
/api/messages/200
/api/messages/300
/api/messages/400
/api/messages/500
/api/messages/600
Here is how I would do it:
Create a function that accepts the relevant parameters: start offset, increment, and most importantly a done callback that should execute in the end.
This function contains a worker function, which will call the API, check the result and either call itself, or the done callback:
function fetchAllMessages(start, increment, done) {
var messages = [];
(function nextCall(offset) {
d3.json("/api/messages/" + offset, function (error, data) {
if (error) return done(error, messages);
if (!data.messages) return done("unexpected response format", messages);
messages.push.apply(messages, data.messages);
if (data.messages.length === increment) {
nextCall(offset + increment);
} else {
done(null, messages);
}
});
})(start);
}
Now you can use it simply from your click event handler:
$(function() {
$('button').click(function() {
var start = Date.now();
fetchAllMessages(0, 100, function (err, messages) {
var end = Date.now();
if (err) console.warn(err);
console.log(messages);
console.log("Time to execute : " + (start - end));
});
});
});
The idea is to chain this ajax calls until a certain cut-off point is reach (in this example offset is greater than max).
I have changed the d3.json call to jQuery.getJSON for this answer as its easier to debug on jsfiddle, but the concept is exactly the same. I also had to change the url for the request to use the jsfiddle debug api.
var start = new Date().getTime();
var offset = 0;
var maxOffset = 600;
var baseUrl = "/echo/json"; // change this to /api/messages in production
var callback = function(json) {
console.log(json);
console.log("current offset: " + offset);
data = json;
// ... do something with data ...
// increment the offset
offset += 100;
// don't run any more and return the execution time
if (offset > maxOffset) {
var end = new Date().getTime();
var time = end - start;
console.log("Time to execute : " + time);
return; // don't run any more
}
// offset too small so run another getJSON call with our callback
$.getJSON(baseUrl + "?" + offset, callback);
}
// when button is click, start the json call chain
$('button').click(function() {
// change the "?" to "/" in production
$.getJSON(baseUrl + "?" + offset, callback);
});
If you need help translating this to your exact problem let me know.
Here is the jsfiddle.

Categories