get console.timeEnd() to not log all by itself - javascript

I would like to get the amount of time the process took to fully complete. I have this code:
console.log(`Ran ${ran} equations in ${console.timeEnd()}`)
but I don't get my expected output, which is:
Ran X equations in 33.099ms // eg
instead I get
default: 33.099ms
Ran X Equations in undefined
Note that I didn't give my console.time() a label.
How can I achieve my expected output?

console.timeEnd doesn't return anything; it's part of the console, as you know. Because console.timeEnd counts in milliseconds with decimal places (unlike Date.now()), the closest thing you'll get is with performance.now(). We can create a custom time function:
class Time {
constructor() {
this.time = performance.now();
}
end() {
return (performance.now() - this.time).toFixed(3); // round number to lower decimal precision, like console.time()
}
}
const time = new Time();
console.time("Console measurement");
let dummyVar = 0;
for(let i = 0; i < 1000000; i++) {
// do some time consuming task
dummyVar += i;
}
console.log("Custom measurement:", time.end() + "ms");
console.timeEnd("Console measurement");
I intentionally returned a number and not a string (with "ms" at the end) so you could use it better. Obviously, if you want to represent the exact output of console.timeEnd(), simply append + "ms" to the expression in Time#end:
class Time {
constructor() {
this.time = performance.now();
}
end() {
return (performance.now() - this.time).toFixed(3) + "ms";
}
}
const time = new Time();
// dummy example
setTimeout(() => console.log(`Ran X equations in ${time.end()}`), Math.floor(Math.random() * 100));

console.timeEnd() returns undefined, not what it logs. To get very close to the desired output, label the timer with the descriptive string...
const ran = 4; // you'll need to know ran before starting the timer
const label = `Ran ${ran} equations in`;
console.time(label);
// do some time consuming stuff
alert('wait a sec, then press ok')
console.timeEnd(label);

Related

Get process CPU usage in percentage

The process.cpuUsage() function displays some weird microsecond values.
How to get cpu usage in percentage?
You can achieve this using the additional os native module to get informations about your CPUs:
const os = require('os');
// Take the first CPU, considering every CPUs have the same specs
// and every NodeJS process only uses one at a time.
const cpus = os.cpus();
const cpu = cpus[0];
// Accumulate every CPU times values
const total = Object.values(cpu.times).reduce(
(acc, tv) => acc + tv, 0
);
// Normalize the one returned by process.cpuUsage()
// (microseconds VS miliseconds)
const usage = process.cpuUsage();
const currentCPUUsage = (usage.user + usage.system) * 1000;
// Find out the percentage used for this specific CPU
const perc = currentCPUUsage / total * 100;
console.log(`CPU Usage (%): ${perc}`);
If you want to get the global CPU usage (taking all your CPUs into account), you need to accumulate every times of every CPUs, not only the first one, but that should be less useful in most cases.
Note that only the "system" time can use more than the first CPU because the calls can run in other threads separated from the NodeJS core.
Sources :
https://nodejs.org/api/os.html#os_os_cpus
https://nodejs.org/api/process.html#process_process_cpuusage_previousvalue
An alternative, assuming you are running node under linux/macos O.S. is:
var exec = require("child_process").exec;
function getProcessPercent() {
// GET current node process id.
const pid = process.pid;
console.log(pid);
//linux command to get cpu percentage for the specific Process Id.
var cmd = `ps up "${pid}" | tail -n1 | tr -s ' ' | cut -f3 -d' '`;
setInterval(() => {
//executes the command and returns the percentage value
exec(cmd, function (err, percentValue) {
if (err) {
console.log("Command `ps` returned an error!");
} else {
console.log(`${percentValue* 1}%`);
}
});
}, 1000);
}
getProcessPercent();
If your O.S is windows, your command must be different. As i'm not running windows i can't tell to you the exact command, but you can start from here:
tasklist
get-process
WMIC
You can also check the platform with process.platform and do an if/else statment setting the right command for the specific OS.
Before answering we need to take care about a couple of facts:
Node.js does not uses only one CPU, but every async I/O operation may use additional CPUs
the times returned by process.cpuUsage are cumulative of all CPUs used by the Node.js process
so to calculate the CPU usage of Node.js considering all the CPUs of the host, we could use something similar to:
const ncpu = require("os").cpus().length;
let previousTime = new Date().getTime();
let previousUsage = process.cpuUsage();
let lastUsage;
setInterval(() => {
const currentUsage = process.cpuUsage(previousUsage);
previousUsage = process.cpuUsage();
// we can't do simply times / 10000 / ncpu because we can't trust
// setInterval is executed exactly every 1.000.000 microseconds
const currentTime = new Date().getTime();
// times from process.cpuUsage are in microseconds while delta time in milliseconds
// * 10 to have the value in percentage for only one cpu
// * ncpu to have the percentage for all cpus af the host
// this should match top's %CPU
const timeDelta = (currentTime - previousTime) * 10;
// this would take care of CPUs number of the host
// const timeDelta = (currentTime - previousTime) * 10 * ncpu;
const { user, system } = currentUsage;
lastUsage = { system: system / timeDelta, total: (system + user) / timeDelta, user: user / timeDelta };
previousTime = currentTime;
console.log(lastUsage);
}, 1000);
or we can read the value of lastUsage from where we need it rather printing it to the console.
Try using the below code to get cpu usage in %
var startTime = process.hrtime()
var startUsage = process.cpuUsage()
// spin the CPU for 500 milliseconds
var now = Date.now()
while (Date.now() - now < 500)
var elapTime = process.hrtime(startTime)
var elapUsage = process.cpuUsage(startUsage)
var elapTimeMS = secNSec2ms(elapTime)
var elapUserMS = secNSec2ms(elapUsage.user)
var elapSystMS = secNSec2ms(elapUsage.system)
var cpuPercent = Math.round(100 * (elapUserMS + elapSystMS) / elapTimeMS)
console.log('elapsed time ms: ', elapTimeMS)
console.log('elapsed user ms: ', elapUserMS)
console.log('elapsed system ms:', elapSystMS)
console.log('cpu percent: ', cpuPercent)
function secNSec2ms (secNSec) {
return secNSec[0] * 1000 + secNSec[1] / 1000000
}
try tweaking the secNSec2ms function to the following to check if it solves your problem.
function secNSec2ms(secNSec) {
if (Array.isArray(secNSec))
return secNSec[0] * 1000 + secNSec[1] / 1000000 return secNSec / 1000;
}

