Related
I am making a sorting algorithm visualizer. I have a part of my program where if you click the merge sort button, it highlights whatever two elements are being compared in red, wait 1000ms, then turn the element back to aquamarine when the comparison is done.
To make the program wait 1000ms, I use the below method. It works just fine in my implementation of bubbleSort but not in mergeSort for some reason:
await new Promise(r => setTimeout(r, 0.1));
I have a theory that this is because the pausing method I used only pauses the async function but not entirely sure if that is correct. What happens in practice is that once the program hits the await new Promise() line, it just goes back up to the while statement and executes from there instead of waiting the 1000ms, then executing the line that would've turned barA and barB back to aquamarine.
function mergeSort(unsortedArray, aux = [...unsortedArray], lowIndex = 0, highIndex = unsortedArray.length - 1) {
console.log(unsortedArray);
// Base case
if (highIndex === lowIndex) return;
// Get midIndex
const midIndex = Math.floor((highIndex + lowIndex) / 2);
// Recursively run left side and right side until base case reached.
mergeSort(unsortedArray, aux, lowIndex, midIndex);
mergeSort(unsortedArray, aux, midIndex + 1, highIndex);
// Merge the left sides and right sides
merge(unsortedArray, aux, lowIndex, midIndex, highIndex);
}
// Does the actual work of ordering list
async function merge(unsortedArray, aux, lowIndex, midIndex, highIndex) {
let auxkey = lowIndex;
let i = lowIndex;
let j = midIndex + 1;
// While there are elements in left/right sides, put element in auxillary array
// then increment the indexes by 1.
while (i <= midIndex && j <= highIndex) {
let arrayBars = document.getElementsByClassName('bar');
const barA = arrayBars[i].style;
const barB = arrayBars[j].style;
barA.backgroundColor = "red";
barB.backgroundColor = "red";
if (unsortedArray[i] <= unsortedArray[j]) {
aux[auxkey] = unsortedArray[i];
auxkey++;
i++;
} else {
aux[auxkey] = unsortedArray[j];
auxkey++;
j++;
}
await new Promise(r => setTimeout(r, 0.1));
barA.backgroundColor = "aquamarine";
barB.backgroundColor = "aquamarine";
}
}
This is a somewhat tirmmed down version of my code. For a slightly more comprehensive one, see: https://jsfiddle.net/SushiCode/k0954yep/9/
I have a theory that this is because the pausing method I used only pauses the async function but not entirely sure if that is correct.
Indeed. You need to mark the mergeSort function as async as well, so you can await the merge() as well as the two recursive mergeSort() calls.
async function mergeSort(unsortedArray, aux = [...unsortedArray], lowIndex = 0, highIndex = unsortedArray.length - 1) { /*
^^^^^ */
if (highIndex === lowIndex) return;
const midIndex = Math.floor((highIndex + lowIndex) / 2);
await mergeSort(unsortedArray, aux, lowIndex, midIndex);
//^^^^^
await mergeSort(unsortedArray, aux, midIndex + 1, highIndex);
//^^^^^
await merge(unsortedArray, aux, lowIndex, midIndex, highIndex);
//^^^^^
}
I am working on an application where I'd like to provide overlays of different animations onto a range of videos using p5js. I'm looking to organize my classes of animation types so that each animation has a similar structure to update and destroy objects during each loop. My plan is to have an array of animations that are currently "active" update them each iteration of the loop and then destroy them when they are completed. I built a class to fade text in this manner but I'm getting some weird flashy behavior that seems to occur every time a new animation is triggered in the middle of another animation. I've been trying to debug it but have been unsuccessful. Do you have any suggestions as to:
(1) if this is due to my code structure? (and maybe you have a suggestion of a better way),
or
(2) I'm doing something else incorrectly?
Here is the code:
// create an array of currently executing animations to update
// each animation class needs to have one function and one attribute:
// (1) update() -- function to move the objects where ever they need to be moved
// (2) done -- attribute to determine if they should be spliced out of the array
var animations = [];
//////////////////////////////////////////
// Global Variables for Animations //
//////////////////////////////////////////
let start = false;
let count = 0;
function setup(){
let canv = createCanvas(1920, 1080);
canv.id = "myP5canvas";
background(0);
}
function draw(){
background(0);
// Check things to see if we should be adding any animations to the picture
var drawText = random(100);
if (drawText > 98) {
//if (start == false) {
let r = 255;
let g = 204;
let b = 0;
let x = random(width-10);
let y = random(height-10);
animations.push(new TextFader("Wowwwzers!", 100, 'Georgia', r, g, b, x, y, count));
start = true;
count += 1;
}
// Update animations that exist!
for (var i=0; i < animations.length; i++) {
// update the position/attributes of the animation
animations[i].update();
// check if the animation is done and should be removed from the array
if (animations[i].done) {
console.log("SPLICE: " + animations[i].id);
animations.splice(i, 1);
}
}
}
// EXAMPLE ANIMATION
// TEXT FADE
let TextFader = function(words, size, font, red, green, blue, xloc, yloc, id) {
this.id = id;
console.log("create fader: " + this.id);
// translating inputs to variables
this.text = words;
this.size = size;
this.font = font;
// To Do: separating out each of the values until I figure out how to fade separately from the color constructor
this.red = red;
this.green = green;
this.blue = blue;
this.xloc = xloc;
this.yloc = yloc;
// Maybe add customization in the future for fading...
this.fade = 255;
this.fadeTime = 3; // in seconds
this.fadeIncrement = 5;
// Variables to use for destruction
this.createTime = millis();
this.done = false;
}
TextFader.prototype.update = function() {
// Update the fade
// If the fade is below zero don't update and set to be destroyed
this.fade -= this.fadeIncrement;
if (this.fade <= 0) {
this.done = true;
} else {
this.show();
}
}
TextFader.prototype.show = function() {
textFont(this.font);
textSize(this.size);
fill(this.red, this.green, this.blue, this.fade);
text(this.text, this.xloc, this.yloc);
console.log("Drawing: " + this.id + " fade: " + this.fade + " done: " + this.done);
}
Yay, I've got you an answer! It works like expected when you reverse the for loop that loops over the animations.
Because you splice elements of the same array inside the loop, some elements are skipped. For example; animations[0].done = true and gets removed. That means that animations[1] is now in the spot of animations[0] and animations[2] is now in the spot of animations[1].
The i variable is incremented to 1, so on the next loop, you update animations[1] (and skip the animation that is now in animation[0]).
When you reverse the loop, everything before the element you splice stays the same and nothing is skipped.
For example; animations[2].done = true and gets removed. That means that animations[1] is still in the spot of animations[1].
The i variable is decremented to 1, so on the next loop, you update animations[1] and don't skip any elements.
// Update animations that exist!
for (var i = animations.length - 1; i >= 0; i--) {
// update the position/attributes of the animation
animations[i].update();
// check if the animation is done and should be removed from the array
if (animations[i].done) {
//console.log("SPLICE: " + animations[i].id);
animations.splice(i, 1);
}
}
I am creating a slideshow using a javascript. I have created a loop that is responsible for changing the css of my slideshow. I want this loop to be endless since I want to change the slides after every set interval.
However, the endless loop is causing my whole website to hang and crash. I want to know if there is an alternative approach to this that doesn't cause my whole page to crash?
async function startSlideShow(slideshow, leftPos, timer) {
let slideContainer = slideshow.children[0];
//How to handle this
let index = 0;
do {
if (index === (leftPos.length - 1)) {
index = 0;
} else {
changeSlide(index);
index++;
}
} while (true);
function changeSlide(index){
setTimeout(function(){
slideContainer.style.left = "-" + leftPos[index] + "px";
console.log("-" + leftPos[index] + "px");
}, timer * index)
}
}
Try setInterval, it calls a function continuously by default. Just put all your counter update stuff inside the interval function.
function startSlideshow(slideshow, leftPos, timer) {
let slideContainer = slideshow.children[0];
let index = 0;
setInterval(
function () {
slideContainer.style.left = "-" + leftPos[index] + "px";
console.log("-" + leftPos[index] + "px");
index = (index + 1) % leftPos.length;
// for the range of values index can be, this is equivalent to
// index = index + 1;
// if (index == leftPos.length) index = 0;
}, timer
);
}
a % b gives you the remainder when you divide a by b. This gives you a when a < b, and then 0 when a == b. More info
Read the comments in the code!
/* Don't need to be `async` */
function startSlideShow(slideshow, leftPos, timer) {
/* Commenting out to get a working example
let slideContainer = slideshow.children[0];
*/
let index = 0;
/* You have to start manually, it will call itself later (see bellow) */
loopThroughSlides();
function loopThroughSlides() {
if (index === (leftPos.length - 1)) {
/* You should call `changeSlide` here as well */
changeSlide(index);
index = 0;
} else {
changeSlide(index);
index++;
}
/* Calling itself after timeout, this makes it endless */
setTimeout(loopThroughSlides, timer /* Don't need to multiply with `index`) */);
}
function changeSlide(index){
/* Keep the original code, but I replace it with another for demonstarting
slideContainer.style.left = "-" + leftPos[index] + "px";
console.log("-" + leftPos[index] + "px");
*/
/* Demonstration code */
console.log(leftPos[index]);
}
}
/* Calling the function */
startSlideShow(null, ['What', 'is', 'leftPos?'], 1000)
I am trying to build a -primitive- pattern generator in jQuery that essentially goes over 1x1 pixel and determines, depending on the value in the preceding pixel, what the one in question is going to look like.
Seeing as I am relatively proficient in jQuery but unfortunately rather oblivious to the ways of the RequestAnimFrame API, realizing the 1x1 pixel approach results in an extremely slowed down execution, making most browsers assume the script has crashed (?) even though it is in fact working, but essentially, really slow.
I have therefore tested it in bigger tile sizes because they are naturally easier to generate. My question at this point is - should I throw the jQuery approach aside and revise the script in the abovementioned API or is there a way to make it more efficient and realistically working with jQuery?
Link to code: http://codepen.io/Grovelli/pen/yepMRZ/
PS: Please excuse the trivial comments in the code
<html>
<head>
<script type="text/javascript" src="jquery-1.11.1.min.js"></script>
<script type="text/javascript">
// run once
$(function() {
//###############################################
//
// Default variables
//
//###############################################
var smallSquareWidth = 20; // size of single tile
var smallSquareHeight = 10;
var bigSquareWidth = 300; // size of tile box
var bigSquareHeight = 300;
var orientationPoint = 0; // point of orientation for pattern drawing
// Tile library
var tileArray = ["#00ff5a", "#02d24b", "#01b13f", "#039737", "#027d2d", "#02521e"];
// assign a random color from the color array tileArray
function drawTile() {
var selectedi;
// if selectedi is not 2, then roll the dice
if (orientationPoint == 0) {
// returns value of array item in question
selectedi = Math.floor(Math.random() * tileArray.length);
//alert("No 2, rolling dice");
}
// if dice return 2, then start building pattern until termination, i.e. orientationPoint being set back to 0
if (selectedi == 2) {
orientationPoint = 1; // disables the random throw above
//alert("got 2! building pattern now!");
chosenTile_Hex = tileArray[0];
orientationPoint++;
}
if (orientationPoint == 2) {
chosenTile_Hex = tileArray[1];
orientationPoint++;
return chosenTile_Hex;
} else if (orientationPoint == 3) {
chosenTile_Hex = tileArray[2];
orientationPoint++;
return chosenTile_Hex;
} else if (orientationPoint == 4) {
chosenTile_Hex = tileArray[3];
orientationPoint++;
return chosenTile_Hex;
} else if (orientationPoint == 5) {
chosenTile_Hex = tileArray[4];
orientationPoint = 0; // resets / turns off pattern building
//alert("done building pattern");
return chosenTile_Hex;
}
// return random array item
var chosenTile = selectedi; // .length is preferrable to size in this case
var chosenTile_Hex = tileArray[selectedi]; // use value of selectedi to determine which color to use for the tile i.q.
/*
// show at which position the background color value of #nChildren-1 is found within the tileArray array
//alert("found at " + (jQuery.inArray( orientationPoint, tileArray)));
var orient_pos = jQuery.inArray(orientationPoint, tileArray);
//alert(orient_pos);
//alert(tileArray[orient_pos + Math.floor(Math.random() * 3) - 2]);
$("#" + (nChildren - 1)).css("background-color", tileArray[orient_pos + Math.floor(Math.random() * 3) - 2]);
*/
//alert(chosenTile);
//alert(nextTile);
//alert(chosenTile_Hex);
return chosenTile_Hex;
}
//###############################################
// Append the main container, bigSquare to the body of the HTML file
$("<div class='bigSquare' style='position:aboslute; width:" + bigSquareWidth + "px; height:" + bigSquareHeight + "px;'></div>").appendTo("body");
/* random colors calc function
// A function to create random HEX color codes
function randomHex() {
var hexArray = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f"];
//creates a random hex color code
var randomHexCode = '' + hexArray[Math.floor(Math.random() * 16)] + '' +
hexArray[Math.floor(Math.random() * 16)] + '' +
hexArray[Math.floor(Math.random() * 2)] + '' +
hexArray[Math.floor(Math.random() * 16)] + '' +
hexArray[Math.floor(Math.random() * 16)] + '' +
hexArray[Math.floor(Math.random() * 16)];
// spit out a random hex code when the function terminates
return randomHexCode;
} */
// Calculate the total number of children
var nLines = bigSquareHeight / smallSquareHeight; // per column
var nPerLine = bigSquareWidth / smallSquareWidth; // and per row
// Generate as many rows as fit into .bigSquare
for (var k = 1; k <= nLines; k++) {
// per row, generate as many smallSquares as fit each row
for (var i = 1; i <= nPerLine; i++) {
// nChildren is the accumulating number of children elements in .bigSquare
var nChildren = $('.bigSquare').children().size();
// pass the accumulating number to each newly generated div
// to give each div a unique id label
$("<div class='smallSquare' id='" + nChildren + "' style='width:" + smallSquareWidth + "px; height:" + smallSquareHeight + "px; float:left;'></div>").appendTo(".bigSquare");
$("#" + nChildren).css("background-color", drawTile);
// var orientationPoint = rgb2hex($("#" + (nChildren - 1)).css("background-color"));
//alert(orientationPoint);
//alert(nChildren);
//alert(($("#" + nChildren).css("background-color")));
/*$('#' + nChildren + '').hide();
//alert(eval(k+i));
//###################################
// saving both k and i in a closure context to reuse them in INNER functions, e.g. setTimeout
(function(nChildren) {
setTimeout(function() {
$('#' + nChildren + '').fadeIn('slow');
//alert('#'+''+k+i+'');
}, nChildren * 18);
})(nChildren);*/
// first for loop END
}
// second for loop END
}
//the code below returns the number of child elements of bigSquare
//alert($('.bigSquare').children().size());
setInterval(function() {
//alert("interval");
for (var h = 0; h <= nChildren; h++) {
//alert(h);
//alert(randomHex());
//$('#'+h+'').css('background-color',randomHex);
}
}, 2000);
//alert($(".bigSquare").children(1).width());
//for centering purposes...
function centerElement() {
//resetting the margin properties each time the function is called
// to avoid margin addups
$('.bigSquare').css('margin-left', "0");
$('.bigSquare').css('margin-top', "0");
var getPageWidth = $(window).width();
var getPageHeight = $(document).height(); //alert(getPageHeight);
var centerPosX = getPageWidth / 2 - bigSquareWidth / 2;
var centerPosY = getPageHeight / 2 - bigSquareHeight / 2;
//alert(centerPosX);
//alert(centerPosY); CAREFUL ENABLING THIS AND RESIZING
// MIGHT FREEZE FF ON MACs
$('.bigSquare').css('margin-left', centerPosX + "px");
//ENABLE THIS FOR VERTICAL POSITIONING
$('.bigSquare').css('margin-top', centerPosY + "px");
//alert("resized");
}
centerElement();
//refresh on resize
//$(window).bind('resize', location.reload());
});
I have a piece of JavaScript code that I am executing using the node.js interpreter.
for(var i = 1; i < LIMIT; i++) {
var user = {
id: i,
name: "MongoUser [" + i + "]"
};
db.users.save(user, function(err, saved) {
if(err || !saved) {
console.log("Error");
} else {
console.log("Saved");
}
});
}
How can I measure the time taken by these database insert operations? I could compute the difference of date values after and before this piece of code but that would be incorrect because of the asynchronous nature of the code.
Use the Node.js console.time() and console.timeEnd():
var i;
console.time("dbsave");
for(i = 1; i < LIMIT; i++){
db.users.save({id : i, name : "MongoUser [" + i + "]"}, end);
}
end = function(err, saved) {
console.log(( err || !saved )?"Error":"Saved");
if(--i === 1){
console.timeEnd("dbsave");
}
};
There is a method that is designed for this. Check out process.hrtime(); .
So, I basically put this at the top of my app.
var start = process.hrtime();
var elapsed_time = function(note){
var precision = 3; // 3 decimal places
var elapsed = process.hrtime(start)[1] / 1000000; // divide by a million to get nano to milli
console.log(process.hrtime(start)[0] + " s, " + elapsed.toFixed(precision) + " ms - " + note); // print message + time
start = process.hrtime(); // reset the timer
}
Then I use it to see how long functions take. Here's a basic example that prints the contents of a text file called "output.txt":
var debug = true;
http.createServer(function(request, response) {
if(debug) console.log("----------------------------------");
if(debug) elapsed_time("recieved request");
var send_html = function(err, contents) {
if(debug) elapsed_time("start send_html()");
response.writeHead(200, {'Content-Type': 'text/html' } );
response.end(contents);
if(debug) elapsed_time("end send_html()");
}
if(debug) elapsed_time("start readFile()");
fs.readFile('output.txt', send_html);
if(debug) elapsed_time("end readFile()");
}).listen(8080);
Here's a quick test you can run in a terminal (BASH shell):
for i in {1..100}; do echo $i; curl http://localhost:8080/; done
Invoking console.time('label') will record the current time in milliseconds, then later calling console.timeEnd('label') will display the duration from that point.
The time in milliseconds will be automatically printed alongside the label, so you don't have to make a separate call to console.log to print a label:
console.time('test');
//some code
console.timeEnd('test'); //Prints something like that-> test: 11374.004ms
For more information, see Mozilla's developer docs on console.time.
Surprised no one had mentioned yet the new built in libraries:
Available in Node >= 8.5, and should be in Modern Browers
https://developer.mozilla.org/en-US/docs/Web/API/Performance
https://nodejs.org/docs/latest-v8.x/api/perf_hooks.html#
Node 8.5 ~ 9.x (Firefox, Chrome)
// const { performance } = require('perf_hooks'); // enable for node
const delay = time => new Promise(res=>setTimeout(res,time))
async function doSomeLongRunningProcess(){
await delay(1000);
}
performance.mark('A');
(async ()=>{
await doSomeLongRunningProcess();
performance.mark('B');
performance.measure('A to B', 'A', 'B');
const measure = performance.getEntriesByName('A to B')[0];
// firefox appears to only show second precision.
console.log(measure.duration);
// apparently you should clean up...
performance.clearMarks();
performance.clearMeasures();
// Prints the number of milliseconds between Mark 'A' and Mark 'B'
})();
https://repl.it/#CodyGeisler/NodeJsPerformanceHooks
Node 12.x
https://nodejs.org/docs/latest-v12.x/api/perf_hooks.html
const { PerformanceObserver, performance } = require('perf_hooks');
const delay = time => new Promise(res => setTimeout(res, time))
async function doSomeLongRunningProcess() {
await delay(1000);
}
const obs = new PerformanceObserver((items) => {
console.log('PerformanceObserver A to B',items.getEntries()[0].duration);
// apparently you should clean up...
performance.clearMarks();
// performance.clearMeasures(); // Not a function in Node.js 12
});
obs.observe({ entryTypes: ['measure'] });
performance.mark('A');
(async function main(){
try{
await performance.timerify(doSomeLongRunningProcess)();
performance.mark('B');
performance.measure('A to B', 'A', 'B');
}catch(e){
console.log('main() error',e);
}
})();
For anyone want to get time elapsed value instead of console output :
use process.hrtime() as #D.Deriso suggestion, below is my simpler approach :
function functionToBeMeasured() {
var startTime = process.hrtime();
// do some task...
// ......
var elapsedSeconds = parseHrtimeToSeconds(process.hrtime(startTime));
console.log('It takes ' + elapsedSeconds + 'seconds');
}
function parseHrtimeToSeconds(hrtime) {
var seconds = (hrtime[0] + (hrtime[1] / 1e9)).toFixed(3);
return seconds;
}
var start = +new Date();
var counter = 0;
for(var i = 1; i < LIMIT; i++){
++counter;
db.users.save({id : i, name : "MongoUser [" + i + "]"}, function(err, saved) {
if( err || !saved ) console.log("Error");
else console.log("Saved");
if (--counter === 0)
{
var end = +new Date();
console.log("all users saved in " + (end-start) + " milliseconds");
}
});
}
Old question but for a simple API and light-weight solution; you can use perfy which uses high-resolution real time (process.hrtime) internally.
var perfy = require('perfy');
function end(label) {
return function (err, saved) {
console.log(err ? 'Error' : 'Saved');
console.log( perfy.end(label).time ); // <——— result: seconds.milliseconds
};
}
for (var i = 1; i < LIMIT; i++) {
var label = 'db-save-' + i;
perfy.start(label); // <——— start and mark time
db.users.save({ id: i, name: 'MongoUser [' + i + ']' }, end(label));
}
Note that each time perfy.end(label) is called, that instance is auto-destroyed.
Disclosure: Wrote this module, inspired by D.Deriso's answer. Docs here.
You could also try exectimer. It gives you feedback like:
var t = require("exectimer");
var myFunction() {
var tick = new t.tick("myFunction");
tick.start();
// do some processing and end this tick
tick.stop();
}
// Display the results
console.log(t.timers.myFunction.duration()); // total duration of all ticks
console.log(t.timers.myFunction.min()); // minimal tick duration
console.log(t.timers.myFunction.max()); // maximal tick duration
console.log(t.timers.myFunction.mean()); // mean tick duration
console.log(t.timers.myFunction.median()); // median tick duration
[edit] There is an even simpler way now to use exectime. Your code could be wrapped like this:
var t = require('exectimer'),
Tick = t.Tick;
for(var i = 1; i < LIMIT; i++){
Tick.wrap(function saveUsers(done) {
db.users.save({id : i, name : "MongoUser [" + i + "]"}, function(err, saved) {
if( err || !saved ) console.log("Error");
else console.log("Saved");
done();
});
});
}
// Display the results
console.log(t.timers.myFunction.duration()); // total duration of all ticks
console.log(t.timers.saveUsers.min()); // minimal tick duration
console.log(t.timers.saveUsers.max()); // maximal tick duration
console.log(t.timers.saveUsers.mean()); // mean tick duration
console.log(t.timers.saveUsers.median()); // median tick duration
You can use a wrapper function to easily report the execution time of any existing function.
A wrapper is a used to extend an existing function to do something before and after the existing function's execution - and is a convenient way to compose logic.
Here is an example of using the withDurationReporting wrapper:
// without duration reporting
const doSomethingThatMayTakeAWhile = async (someArg: string, anotherArg: number) => {
/** your logic goes here */
}
// with duration reporting
const doSomethingThatMayTakeAWhileWithReporting = withDurationReporting(
'doSomethingThatMayTakeAWhile',
doSomethingThatMayTakeAWhile
);
// note: you can define the function with duration reporting directly, too
const doSomethingThatMayTakeAWhile = withDurationReporting(
'doSomethingThatMayTakeAWhile',
async (someArg: string, anotherArg: number) => {
/** your logic goes here */
}
)
And here is the wrapper itself:
import { hrtime } from 'process';
const roundToHundredths = (num: number) => Math.round(num * 100) / 100; // https://stackoverflow.com/a/14968691/3068233
/**
* a wrapper which reports how long it took to execute a function, after the function completes
*/
export const withDurationReporting = <R extends any, T extends (...args: any[]) => Promise<R>>(
title: string,
logic: T,
options: {
reportingThresholdSeconds: number;
logMethod: (message: string, metadata?: Record<string, any>) => void;
} = {
reportingThresholdSeconds: 1, // report on anything that takes more than 1 second, by default
logMethod: console.log, // log with `console.log` by default
},
) => {
return (async (...args: Parameters<T>): Promise<R> => {
const startTimeInNanoseconds = hrtime.bigint();
const result = await logic(...args);
const endTimeInNanoseconds = hrtime.bigint();
const durationInNanoseconds = endTimeInNanoseconds - startTimeInNanoseconds;
const durationInSeconds = roundToHundredths(Number(durationInNanoseconds) / 1e9); // https://stackoverflow.com/a/53970656/3068233
if (durationInSeconds >= options.reportingThresholdSeconds)
options.logMethod(`${title} took ${durationInSeconds} seconds to execute`, { title, durationInSeconds });
return result;
}) as T;
};
I designed a simple method for this, using console.time() & console.timeEnd():
measure function definition
function measureRunningTime(func,...args){
const varToString = varObj => Object.keys(varObj)[0]
const displayName = func.name || varToString({ func })
console.time(displayName)
func(...args)
console.timeEnd(displayName)
}
To use it, pass a function without arguments, with arguments binded, or with arguments as the following parameters.
Examples:
let's say I want to check the running time of the simplest searching algorithm - SimpleSearch:
measured function definition (your code here)
const simpleSearch = (array = [1,2,3] ,item = 3) => {
for(let i = 0; i< array.length; i++){
if (array[i] === item) return i;
}
return -1
}
implementation without arguments
measureRunningTime(simpleSearch)
//Prints something like that-> simpleSearch: 0.04ms
implementation with arguments using .bind()
const array = [1,2,3]
const item = 3
measureRunningTime(simpleSearch.bind(null, array, item))
//Prints something like that-> bound simpleSearch: 0.04ms
implementation with arguments without using .bind()
const array = [1,2,3]
const item = 3
measureRunningTime(simpleSearch, array, item)
//Prints something like that-> simpleSearch: 0.04ms
-> Take notice!! this implementation is far from perfect - for example there is no error handling - but it can be used to check the running times of simple algorithms,
Moreover , I'm not an experienced programmer so take everything with a grain of salt 🧂 👌
I had same issue while moving from AWS to Azure
For express & aws, you can already use, existing time() and timeEnd()
For Azure, use this:
https://github.com/manoharreddyporeddy/my-nodejs-notes/blob/master/performance_timers_helper_nodejs_azure_aws.js
These time() and timeEnd() use the existing hrtime() function, which give high-resolution real time.
Hope this helps.
I need this to be cumulative, and to measure different stuff.
Built these functions:
function startMeasuring(key) {
measureTimers[key] = process.hrtime();
}
function stopMeasuring(key) {
if (!measures[key]) {
measures[key] = 0;
}
let hrtime = process.hrtime(measureTimers[key]);
measures[key] += hrtime[0] + hrtime[1] / 1e9;
measureTimers[key] = null;
}
Usage:
startMeasuring("first Promise");
startMeasuring("first and second Promises");
await new Promise((resolve) => {
setTimeout(resolve, 1400);
});
stopMeasuring("first Promise");
stopMeasuring("first and second Promises");
startMeasuring("first and second Promises");
await new Promise((resolve) => {
setTimeout(resolve, 600);
});
stopMeasuring("first and second Promises");
console.log("Measure Results", measures);
/*
Measusre Results {
setting: 0.00002375,
'first Promise': 1.409392916,
'first and second Promise': 2.015160376
}
*/