July 23rd, 2007
Today I was working with JavaScript objects and I had to do something that required calling a parent function from the subclass function that overrides it. So I had a parent class and a subclass:
I tried a few things, like Douglas Crockford’s inheritance patterns, but they wouldn’t give me access to Parent.myPrivate from within Parent.myFunc. The problem had to do with scope: they would use Function.apply to call Parent.myFunc, using SubClass’s scope. JavaScript doesn’t give inherited classes access to the parent classes’ private variables. So something like this doesn’t work:
I found a bunch of other ways to deal with inheritance, none of which worked the way I needed. I ended up doing having to make an alias for Parent.myFunc before defining the overridding method. Here’s the entire source:
July 12th, 2007
I was reading Dennis Forbes’s take on JavaScript string concatenation in Firefox and IE, and I realized I had an opportunity to increase the performance of my raycaster. I’m currently rendering by building a giant string of HTML that is inserted into the frame using innerHTML. But because of the way string are handled, this can get slow. If I can replace concatenation with an Array.join, there should be a noticable speed boost. But first, some benchmarks.
Here’s a standard string builder, like what I’m currently using:
And this is what it might look like using an array:
Both are supplied with a base string and a iteration count. By varying the length of the base string and the count, we can find how the functions compare. Here are the IE7 results from averaging 100 runs. The columns represent the iteration count, the rows are base string length, and each cell gives the standard string building time (in ms) and the time using Array.join.
|
500 |
1000 |
2000 |
4000 |
| 1 |
1.12 / 0.59 |
2.4 / 1.03 |
6.37 / 2.05 |
14.09 / 4.25 |
| 4 |
1.36 / 0.53 |
3.6 / 1.16 |
10.35 / 2.17 |
32.75 / 4.21 |
| 16 |
2.75 / 0.73 |
8.45 / 1 |
28.78 / 2.19 |
106.67 / 4.74 |
| 64 |
7.45 / 0.75 |
27.16 / 1.29 |
90.38 / 2.51 |
407.3 / 6.02 |
The results are pretty staggering. For the longest strings (which total 256000 characters), using arrays is more than 65 times faster.
Now for Firefox 2:
|
1000 |
2000 |
4000 |
8000 |
| 1 |
0.95 / 1.71 |
2.24 / 22.37 |
5.64 / 8.28 |
17.3 / 23.51 |
| 4 |
1.54 / 2.27 |
4.79 / 6.12 |
24.73 / 9.18 |
9.41 / 14.9 |
| 16 |
1.86 / 2.52 |
3.33 / 4.09 |
4.46 / 7 |
26.85 / 13.3 |
| 64 |
1.84 / 2.11 |
3.22 / 3.91 |
7.53 / 9.4 |
174.42 / 174.96 |
Notice that the iterator counts for Firefox are twice what they were for IE. This is because Firefox does string concatenation much better than IE.
Also notice that some Firefox numbers are inconsistant. For example, with a base string of length 4, the highest iterator count ran faster than the second highest for standard concatenation. I don’t know why it does this, but every time I ran it, at least one set of results was out of line. Regardless, it’s easy to see that Firefox did not benefit from using Array.join at all. This is probably because Firefox knows that concatenations that are essentially appends can by optimized, as Dennis Forbes explains. If the line s = s + a is replaced with s = a + s, Firefox is considerably slower. Much slower than IE, in fact. But I intentionally used s = s + a because it’s how my raycaster works.
Finally, notice that IE is actually faster than Firefox when using Array.join.
I’ll post another update when I implement this into my raycaster.
Aside
In order to get these results, I had to create some testing functions. I ended up with a pretty solid set of routines, complete with bar-graphs, and I’d like to extend it to something more complete and robust.
Update
I made a quick implementation but it didn’t speed up my raycaster much. After some quick and dirty speed tests, it looks like the bulk of the rendering time is spread across the actual ray casting and intersection testing, and the browser actually drawing the sprites and the walls.
July 6th, 2007
I was working on some javascript for things like fading and animation. These functions all have a similar structure:
And I wanted to abstract this away to an iterator function so I could do something like:
This would execute the anonymous function repeatedly until it returns false. Here’s what I came up with:
It works by creating an anonymous function that sets a callback to itself. Since there’s no way to call anonymous functions directly, it is called with itself as a parameter.
It also allows specifying an “end” function that is called after the iteration finishes. This end function can set up an iterator itself. So, to move an element right, then fade it out, you could do:
This came up when I was working on LAMEO. I was designing a AJAX response handler and wanted a way to easily do UI effects and chain events so they happen back-to-back. I’m not sure if I’ll end up using it, but it was fun to make.
Update
Here’s a slightly improved version:
This way, no parameter is passed to the function created. Other than that it’s the same.
July 5th, 2007
I’ve updated my javascript raycaster with a fix to a problem that caused the sprites to be downloaded repeatedly.
Earlier this week a “fully texturized first-person shooter in 4003 bytes of JavaScript” appeated on programming.reddit, which inspired me to revisit mine. I was a little disappointed with 3D Tomb. I was hoping someone solved the texturing problem I’ve struggled with, but it turned out to be very low-res. Still, it’s pretty cool, and far closer to an actual game than mine.
July 5th, 2007
Take a look at this CSS:
and this HTML:
Now, which div is on the top? blue, of course, because it has the highest z-index, right? Wrong. red is on top because .. well, I’ll get to it. But anything inside the wrapper is behind anything before the wrapper, regardless of the z-index.
According the the CSS spec (http://www.w3.org/TR/CSS21/visuren.html#z-index) (and the elaborate appendix (http://www.w3.org/TR/CSS21/zindex.html)), this is the designed behavior:
The contents of inline blocks and inline tables are stacked as if they generated new stacking contexts, except that any elements that actually create new stacking contexts take part in the parent stacking context. They are then painted atomically in the inline stacking level.
Essentially, elements with different parents cannot be intermixed. z-index is only used to order adjacent elements. So, for this example, the renderer says, “red has an index of 2, and wrapper has a default index of 0, so red, and all its children, are in front of wrapper and all its children”.
Aside
This came up when I was working on my raycaster. In my previous version, sprites were handled by inserting img tags using innerHTML. The walls are handled in the same way, and the sprite HTML is just tacked on the the end of the wall HTML. But doing this causes the browser (both IE and Firefox) to send extraneous HTTP requests whenever an image is inserted. My immediate solution was to the use persistant nodes for the sprites and just move them by setting the styles.
Unfortunately, since the code for creating the walls uses the same innerHTML, I had to break the sprites out into a separate part of the structure:
became:
Which, like in the opening example, meant that each sprite would be either in front of every wall, or behind every wall.
The correct solution is to preload the images. By throwing all the images into a div with display: none, they get cached correctly.
July 1st, 2007
Programmers don’t like writing documentation; documentation is important; most documentation is bad. Blah, blah, blah, you’ve heard it all before. There are plenty of tools that help you with documentation, mostly by automating it somehow. I’ve tried a few, but none of them have helped at all.
I think the problem is not writing documentation so much as keeping up-to-date documentation.
Imagine you start writing a function that will foo all supplied bars and return foobars. You put a comment at the top of the function to state this. Then later you change the function to make it baz all bars in addition to fooing them. And you forget to update the comment.
You now have incorrect documentation, which is worse than no documentation at all.
The solution is for the IDE to keep track of when each comment and each function was last updated. If the function is newer than the comment, highlight the comment as old. Add in a little reporting feature (list all functions with old comments), and the quality of documentation will improve.
Now it’s easy to see where the documentation suffers with nothing more than a glance. This solves the problem by removing the requirement that the programmer actively keeps track of documentation and gives the task to the IDE. It could also be extended to documentation written in, say, Word. Tie each piece of the document to a function or file and use the same logic for finding the old stuff.
I haven’t seen this before, but I’d be surprised if no one has done it yet.
|