cancelScheduledValues(x) followed by setValueCurveAtTime(x) throws error

I'm using the WebAudio API to crossfade between multiple sources. Fades are queued using setValueCurveAtTime(curve, time, duration). The WebAudio spec indicates that any subsequent call to setValueCurveAtTime with overlapping durations is not allowed. So I'm calling cancelScheduledValues(time) before queuing up new fades. Both Firefox v68 and Chrome v77 throw errors on the second setValueCurveAtTime call however.
The attached snippet contains the minimum amount of code to trigger the errors in either browser. Click on Start to trigger the error. Note that it doesn't play any audio as it's not needed for the error to be thrown. The select dropdown allow control of the time argument to both functions. In Chrome v77 time=0 doesn't trigger an error.
Any ideas on how to get this to work in both browsers would be much appreciated!
Update: As Raymond Toy pointed out cancelScheduledValues(t) appears to cancel automations which started at t or later (not simply active during t). By using cancelScheduledValues(Math.max(t - duration, 0)) the code now appears to work in Chrome. Firefox still fails with a Operation is not supported error however.
<!DOCTYPE html>
<html>
<body>
<button id="start">Start</button>
<select id="time">
<option value="0">time=0</option>
<option value="1">time=currentTime</option>
</select>
<pre id="log"></pre>
<script>
const select = document.querySelector('#time')
const log = document.querySelector('#log')
function start() {
const ctx = new AudioContext()
ctx.resume()
const gain = ctx.createGain()
gain.connect(ctx.destination)
// Fade in
gain.gain.setValueCurveAtTime(new Float32Array([0, 1]), 0, 1)
setTimeout(() => {
const time = select.options[select.selectedIndex].value === '0' ? 0 : ctx.currentTime
// Replace fade in with fade out
// THIS IS THE CALL THAT DOESN'T WORK =====
// Doesn't work in Firefox nor Chrome:
// gain.gain.cancelScheduledValues(time)
// Doesn't work in Firefox:
gain.gain.cancelScheduledValues(Math.max(time - 1 /* duration of previous fade */, 0))
try {
// ERROR IS THROWN HERE =================
gain.gain.setValueCurveAtTime(new Float32Array([0, 1]), time, 1)
} catch (error) {
log.prepend(error.message + '\n')
throw error
}
log.prepend('No error!\n')
}, 100)
}
document.querySelector('#start').addEventListener('click', start)
</script>
</body>
</html>
My reading of cancelScheduledValues shows that this is working as intended. The event time for a setValueCurveAtTime(curve, time, duration) is time. cancelScheduledValues(t2) removes all events whose event time is t2 or greater. In your test case, time = 0, and t2 is currentTime which is greater than 0. Thus, nothing is removed from the timeline. The second call to setValueCurveAtTime inserts a new event that does overlap the previous one. Hence, you get an error.
Having said that, I think this is kind of unexpected. This could be an error in the WebAudio spec.
In the end I ended up ditching setValueCurveAtTime() in favour of multiple setValueAtTime calls:
function fade(gainNode, fadeIn, startTime = 0) {
const duration = 1 // seconds
const delta = 1 / 100 // number of volume changes per second
const targetVolume = fadeIn ? 1 : 0
const currentTime = audioContext.currentTime
if (!startTime) { startTime = currentTime }
// We can only read current volume for current startTime, so if queueing a fade
// we'll have to assume it starts in the other end
const startingVolume = startTime && startTime !== currentTime
? 1 - targetVolume
: gainNode.gain.value
// Offset to start at when startingVolume isn't 0 or 1
let tOffset = equalPowerEasingInverse(startingVolume)
if (fadeIn) tOffset = 1 - tOffset
let t = 0 // time iterator [0..1]
try {
// Cancel any potentially overlapping fade automations
gainNode.gain.cancelScheduledValues(Math.max(startTime - duration, 0))
for (; t + tOffset <= 1; t += delta) {
// Queue volume change
gainNode.gain.setValueAtTime(
equalPowerEasing(t + tOffset, fadeIn),
startTime + t*duration
)
}
// Ensure final value is exact
gainNode.gain.setValueAtTime(targetVolume, startTime + t*duration)
} catch (error) {
if (/Failed to execute 'setValueCurveAtTime'|Operation is not supported/.test(error.message)) {
// Ignore Chrome + Firefox errors
} else {
throw error
}
}
}
function equalPowerEasing(t, invert = true) {
if (invert) t = 1 - t
return Math.cos(t * 0.5 * Math.PI)
}
function equalPowerEasingInverse(x) {
return Math.acos(x) / 0.5 / Math.PI
}

