When I use console.time and console.timeEnd to measure the execution speed of a function or code snippet in JavaScript it prints this to the console:
timer: 14657.580078125 ms
How do I round this to the nearest integer or some other digit? I've looked at the documentation for both of these functions and neither gives me a clue how to do this.
You'd have a better shot with the Performance API, since console timers are not exposed programmatically.
There are a couple of things you could do with the API. You could use a high resolution timestamp:
let ts = performance.now();
//some code later
let measure = performance.now() - ts;
That would get you the time in milliseconds with the decimals format you have with console timers. If you need it on seconds then you can just as well do:
console.log(Math.round(measure/1000));
The Performance api has several other way to mark timestamps and measure the difference. Take a look at it.
An example taken from MDN:
const markerNameA = "example-marker-a"
const markerNameB = "example-marker-b"
// Run some nested timeouts, and create a PerformanceMark for each.
performance.mark(markerNameA);
setTimeout(function() {
performance.mark(markerNameB);
setTimeout(function() {
// Create a variety of measurements.
performance.measure("measure a to b", markerNameA, markerNameB);
performance.measure("measure a to now", markerNameA);
performance.measure("measure from navigation start to b", undefined, markerNameB);
performance.measure("measure from navigation start to now");
// Pull out all of the measurements.
console.log(performance.getEntriesByType("measure"));
// Finally, clean up the entries.
performance.clearMarks();
performance.clearMeasures();
}, 1000);
}, 1000);
Unfortunately, you will not get console.time and console.timeEnd (methods of the console object) to do anything other than the output you've already seen exclusively in the console.
Perhaps it is too bad that console.timeEnd returns undefined instead of returning the same duration that it puts into the console. But, even if it did return that duration, and you set a variable (and rounded it), your console would still show those un-rounded values in the log. There's no way to change this behavior without hacking each javascript engine your code runs on and that's not practical.
For rounded values, you'll have to forget about console.time and console.timeEnd. Those won't assist.
Related
I use console.time to show the time of the function. But I found that it shows different running time of the same function.
I have simplified my function as below:
const findIP = (res) => {
let arr = []
arr = res.split(',')
}
console.time('1')
findIP('1,2,3,4,5,6,7,8,9,0')
console.timeEnd('1')
console.time('2')
findIP('1,2,3,4,5,6,7,8,9,0')
console.timeEnd('2')
The time difference between the two is very large.
I have tried to run several times. And it still cost different time.
To quote the answer in the the following link:
If you run shorten multiple times, the V8 engine has a JIT compiler that will optimize that piece of code so it runs faster the next time.
https://stackoverflow.com/a/54601440
Try changing the argument value, for example
console.time('1')
findIP('1,2,3,4,5,6,7,8,9,0')
console.timeEnd('1')
console.time('2')
findIP('1,2,3,4,43,6,7,8,9,4')
console.timeEnd('2')
you will see approx equal time
Reason of that difference is: The browser cache
Simple Definition
browser cache is a temporary storage area in memory or on disk that holds the most recently downloaded Web pages and/or calculated result.
How to test a function that output is random using Jest? Like this:
import cuid from 'cuid';
const functionToTest = (value) => ({
[cuid()]: {
a: Math.random(),
b: new Date().toString(),
c: value,
}
});
So the output of functionToTest('Some predictable value') will be something like:
{
'cixrchnp60000vhidc9qvd10p': {
a: 0.08715126430943698,
b: 'Tue Jan 10 2017 15:20:58 GMT+0200 (EET)',
c: 'Some predictable value'
},
}
I used:
beforeEach(() => {
jest.spyOn(global.Math, 'random').mockReturnValue(0.123456789);
});
afterEach(() => {
jest.spyOn(global.Math, 'random').mockRestore();
})
It is easy to add and restores the functionality outside the tests.
Here's what I put at the top of my test file:
const mockMath = Object.create(global.Math);
mockMath.random = () => 0.5;
global.Math = mockMath;
In tests run from that file, Math.random always returns 0.5.
Full credit should go to this for the idea: https://stackoverflow.com/a/40460395/2140998, which clarifies that this overwrite is test-specific. My Object.create is just my additional extra little bit of caution avoiding tampering with the internals of Math itself.
I've taken Stuart Watt's solution and ran with it (and got a bit carried away). Stuart's solution is good but I was underwhelmed with the idea of having a random number generator always spit out 0.5 - seems like there would be situations where you're counting on some variance. I also wanted to mock crypto.randomBytes for my password salts (using Jest server-side). I spent a bit of time on this so I figured I'd share the knowledge.
One of the things I noticed is that even if you have a repeatable stream of numbers, introducing a new call to Math.random() could screw up all subsequent calls. I found a way around this problem. This approach should be applicable to pretty much any random thing you need to mock.
(side note: if you want to steal this, you'll need to install Chance.js - yarn/npm add/install chance)
To mock Math.random, put this in one of the files pointed at by your package.json's {"jest":{"setupFiles"} array:
const Chance = require('chance')
const chances = {}
const mockMath = Object.create(Math)
mockMath.random = (seed = 42) => {
chances[seed] = chances[seed] || new Chance(seed)
const chance = chances[seed]
return chance.random()
}
global.Math = mockMath
You'll notice that Math.random() now has a parameter - a seed. This seed can be a string. What this means is that, while you're writing your code, you can call for the random number generator you want by name. When I added a test to code to check if this worked, I didn't put a seed it. It screwed up my previously mocked Math.random() snapshots. But then when I changed it to Math.random('mathTest'), it created a new generator called "mathTest" and stopped intercepting the sequence from the default one.
I also mocked crypto.randomBytes for my password salts. So when I write the code to generate my salts, I might write crypto.randomBytes(32, 'user sign up salt').toString('base64'). That way I can be pretty sure that no subsequent call to crypto.randomBytes is going to mess with my sequence.
If anyone else is interested in mocking crypto in this way, here's how. Put this code inside <rootDir>/__mocks__/crypto.js:
const crypto = require.requireActual('crypto')
const Chance = require('chance')
const chances = {}
const mockCrypto = Object.create(crypto)
mockCrypto.randomBytes = (size, seed = 42, callback) => {
if (typeof seed === 'function') {
callback = seed
seed = 42
}
chances[seed] = chances[seed] || new Chance(seed)
const chance = chances[seed]
const randomByteArray = chance.n(chance.natural, size, { max: 255 })
const buffer = Buffer.from(randomByteArray)
if (typeof callback === 'function') {
callback(null, buffer)
}
return buffer
}
module.exports = mockCrypto
And then just call jest.mock('crypto') (again, I have it in one of my "setupFiles"). Since I'm releasing it, I went ahead and made it compatible with the callback method (though I have no intention of using it that way).
These two pieces of code pass all 17 of these tests (I created __clearChances__ functions for the beforeEach()s - it just deletes all the keys from the chances hash)
Update: Been using this for a few days now and I think it works pretty well. The only thing is I think that perhaps a better strategy would be creating a Math.useSeed function that's run at the top of tests that require Math.random
I'd ask myself the following questions:
Do I really need to test random output? If I have to, I'd most likely test ranges or make sure that I received a number in a valid format, not the value itself
Is it enough to test the value for c?
Sometimes there is a way to encapsulate the generation of the random value in a Mock and override the generation in your test to return only known values. This is a common practice in my code. How to mock a constructor like new Date() sounds like a similar approach in jestjs.
You could always use jest-mock-random
But it offers a little bit more functionality than mocking it as proposed in the first answer.
For example you could use before the testmockRandomWith(0.6); and your Math.random in test will always return this predictable value
Mocking literal random data isn't exactly the way to test. The question is, as it's stated, is a bit broad because "how to test a function that output is random" requires you to do statistical analysis of the output to ensure effective randomness - which has likely been done by the creators of your pseudo-random number generator.
Inferring instead "that output is random" means you want to ensure the function functions properly regardless of the random data then merely mocking the Math.random call to return numbers that meet your specific criteria (covering any variance) is enough. That function is a third-party boundary that, while needing testing, is not what's being tested based on my inference. Unless it is - in which case refer to the paragraph above.
I agree with Richard Barker answer. Strange that at the time of writing his answer has 0 votes, while the upvoted and accepted ones completely miss the point. Guess this thread is too old.
How to test a function that output is random using Jest? Its not a Jest or even a programming problem, but a statistical (or even philosophical) one and as far as I can understand, mathematics can only conclusively prove that a sequence is non-random, meaning it has a recognizable pattern. Math.random() as all other pseudo-random number generators will eventually put out a pattern, cause they are algorithms.
The best actionable advice is in cringe answer. Test the return range and type. All other suggestions eliminate the output randomness that is supposedly being tested, making the "test for randomness" pointless.
i tried to figure out, what is different between two versions of a small code-snippet in execution. Do not try to understand, what this is for. This is the final code after deleting all the other stuff to find the performance problem.
function test(){
var start=new Date(), times=100000;
var l=["a","a"];
for(var j=0;j<times;j++){
var result=document.getElementsByTagName(l[0]), rl=result.length;
for(var i=0;i<rl;i++){
l[0]=result[i];
}
}
var end=new Date();
return "by=" + (end-start);
}
For me this snippets takes 236ms in Firefox, but if you change l[0]=result[i]; to l[1]=result[i]; it only takes 51ms. Same happens if I change document.getElementsByTagName(l[0]) to document.getElementsByTagName(l[1]). And if both are change the snippet will be slow again.
After using Google Chrome with DevTools/Profiles I see that a toString function is added when executing the slow code. But i have no chance to get which toString this is and why it is needed in that case.
Can you please tell me what is the difference for the browser so that it will take 5 times longer than the other?
Thanks
If you only change one of the indexes to 0 or 1, the code doesn't do the same thing anymore. If you change both indexes, the performance remains identical.
When using the same index for reading and writing, what happens is that the value stored in l[0] is used in the next call to getElementsByTagName, which has to call toString on it.
In the code above you use l[0] to search for an element. Then you change l[0] und search again and so on. If you now change only one of the two uses (not both!) to l[1], you don't change what you are searching for, which boosts the performance.
That is why when you change both it is slow again.
How to input between lines of code some force-timeout (like java Thread.Sleep) in NighWatch.js ?
Have to wait for element to have exact value after page render.
I don't think this is the correct answer. For the original poster it's probably too late but other users might google it:
If you use the Nightwatch testing frame work then you can use these commands:
http://nightwatchjs.org/api#pause
browser.pause(1000); // pauses the test for 1000 milliseconds
or wait for an element to be present:
browser.waitForElementPresent('body', 1000); // waits max. 1000 ms for the element to appear
You won't be able to stop the thread since javascript is single thread non blocking.
What you want to do is this
setInterval(function () {alert("Hello")}, 3000);
The syntax is.
window.setInterval("javascript function", milliseconds);
See : http://www.w3schools.com/js/js_timing.asp
I've been reading John Resig's "Secrets of a JavaScript Ninja" and it explains that JavaScript is single-threaded. However, I tried testing this and I'm not sure what to take away from here:
// executing this in browser
(function () {
// throw something into event queue
setTimeout(function () {
alert("This will be called back after 1 second.");
}, 1000);
// arbitrary loop to take up some time
for (var i = 0; i < 10000; i += 1) {
console.log(i);
}
})();
Maybe I'm not understanding exactly what being single-threaded means, but I thought that the setTimeout callback wouldn't execute until all of the outer anonymous function is complete. However, running this in the browser shows that the callback function gets called while i's are still being outputted onto the console. To me, this seems like there's 2 threads with anonymous function's invokation occupying 1 thread and then the callback using the 2nd thread.
Can someone help un-confuse me?
console.log() is a weird function in some browsers (like Chrome) and is not synchronous itself so you can't really use it to gauge the single threadedness. What you are probably seeing is that the JS engine executes all the console.log() statements and then the setTimeout() runs to show the alert and, in parallel (in some other process that isn't javascript) all the data is being shown in the console.
Javascript is indeed single threaded. In your example, the setTimeout() callback will not execute until your for loop is done.
You can illustrate it better like this:
(function () {
// throw something into event queue
setTimeout(function () {
alert("This will be called back after 1 second.");
}, 1000);
function now() {
return new Date().getTime();
}
var start = now();
// loop for 1.2 seconds
while (now() - start < 1200) {}
alert("Looping done");
})();
Working jsFiddle demo: http://jsfiddle.net/jfriend00/3sBTb/
This is a bit of a tricky concept to understand. Throwing in things like event listeners also further muddies up the picture.
A simple way to think of it is as if you have a conveyor belt. You have your normal function calls all evenly spaced out, with room in between.
Things that are asynchronous things (timeouts, triggered events, etc.) fill those spots. There isn't an infinite amount of room between each of those normal calls, so it fits what it can from this queue, does a little more of the normal synchronized functions, fills some more space with asynchronous, etc.
The affect appears to be somewhat multi-threaded (and indeed you can cause race conditions of a sort with asynchronous calls). In many cases, the distinction doesn't matter. However, it is important to remember this.
However, when you try to debug things, especially when using tools like Chrome's console.log, it can look like things are scrambled because console.log itself is asynchronous (if it were synchronous, it would freeze your script on a long function).
You can see this yourself if you output something like this:
var input = document.createElement('input');
input.setAttribute('value', 0);
function inc() {
input.setAttribute('value', parseInt(input.getAttribute('value'))+1);
console.log(input);
if (parseInt(input.getAttribute('value')) < 100) {
setTimeout(inc, 10);
}
}
inc();
JSFiddle: http://jsfiddle.net/c2PnP/
What this script does it creates an input element, then every 10 milliseconds, it increments the value of input, then outputs the input element. It repeats 100 times (until value = 100).
If you look at your console, you'll notice that some of the values will be duplicated, it won't be a smooth progression. For example, on a run I just did, I see 5 inputs with a value of "100" and gaps for the missing numbers. This is because console.log is running asynchronously and only outputting when it gets the gap to do so.
(Note: If you have a super fast computer, you may need to decrease the time to something smaller, like 1, and/or increase the number of iterations to a bigger number).
John Resig covered this well. Summarizing:
"JavaScript can only ever execute one piece of code at a time (due to
its single-threaded nature)... when an asynchronous event occurs (like
a mouse click, a timer firing, or an XMLHttpRequest completing) it
gets queued up to be executed later.... After the initial block of
JavaScript finishes executing the browser immediately asks the
question: What is waiting to be executed? The browser then picks one
and executes it immediately. The [rest] will wait until the next
possible time, in order to execute."