I've noticed an odd behavior in a program I am working on. While it's probably my fault, I wanted to check if someone faced this before.
Both with console.time and performance-now my code has highly variable run time. I can't exactly paste it here because it's work related, but the workflow is:
start timer
load image via jimp
when image is loaded, scale image times 2
scan the image, transform pixels in zeroes and ones and put it into an array
log time
Some discrepancy is sure to be expected, but the results are so different I'm wondering what I did wrong. Average time is short, but the outliers are pretty... well, you can see on the image below.
I've been working on a 2D game in JavaScript using the canvas, and I found that requestAnimationFrame seems to make the game much smoother, which is great. However, the game has been freezing at random times ever since. The tab becomes stuck, and the game doesn't throw any errors, so I'm kind of at a loss. I have tried many things to manually debug it, such as constantly updating a LocalStorage variable, just displaying in the console, etc. Nothing is really giving me any results.
I can say that my experiments lead me to believe that there may be some strange asynchronous behavior associated with requestAnimationFrame; namely, I have noticed that if I change the size of something via socket.on, such as an array, and the game happens to be running a for-loop on that array, it sometimes crashes mid for-loop saying that the thing I'm referencing is undefined, even though I check for that right before the for-loop. Moreover, I noticed that when requestAnimationFrame calls code, such as my Game.update() function, sometimes the "this" object isn't properly referencing the object I'm in. ie., in Game.update(), this.draw_something() would throw an error. I have fixed those issues I believe, but I'm wondering if anyone has any insight into the overall nature of requestAnimationFrame.
The last thing I want to mention is that when the tab freezes, the memory begins to sky-rocket. It quickly goes from a few hundred MBs (from pre-loaded gfx, etc) to around 2 gigs, and continually increases.
I hope someone has some good feedback - and thanks in advance.
I have an animation loop running in which I'm getting an error that reads...
GL ERROR :GL_INVALID_OPERATION : glDrawElements: Source and destination textures of the draw are the same.
This error pops up after between 2 and 3 animation frame requests, depending on whether I've refreshed or hard refreshed the screen - and even then the timing of the error is not consistent. A hard refresh may occasionally delay the error from showing up until after 3 frame requests, but most of the time for both a refresh and hard refresh the error shows up after 2 frame requests. Based on those observations, the problem seems to be in an asynchronous component. I also have a simpler toy version of this loop running without any errors. I've been simplifying the buggy program more and more (it's now just displaying a non-moving cube) and still can't find the source of the problem.
The program is decently complex, so it's hard to determine what code to show here, so instead I'm hoping for an answer that may teach me a little about approaching a problem like this generally, so I can apply it whenever I hit similar situations: My question is, what are the top candidate areas in a program for a problem like this? Knowing that, I can focus my efforts.
I hope this makes sense - let me know if you need further clarification. Thanks!
Update:
This seems quite basic, but I will add that when I put no objects in the scene (cubes, axis helpers, etc.) and leave everything else the same, the error goes away.
Also, I'm wondering if this sort of error can occur because of a lost context? Like so.
You probably need to post your code but just guessing...
First off the error is exactly what it says it is. You have a texture attached to the current framebuffer. That same texture is also assigned to some texture unit.
Why that happens intermittently I can only guess. If you're loading textures from images or even from dataURLs they load async. Being in the cache or if you're testing locally they'll load quickly. So, my guess would be you're not correctly setting your texture units every frame (calling gl.activeTexture and gl.bindTexture for each texture unit used by your shaders). When your image is finally downloaded async you call gl.bindTexture to upload the texture. That ends up assigning a texture to whatever the current active texture unit is and messes up your setup.
I have this web app that creates rows and columns of holes. With each hole there can also be text and a path or 2 associated with it. I have all of these stored in a set. The user also has the option of moving this set using free_transform.js. It works great if I have less than 50 holes; less in Firefox for some reason. But the problem really shows itself when the user decides to create a grid of 100 or more holes.
The functionality works fine; it's just that the animation is slow to catch up to my mouse movement. At worst I would say the delay is 2 seconds, but as a client that would be really annoying and of course we don't want to annoy the client.
My question is does anyone have experience using Raphael/free_transform in this context? Is there a better solution? Are the tools I am using insufficient for my goal?
I'm playing some notes at regular intervals. Each one is delayed by a random number of milliseconds, creating a jarring irregular effect. How do I fix it?
Note: I'm OK with some latency, just as long as it's consistent.
Answers of the type "implement your own small SoundManager2 replacement, optimized for timing-sensitive playback" are OK, if you know how to do that :) but I'm trying to avoid rewriting my whole app in Flash for now.
For an example of app with zero audible latency see the flash-based ToneMatrix.
Testcase
(see it here live or get it in an zip):
<head>
<title></title>
<script type="text/javascript"
src="http://www.schillmania.com/projects/soundmanager2/script/soundmanager2.js">
</script>
<script type="text/javascript">
soundManager.url = '.'
soundManager.flashVersion = 9
soundManager.useHighPerformance = true
soundManager.useFastPolling = true
soundManager.autoLoad = true
function recur(func, delay) {
window.setTimeout(function() { recur(func, delay); func(); }, delay)
}
soundManager.onload = function() {
var sound = soundManager.createSound("test", "test.mp3")
recur(function() { sound.play() }, 300)
}
</script>
</head>
<body>
</body>
</html>
I know this isn't the answer you want to hear, but there is no way to stop this, regardless of whether you wrote your own flash library to play sound or not.
For everyone who said "it works fine for me!" try resizing or moving your browser window as the poster's demo plays out. You'll hear more than just a subtle amount of delay. This is most noticeable in Firefox and IE, but even Chrome will experience it.
What's worse, if you click and hold the mouse down on the close box for the browser window, the sound completely stops until you release your mouse (you can release it outside of the close box and not actually close the window, FYI).
What is going on here?
It turns out that when you start resizing or moving around the browser window, the browser tries to multi-task the act of changing the window properties with the act of keeping up with the javascript going on in the window. It short-changes the window when it needs to.
When you hold down the mouse over the close box in the browser window, time stops completely. This is what is happening in smaller increments when you are re-sizing or moving the window: time is standing still in the javascript world in small, sporadic chunks (or large chunks, depending on how slow your machine is).
Now, you might say "sure, resizing the browser or holding down the close button makes the browser pause, but normally this wouldn't happen". Unfortunately you would be wrong.
It happens all the time, actually. I've run tests and it turns out that even by leaving the browser window completely still, not touching the mouse, and not touching the keyboard, backgrounds processes on the computer can still cause "hiccups", which means that for brief periods (perhaps as small as a few milliseconds) time is "standing still" in the browser, at completely random intervals outside of your control.
What do I mean by "standing still"? Let's say you have a setInterval() call (this applies to setTimeout also) running every 33 milliseconds (about 30 frames per second). Now, you would expect that after every 33 "real world" milliseconds your function would get called. And most of the time, this is true.
But when "hiccups" start happening, your setInterval call might happen in 43 milliseconds. What happened during the 10 ms? Nothing. Time stood still. Nothing on the browser was being updated. If you had sound playing, it will continue playing, but no NEW sound calls would start playing, because no javascript is being executed at all. If you had 5 setInterval() functions running, they would have all been paused for 10ms at some point.
The only way to tell that "time stood still" is to poll real-world time in your setInterval function callbacks. You'll be able to see that the browser tries to keep up most of the time, but that when you start resizing the window or doing something stressfull, the intervals will be longer than usual, but that all of your code will remain synched up (I'm making games using this technique, so you will see that all your game updates happen in synch, but just get slightly stuttered).
Usually, I should point out, these stutters are completely unnoticeable, and unless you write a function to log real-world time during setInterval times (as I have done in my own testing) you wouldn't even know about it. But it becomes a problem if you try to create some type of repetitive sound (like the beeping in the background of Asteriods) using repetitive play() calls.
My suggestion? If you have a sound that you know will loop, give it a long duration, maybe 10 seconds, and you'll be less likely to notice the hiccups (now, the graphics on the screen could still hiccup, but you're screwed there).
If you are writing a game and having the main character fire off a machine gun, don't do 10 rapid-succession calls to playSound('singleShot'), do one call to playSound('machineGunFire10Rounds'), or something along those lines.
You'll have to do some trickery to get around it, but in most cases you'll be alright.
It seems that Flash applets run in a process that is somehow less affected this whole "time freezing" thing going on in the regular browser/javascript environment, but I can still get it to happen, even on your link to the ToneMatrix example, by resizing or moving the browser window.
But Flash still seems much better than javascript. When I leave the browser alone I'd be willing to bet that Flash is not freezing for any amount of time and that intervals are always running on time.
tl;dr:
you're screwed in what you're hoping to achieve
try to deal with it using some workarounds
re-write your project in pure flash (no javascript)
wait for browsers to get better (Firefox 4 is getting a new javascript engine called JaegerMonkey which will be interesting to watch)
how do I know all this? I've done a lot of testing & logging with javascript, setInterval, and soundManager/html5 audio calls
In my comment to your question I mentioned that I don't hear the irregularity when I play your sample. That means I'm either "rhythm deaf", or that there may be something in your setup that interferes with good realtime performance. You don't mention any details of your environment, but you may have other processes running on your computer that are sucking up CPU cycles, or an older version of Flash that may not do a good job of handling sound latencies. I myself am using a recent version of Flash (10.something), whereas your parameters call for Flash 9. But maybe I should assume that if you're smart enough to be using SoundManager2 and StackOverflow that you would have eliminated these problems.
So here are some troubleshooting possibilities and comments that come to mind:
1) the SoundManager site has a number of demos, including JS-DOM "painting" + Sound, V2. Are you hearing irregular latencies and delays there? If not, maybe you can compare what they're doing there against what you're doing. If you are, then maybe look at your machine environment. When I run that demo, it is very responsive. (EDIT: Looking at it more closely, however, you can watch how the size of the brush stamps varies during a stroke. Since it varies with the time interval between mouse events (assuming you are keeping a constant mouse speed), you can visually see any irregularities in the pattern of mouse events. I can see occasional variation in stamp sizes, which does indicate that mouse events are not coming in at regular times. Which brings us to Javascript events.)
2) Javascript setTimeout() and setInterval() are not very reliable when it comes to timing. Mostly they will come back in some ballpark of the interval you have requested, but there can be large variations, usually delays, that make them unreliable. I've found that the same is true when using ActionScript inside Flash. You might want to print out the times that your sound.play() call is being made to see whether the irregularities are due to the irregularities in setTimeout/setInterval(). If that's the case, you could try shortening the interval, and then polling the system time to get much closer to the 300ms interval that you want. You can poll system time using new Date().getTime(), and this seems to have ms accuracy. Polling is of course a hideous hack that sucks up cycles when they could be used for something else, and I don't recommend it in general, but you may try it to see whether it helps. EDIT: Here's a writeup by John Resig on the handling of input and timer events in js.
3) When flash plays sounds, there is usually a latency involved, just so that the player can "build up a head of steam" and make sure there's enough stuff in the buffer to be played before the next buffer request is filled. There's a trade off between this latency and the reliability of uninterrupted playback. This might be a limitation you can't do anything about, short of "implement[ing] your own small SoundManager2 replacement", which I know you don't want to do.
Hope this helps. I recently wrote an AS3 sound experiment which exposed me to some of the basics, and will be watching this space to see what other suggestions people come up with.
You are using the javascript interval, which can not be guaranteed to fire at an exact time. I am sure that the internal Flash timing is far more reliable.
But this might help, fire recur AFTER you have triggered playing the sound.
window.setTimeout(function() { func(); recur(func, delay); }, delay);
As explained in another answer, there's no way you can avoid this. But...
I've done some experiments to mitigate this issues, and in the end I resorted to using:
lowLag: responsive html5 audio, which uses SoundManager2 for some cases where it's the fastest option available.
GSAP JS – Professional-Grade JavaScript Animation, in order to do the animation of properties and syncing of the audio (you probably don't care about this :P)
Take a peek at the source on the prototype of the demo, and (if possible) give lowLag a shot. It worked nicely for me.
Good luck!