How Can I make millisecond Unique?

I'm using NodeJs.
I received constantly request from server.
I'm added some variable like createdTime to it and saved to the database.
when I sorted data by createdTime in some case It is not reliable, It is Repeated
How can I make differentiate between them ?
I do not want to count request.
I do not like to change timestamp's format.
var createdTime = new Date().getTime();
Here's a method of combining a counter with the current time to allow you to have as many as 1000 separate transactions within the same ms that are all uniquely numbered, but still a time-based value.
And, here's a working snippet to illustrate:
// this guarantees a unique time-based id
// as long as you don't have more than 1000
// requests in the same ms
var getTransactionID = (function() {
var lastTime, counter = 0;
return function() {
var now = Date.now();
if (now !== lastTime) {
lastTime = now;
counter = 0;
} else {
++counter;
}
return (now * 1000) + counter;
}
})();
for (var i = 0; i < 100; i++) {
document.write(getTransactionID() + "<br>");
}
If you want something that is likely to work across clusters, you can use process.hrtime() to use the high resolution timer instead of the counter and then make the id be a string that could be parsed into a relative time if needed. Since this requires node.js, I can't make a working snippet here in the browser, but here's the idea:
// this makes a unique time-based id
function getTransactionID () {
var now = Date.now();
var hrtime = process.hrtime();
return now + "." + ((hrtime[0] * 1e9) + hrtime[1]);
}
Due to my low rep I can't add a comment but it looks like you are needing to go beyond milliseconds.Maybe this stackoverflow question can help you
How to get a microtime in Node.js?

window.performance.now() equivalent in nodejs?

