Audio sync, call function every 1 / 44.1 millisecond - javascript

In JavaScript, is it possible to call a function playing 10 different wav sounds at 44.1 kHz and call that same function again in (1/44100)*(128/60)*16 seconds with a 1/44.1 millisecond precision preferably with chrome/safari and in that case how?
I'm looking at making a music loop machine playing a few simultaneous loops. The precision is needed otherwise there will be unwanted hearable issues with the sounds (phasing).

Robert,
It's possible to measure time with high accuracy - via performance.now() - but you cannot get a callback with that kind of precision. In fact, in light of layout passes and JavaScript execution in the main thread, and the ever-looming threat of garbage collection happening in the main thread, you can't get anywhere NEAR even millisecond precision; you generally ought to be planning on potential interruptions in the tens of milliseconds for robustness.
The answer to this is to use scheduling, particularly in the Web Audio API - I see that you saw the article I wrote about this a year ago on HTML5Rocks (http://www.html5rocks.com/en/tutorials/audio/scheduling/), but you missed the significant piece - you shouldn't be calling
audioSource2.noteOn(0, 0.1190, 1.875);
you need the time offset to schedule it ahead appropriately:
audioSource2.noteOn(time, 0.1190, 1.875);
If you look at my original code, that's how I'm scheduling the oscillator ahead of time. The scheduler runs in a "slow" callback loop - being called only every 100ms or so - but schedules ahead a few beats. If you truly need to mute notes that may already be scheduled in the next 1/10th of a second, then you can keep a node in the middle to disconnect().

I would take a look at either DOM High Resolution timestamp, which can be accessed with window.performance.now(), or request Animation Frame, with window.requestAnimationFrame

You can use this library which I have written : https://github.com/sebpiq/WAAClock
It lets you schedule things precisely and easily and also provides useful functionalities such as : cancel event, change tempo, ... everything necessary for a loop machine. Under the hood, it implements the tricks explained in this article (already linked by other people) : http://www.html5rocks.com/en/tutorials/audio/scheduling/
If by loop machine you mean continuously looping a few samples (and not a drum machine, where you just play a sample at a point in time), you might also want to look into this : https://github.com/sebpiq/WAATableNode

Related

Would calling Performance API frequently be causing a performance issue?

I want to measure the memory usage of my web SPA using performance.memory, and the purpose is to detect if there is any problem i.e. memory leak during the webapp's lifetime.
For this reason I would need to call this API for specific time interval - it could be every 3 second, every 30 second, or every 1 minute, ... Then I have a question - to detect any issue quickly and effectively I would have to make the interval as short as I could, but then I come up with the concern about performance. The measuring itself could affect the performance of the webapp if the measuring is such a expensive task (hopefully I don't think that is the case though)
With this background above, I have the following questions:
Is performance.memory such a method which would affect browser's main thread's performance so that I should care about the frequency of usage?
Would there be a right way or procedure to determine whether a (Javascript) task is affecting the performance of a device? If question 1 is uncertain, then I would have to try other way to find out the proper interval for calling of memory measurement.
(V8 developer here.)
Calling performance.memory is pretty fast. You can easily verify that in a quick test yourself: just call it a thousand times in a loop and measure how long that takes.
[EDIT: Thanks to #Kaiido for highlighting that this kind of microbenchmark can in general be very misleading; for example the first operation could be much more expensive; or the benchmark scenario could be so different from the real application's scenario that the results don't carry over. Do keep in mind that writing useful microbenchmarks always requires some understanding/inspection of what's happening under the hood!
In this particular case, knowing a bit about how performance.memory works internally, the results of such a simple test are broadly accurate; however, as I explain below, they also don't matter.
--End of edit]
However, that observation is not enough to solve your problem. The reason why performance.memory is fast is also the reason why calling it frequently is pointless: it just returns a cached value, it doesn't actually do any work to measure memory consumption. (If it did, then calling it would be super slow.) Here is a quick test to demonstrate both of these points:
function f() {
if (!performance.memory) {
console.error("unsupported browser");
return;
}
let objects = [];
for (let i = 0; i < 100; i++) {
// We'd expect heap usage to increase by ~1MB per iteration.
objects.push(new Array(256000));
let before = performance.now();
let memory = performance.memory.usedJSHeapSize;
let after = performance.now();
console.log(`Took ${after - before} ms, result: ${memory}`);
}
}
f();
(You can also see that browsers clamp timer granularity for security reasons: it's not a coincidence that the reported time is either 0ms or 0.1ms, never anything in between.)
(Second) however, that's not as much of a problem as it may seem at first, because the premise "to detect any issue quickly and effectively I would have to make the interval as short as I could" is misguided: in garbage-collected languages, it is totally normal that memory usage goes up and down, possibly by hundreds of megabytes. That's because finding objects that can be freed is an expensive exercise, so garbage collectors are carefully tuned for a good compromise: they should free up memory as quickly as possible without wasting CPU cycles on useless busywork. As part of that balance they adapt to the given workload, so there are no general numbers to quote here.
Checking memory consumption of your app in the wild is a fine idea, you're not the first to do it, and performance.memory is the best tool for it (for now). Just keep in mind that what you're looking for is a long-term upwards trend, not short-term fluctuations. So measuring every 10 minutes or so is totally sufficient, and you'll still need lots of data points to see statistically-useful results, because any single measurement could have happened right before or right after a garbage collection cycle.
For example, if you determine that all of your users have higher memory consumption after 10 seconds than after 5 seconds, then that's just working as intended, and there's nothing to be done. Whereas if you notice that after 10 minutes, readings are in the 100-300 MB range, and after 20 minutes in the 200-400 MB range, and after an hour they're 500-1000 MB, then it's time to go looking for that leak.

Accuracy of JavaScript time over a period of a few hours

I need to code myself a mini, locally running HTML5 + JavaScript app, which I will use as a timer to time a person performing squats.
The idea is simple: When I press A on the keyboard, it will store the current time with seconds and miliseconds into a local table as a repetition start. When I press B, it will store the current time as a repetition end.
What I'm not 100% sure about is how reliable the JavaScript timestamp really is. What is my best bet here? Here are a few ideas:
run it on the latest version of Chrome
disable the internet connection, so that the OS will not sync/change its current time
Is there anything else I should be careful about?
I don't need the time to be absolutely exact, only relatively; meaning that the last timestamp minus the first timestamp will yield the real time taken to perform the whole session. I don't care to know exactly at what time it started.
If you're retrieving the system time in Javascript with something like Date.now() in order to measure the time between two events, then that will be exactly as accurate as the system time is on the local computer. How exactly accurate that is will depend entirely upon the clock in the local system and whether there are any changes to the system time during the measurement period.
If there are no changes to the system time (such as a clock sync with an external source), then most system clocks are pretty darn accurate these days. Measuring an event that takes minutes would likely be accurate within a few milliseconds which is more accuracy than you can achieve by marking start and stop with just a keypress anyway since the precision on exactly when the key is pressed relative to the start and stop of the event is certainly not better than several hundred milliseconds.

Is there a harder to break way to obfuscate a javascript function than hieroglyphy?

I'm developing an online chess variant game. I want to create a javascript function that has the purpose of communicating to the server on behalf of the player the exact time spent on a move.
This message will be encrypted, of course, but in order to trust this function, I want to obfuscate it to the point that I can rely on the obfuscation algorithm.
I only know a few obfuscation algorithms, hieroglyphy being the most interesting. But it isn't unbreakable. Speed of execution and size are not critical, I can deduct the time spent by the function that sends the message in that same function, and the size can be even up to 2MB.
I'm pretty sure that there is no unbreakable algorithm because as long as it is required to run in a browser, anyone with enough patience can take it piece by piece and see what it does.
Do I have an alternative that would require more effort and time from a user with bad intentions?
Edit I've done some tests in every browser on WindowsXP and it appears that in FF, IE, Opera and Chrome the setTimeout function will trigger after a delay that is passed as the second parameter, regardless of any changes to system time during the delay. If no other information is presented to suggest otherwise, the logical conclusion would be that time can be measured client-side regardless of system time changes, using the setTimeout function but not the Date() object, up to a precision given by the setTimeout delay time.
Hamish mentioned in an answer below that modifying the browser date/time APIs is trivial. In that case, the javascript code is vulnerable to a modification that will increase the setTimeout real delay time. Some code should be set in place so that the server should start suspecting of cheating someone who has unreasonable lag time. This will always be a problem if lag time isn't included in thinking time.
There's a reason I can't use server side timing. The lag times would sometimes exceed a reasonable amount and that will leave users dissatisfied. And sometimes the lag can make all the difference.
Which brings me back to the original question. I'm looking for the best obfuscation method, where best is measured in the effort an attacker has to make to deobfuscate. Ideally, I would want to change the obfuscation algorithm faster than an attacker can deobfuscate, and then never to use that algorithm again or use it rarely, at a time the attacker won't expect.
I could set my computer's clock to three hours ago and your script would happily send -10800 seconds. NEVER rely on JavaScript to handle information in a trusted manner. Use your server-side code to time the difference between when the player's turn started and when they made their move, and absolutely keep a representation of the game on the server and make sure the move is valid.
Obfuscating your code doesn't help, for two reasons:
Users can still inspect the messages being sent from the browser to the server. You would also have to sign the message somehow, to prevent it being intercepted and modified. Generally, it will be even easier to unpack the message than the function used to generate it.
You're trying to measure the time taken on the move, which means your obfuscated function still has to trust the system clock and the browser date/time APIs. Both are trivial to modify.
A sensible solution would be to measure the time messages are sent and received on your server, and measure the latency of the connection to correct for transmission speeds (if you need to be very accurate).

Microsecond timing in JavaScript

Are there any timing functions in JavaScript with microsecond resolution?
I am aware of timer.js for Chrome, and am hoping there will be a solution for other friendly browsers, like Firefox, Safari, Opera, Epiphany, Konqueror, etc. I'm not interested in supporting any IE, but answers including IE are welcome.
(Given the poor accuracy of millisecond timing in JS, I'm not holding my breath on this one!)
Update: timer.js advertises microsecond resolution, but it simply multiplies the millisecond reading by 1,000. Verified by testing and code inspection. Disappointed. :[
As alluded to in Mark Rejhon's answer, there is an API available in modern browsers that exposes sub-millisecond resolution timing data to script: the W3C High Resolution Timer, aka window.performance.now().
now() is better than the traditional Date.getTime() in two important ways:
now() is a double with submillisecond resolution that represents the number of milliseconds since the start of the page's navigation. It returns the number of microseconds in the fractional (e.g. a value of 1000.123 is 1 second and 123 microseconds).
now() is monotonically increasing. This is important as Date.getTime() can possibly jump forward or even backward on subsequent calls. Notably, if the OS's system time is updated (e.g. atomic clock synchronization), Date.getTime() is also updated. now() is guaranteed to always be monotonically increasing, so it is not affected by the OS's system time -- it will always be wall-clock time (assuming your wall clock is not atomic...).
now() can be used in almost every place that new Date.getTime(), + new Date and Date.now() are. The exception is that Date and now() times don't mix, as Date is based on unix-epoch (the number of milliseconds since 1970), while now() is the number of milliseconds since your page navigation started (so it will be much smaller than Date).
now() is supported in Chrome stable, Firefox 15+, and IE10. There are also several polyfills available.
Note: When using Web Workers, the window variable isn't available, but you can still use performance.now().
There's now a new method of measuring microseconds in javascript:
http://gent.ilcore.com/2012/06/better-timer-for-javascript.html
However, in the past, I found a crude method of getting 0.1 millisecond precision in JavaScript out of a millisecond timer. Impossible? Nope. Keep reading:
I'm doing some high-precisio experiments that requires self-checked timer accuracies, and found I was able to reliably get 0.1 millisecond precision with certain browsers on certain systems.
I have found that in modern GPU-accelerated web browsers on fast systems (e.g. i7 quad core, where several cores are idle, only browser window) -- I can now trust the timers to be millisecond-accurate. In fact, it's become so accurate on an idle i7 system, I've been able to reliably get the exact same millisecond, over more than 1,000 attempts. Only when I'm trying to do things like load an extra web page, or other, the millisecond accuracy degrades (And I'm able to successfully catch my own degraded accuracy by doing a before-and-after time check, to see if my processing time suddenly lengthened to 1 or more milliseconds -- this helps me invalidate results that has probably been too adversely affected by CPU fluctuations).
It's become so accurate in some GPU accelerated browsers on i7 quad-core systems (when the browser window is the only window), that I've found I wished I could access a 0.1ms precision timer in JavaScript, since the accuracy is finally now there on some high-end browsing systems to make such timer precision worthwhile for certain types of niche applications that requires high-precision, and where the applications are able to self-verify for accuracy deviations.
Obviously if you are doing several passes, you can simply run multiple passes (e.g. 10 passes) then divide by 10 to get 0.1 millisecond precision. That is a common method of getting better precision -- do multiple passes and divide the total time by number of passes.
HOWEVER...If I can only do a single benchmark pass of a specific test due to an unusually unique situation, I found out that I can get 0.1 (And sometimes 0.01ms) precision by doing this:
Initialization/Calibration:
Run a busy loop to wait until timer increments to the next millisecond (align timer to beginning of next millisecond interval) This busy loop lasts less than a millisecond.
Run another busy loop to increment a counter while waiting for timer to increment. The counter tells you how many counter increments occured in one millisecond. This busy loop lasts one full millisecond.
Repeat the above, until the numbers become ultra-stable (loading time, JIT compiler, etc). 4. NOTE: The stability of the number gives you your attainable precision on an idle system. You can calculate the variance, if you need to self-check the precision. The variances are bigger on some browsers, and smaller on other browsers. Bigger on faster systems and slower on slower systems. Consistency varies too. You can tell which browsers are more consistent/accurate than others. Slower systems and busy systems will lead to bigger variances between initialization passes. This can give you an opportunity to display a warning message if the browser is not giving you enough precision to allow 0.1ms or 0.01ms measurements. Timer skew can be a problem, but some integer millisecond timers on some systems increment quite accurately (quite right on the dot), which will result in very consistent calibration values that you can trust.
Save the final counter value (or average of the last few calibration passes)
Benchmarking one pass to sub-millisecond precision:
Run a busy loop to wait until timer increments to the next millisecond (align timer to beginning of next millisecond interval). This busy loop lasts less than a millisecond.
Execute the task you want to precisely benchmark the time.
Check the timer. This gives you the integer milliseconds.
Run a final busy loop to increment a counter while waiting for timer to increment. This busy loop lasts less than a millisecond.
Divide this counter value, by the original counter value from initialization.
Now you got the decimal part of milliseconds!!!!!!!!
WARNING: Busy loops are NOT recommended in web browsers, but fortunately, these busy loops run for less than 1 millisecond each, and are only run a very few times.
Variables such as JIT compilation and CPU fluctuations add massive inaccuracies, but if you run several initialization passes, you'll have full dynamic recompilation, and eventually the counter settles to something very accurate. Make sure that all busy loops is exactly the same function for all cases, so that differences in busy loops do not lead to differences. Make sure all lines of code are executed several times before you begin to trust the results, to allow JIT compilers to have already stabilized to a full dynamic recompilation (dynarec).
In fact, I witnessed precision approaching microseconds on certain systems, but I wouldn't trust it yet. But the 0.1 millisecond precision appears to work quite reliably, on an idle quad-core system where I'm the only browser page. I came to a scientific test case where I could only do one-off passes (due to unique variables occuring), and needed to precisely time each pass, rather than averaging multiple repeat pass, so that's why I did this.
I did several pre-passes and dummy passes (also to settle the dynarec), to verify reliability of 0.1ms precision (stayed solid for several seconds), then kept my hands off the keyboard/mouse, while the benchmark occured, then did several post-passes to verify reliability of 0.1ms precision (stayed solid again). This also verifies that things such as power state changes, or other stuff, didn't occur between the before-and-after, interfering with results. Repeat the pre-test and post-test between every single benchmark pass. Upon this, I was quite virtually certain the results in between were accurate. There is no guarantee, of course, but it goes to show that accurate <0.1ms precision is possible in some cases in a web browser.
This method is only useful in very, very niche cases. Even so, it literally won't be 100% infinitely guaranteeable, you can gain quite very trustworthy accuracy, and even scientific accuracy when combined with several layers of internal and external verifications.
Here is an example showing my high-resolution timer for node.js:
function startTimer() {
const time = process.hrtime();
return time;
}
function endTimer(time) {
function roundTo(decimalPlaces, numberToRound) {
return +(Math.round(numberToRound + `e+${decimalPlaces}`) + `e-${decimalPlaces}`);
}
const diff = process.hrtime(time);
const NS_PER_SEC = 1e9;
const result = (diff[0] * NS_PER_SEC + diff[1]); // Result in Nanoseconds
const elapsed = result * 0.0000010;
return roundTo(6, elapsed); // Result in milliseconds
}
Usage:
const start = startTimer();
console.log('test');
console.log(`Time since start: ${endTimer(start)} ms`);
Normally, you might be able to use:
console.time('Time since start');
console.log('test');
console.timeEnd('Time since start');
If you are timing sections of code that involve looping, you cannot gain access to the value of console.timeEnd() in order to add your timer results together. You can, but it get gets nasty because you have to inject the value of your iterating variable, such as i, and set a condition to detect if the loop is done.
Here is an example because it can be useful:
const num = 10;
console.time(`Time til ${num}`);
for (let i = 0; i < num; i++) {
console.log('test');
if ((i+1) === num) { console.timeEnd(`Time til ${num}`); }
console.log('...additional steps');
}
Cite: https://nodejs.org/api/process.html#process_process_hrtime_time
The answer is "no", in general. If you're using JavaScript in some server-side environment (that is, not in a browser), then all bets are off and you can try to do anything you want.
edit — this answer is old; the standards have progressed and newer facilities are available as solutions to the problem of accurate time. Even so, it should be remembered that outside the domain of a true real-time operating system, ordinary non-privileged code has limited control over its access to compute resources. Measuring performance is not the same (necessarily) as predicting performance.
editing again — For a while we had performance.now(), but at present (2022 now) browsers have degraded the accuracy of that API for security reasons.

What is considered a fast or slow load w/ respect to a web page

I just built a web page that is employing several different javascript elements. I am just curious as to what is considered a fast vs. a slow load time. Mine is coming out to be about 490ms w/ four different javascript pieces. Is that good, bad or average? Wondering if I need to optimize my js elements or not.
There's a paper from 1991 called “The information visualizer, an information workspace”, by Card et all (Xerox Palo Alto Research Center) that says:
0.1 second is about the limit for having the user feel that the system is reacting instantaneously, meaning that no special feedback is necessary except to display the result.
1.0 second is about the limit for the user's flow of thought to stay uninterrupted, even though the user will notice the delay. Normally, no special feedback is necessary during delays of more than 0.1 but less than 1.0 second, but the user does lose the feeling of operating directly on the data.
10 seconds is about the limit for keeping the user's attention focused on the dialogue. For longer delays, users will want to perform other tasks while waiting for the computer to finish, so they should be given feedback indicating when the computer expects to be done. Feedback during the delay is especially important if the response time is likely to be highly variable, since users will then not know what to expect.
A detailed overview can be found here.
Bottom line: if we want a fluid user experience, our apps need to operate at 10+ 'fps' :)
Just run your site through this tool and you'll know (almost) all there is to know about loading times. Or use Google's Speed Tracer if you use Chrome.
Try to think from the users point of view:
Instead of measuring the response time of xyz XHR request, consider the function the user wants to perform - "post a comment on this website"? Then measure the total time to achieve that goal. If the users work, as a whole, is too much or takes too long then they will go elsewhere.
eg. I can have 10 XHR functions that return in 15ms each it might seem blazing fast. But if the user has to click 10 different places to post a comment, they're going to get sick of my interface pretty quick too.
(extreme example)
This is going to vary from system to system. But if it's taking less than a few seconds to load everything (completely - dom ready), that's pretty good if you ask me. I recall keeping my entire project size down to about 50kb, back before we had all of this fancy ajax :) Cherish your broadbands and asynchronous calls!
If I remember well a podcast about StackOverflow (I can't find which one it is anymore, on DNR or on Hanselminute), above 1 sec the user starts to have the time to be distracted by something else and loose focus. At 10 seconds, I would probably already have closed your page!
of course it depends on what kind of action it is. but if it's a repetitive task, 1 second is the maximum I would say. That's what I aim to in general. It feels instant when you go under that limit.
The general rule of thumb is that the maximum attention span of a web surfer is 10 seconds*. Anything longer and they'll use another site.
*note: I read that somewhere but can't remember where.

Categories

Resources