I think the question is straight forward.
I'm looking for something that's similar to window.performance.now() in nodejs V8 engine.
Right now I'm just using:-
var now = Date.now();
//do some processing..
console.log("time elapsed:", Date.now() - now);
But, I read that window.performance.now() is lot more accurate than using the date because of the what's defined here.
Node v8.5.0 has added Performance Timing API, which includes the performance#now(), e.g.
const {
performance
} = require('perf_hooks');
console.log('performance', performance.now());
I would only mention that three of the reasons the author gives for the preference of the timing API in the browser wouldn't seem to apply directly to a node situation, and the fourth, the inaccuracy of Javscript time, cites an article from 2008, and I would strongly caution against relying on older material regarding Javascript performance specifics, particularly given the recent round of performance improvements all the engines have made to support "HTML5" apps.
However, in answer to your question, you should look at process.hrtime()
UPDATE: The present package (available via npm install present) provides some sugar around hrtime if you'd like it.
Note: Since the version 8.5.0 of Node, you can use performance.now()
Here's a shortcut for process.hrtime() that returns milliseconds instead of microseconds:
function clock(start) {
if ( !start ) return process.hrtime();
var end = process.hrtime(start);
return Math.round((end[0]*1000) + (end[1]/1000000));
}
Usage:
var start = clock();
// do some processing that takes time
var duration = clock(start);
console.log("Took "+duration+"ms");
Will output something like "Took 200ms"
What about?
console.time('FooTimer');
// do the work
console.timeEnd('FooTimer');
process.uptime()
Official Node Documentation
"The process.uptime() method returns the number of seconds the
current Node.js process has been running.
The return value includes fractions of a second. Use Math.floor() to
get whole seconds."
Example: Measure For Loop Execution Time
const nemo = ['nemo'];
function findNemo(array) {
let start_time = process.uptime();
for (let iteration = 0; iteration < array.length; iteration++) {
if (array[iteration] === 'nemo') {
console.log("Found Nemo");
}
}
let end_time = process.uptime();
console.log("For loop took this much time: ", end_time - start_time);
}
findNemo(nemo);
Example Output
Here's a Typescript version with process.hrtime(), based on NextLocal's answer:
class Benchmark {
private start = process.hrtime();
public elapsed(): number {
const end = process.hrtime(this.start);
return Math.round((end[0] * 1000) + (end[1] / 1000000));
}
}
export = Benchmark;
Usage:
import Benchmark = require("./benchmark");
const benchmark = new Benchmark();
console.log(benchmark.elapsed());
To sum up and avoiding using perf_hooks
const performance = {
now: function(start) {
if ( !start ) return process.hrtime();
var end = process.hrtime(start);
return Math.round((end[0]*1000) + (end[1]/1000000));
}
}
console.log('performance', performance.now());
This method came into existence in version 8.5.0 of nodejs https://nodejs.org/api/perf_hooks.html#perf_hooks_performance_measurement_apis
compare solutions with and without loop.
Note down, which makes a difference performance wise ?
Try it out in JS snippets in developer tools or any JS editor.
function sum(n) {
let total = 0;
for (let i = 0; i <= n; i++) {
total += i;
}
return total;
}
var t1 = performance.now();
sum(100000000);
var t2 = performance.now();
console.log(`time elapsed: ${(t2-t1)/1000} seconds.`);
function addupto(n) {
return n * (n + 1) / 2;
}
var t3 = performance.now();
addupto(100000000);
var t4 = performance.now();
console.log(`time elapsed: ${(t4-t3)/1000} seconds.`);

How to make a real Javascript timer

I'm looking for a way to manipulate animation without using libraries
and as usual I make a setTimeout in another setTimout in order to smooth the UI
but I want to make a more accurate function to do it, so if I want to make a 50ms-per-piece
animation, and I type:
............
sum=0,
copy=(new Date()).getMilliseconds()
function change(){
var curTime=(new Date()).getMilliseconds(),
diff=(1000+(curTime-copy))%1000 //caculate the time between each setTimeout
console.log("diff time spam: ",diff)
sum+=diff
copy=curTime
var cur=parseInt(p.style.width)
if (sum<47){//ignore small error
//if time sum is less than 47,since we want a 50ms-per animation
// we wait to count the sum to more than the number
console.log("still wating: ",sum)
}
else{
//here the sum is bigger what we want,so make the UI change
console.log("------------runing: ",sum)
sum=0 //reset the sum to caculate the next diff
if(cur < 100)
{
p.style.width=++cur+"px"
}
else{
clearInterval(temp)
}
}
}
var temp=setInterval(change,10)
I don't know the core thought of my code is right,anyone get some ideas about how to make a more accurate timer in most browser?
Set the JsFiddle url:
http://jsfiddle.net/lanston/Vzdau/1/
Looks too complicated to me, use setInterval and one start date, like:
var start = +new Date();
var frame = -1;
var timer = setInterval(checkIfNewFrame, 20);
function checkIfNewFrame () {
var diff = +new Date() - start;
var f = Math.floor(diff / 50);
if (f > frame) {
// use one of these, depending on whether skip or animate lost frames
++frame; // in case you do not skip
frame = f; // in case you do skip
moveAnimation();
}
}
function moveAnimation () {
... do whatever you want, there is new frame, clear timer past last one
}

Categories