Jakub Stachowski, who just committed a significant performance improvement to KConfig parsing, which, with previous improvements of his, made it about 4.5 times faster than the initial KDE4 version, and slightly faster than the KDE 3.5.9 one.
sad eagle's blog
Say hello to KJS/Frostbyte -40.9° and Icemaker
Submitted by sad eagle on Mon, 03/10/2008 - 14:10. KDE GeneralIf you've been scanning KDE commits lately, you may have wondered about heavy activity on an experimental KJS branch, KJS/Frostbyte. Well, while it's still not 100% done (there are a couple bugs, and not all goals have been met yet), it's complete enough that I am comfortable to blog about it.
KJS/Frostbyte is a bytecode and performance improvement version of KJS, which aims to both provide an immediate speed up, and the infrastructure for further improvements. Right now, if I didn't screw up my notes, it's showing ~1.4x speedup over KDE4.0.2 version of KJS on the SunSpider benchmark suite.
Now, you might wonder why "bytecode" and "performance improvement" are two separate bullets. Doesn't bytecode usually mean "faster?". Well, in this case, only somewhat; much of speedup comes from other changes. KJS's traditional recursive nature matched very well with how ECMAScript is specified (ad hoc big-step operational semantics, basically), so it really didn't have much overhead.
The value of bytecode is more:
- It separates out the representation during parsing from the representation used during execution. This means they can both be kept as clean as possible. Previously, various optimizations would require things such as splicing of nodes (or the horrific, though clever, in-place replacement in JSC)
- It provides a much simpler, flattened program form to operate on and reason about, opening the possibility of doing fancier things in the future. A lot of the subtler trickiness in the language is made far more explicit, too.
To help with both, and to stay flexible, we do not hand-code the bytecode language. Instead, a description file with a list of IR types, instructions, etc., is fed to a special tool I wrote, Icemaker.
Icemaker converts that into:
- The virtual machine main loop
- Instruction description tables, which with some enhancement could
perhaps be used to drive a dataflow engine - Instruction selection and conversion cost tables
Here, too, we have a layer of indirection, keeping things cleaner. For a subtraction operation, we can describe its bytecode merely as:
operation Sub {
impl number(number v1, number v2) [[
$$ = v1 - v2;
]]
}
Then, when compiling JavaScript into bytecode, we merely ask for an Op_Sub with given arguments. Sounds trivial? Well, it's not quite that simple, since the arguments don't have to be numbers. Using the tables Icemaker built, the instruction selection engine can automatically put in conversions, if needed. It can also do better than that, and pick a more efficient variant, if more than one is described:
operation BracketGet {
impl value (value v1, value v2) costs 50 [[
// snip code
]]
overload value (value base, int32 prop) [[
$$ = base->getByIndex(exec, prop);
]]
}
With this, little tweaks to the IR can be tried easily, and specializations can often be done w/o even touching the compiler proper...
Coming up at some point later: some benchmark numbers... After I figure out what's wrong with this ScopeChainNode allocation optimization, anyway.
Debugging the debugger.
Submitted by sad eagle on Wed, 12/19/2007 - 22:31. KDE GeneralI've spent some time recently trying to get Konqueror's JavaScript debugger in a shippable form for 4.0. The debugger was changed heavily from the 3.x version in a SoC project, making ground for much nicer UI. Unfortunately, it also barely worked.
I've fixed up a chunk of the issues, but there is still a long way to go in fixing up some remaining holes, and doing testing to improve stability. But, it's at least good enough for a screenshot:
![]()
... as well as some simple debugging tasks. Anyway, I am sort of curious: what do readers want from such a debugger? Now, I probably can't incorporate any non-minor suggestions in 4.0 (feature/string freeze), but it'd be good to know what direction to take, and some minor stuff is certainly tweakable.
KHTML: a position statement
Submitted by sad eagle on Wed, 10/24/2007 - 15:02. KDE GeneralI guess sometimes one has to be direct. So, here is what I do and do not believe in:
I am not opposed to:
(1) Dropping our tree in favor of Apple's in general. I am quite aware of the tons of good things they've done (along with a few things I thought were poor decisions); however, I would only want this to happen after some concerns are addressed, and I, perhaps naively, expect that all those people going around talking about how it would be great, and how all those people and businesses are involved would lend a hand. I am a busy guy and my priority is to get things in shape for 4.0.
The truth is, we have done something like this with JavaScript. And why did it happen? In large part because George Staikos did a lot of the heavy work, and convinced me to help. He believed it was right, and he made it happen by working within the community, and doing some of the skull-numbing portions. Of course, it was easier there, due to smaller, less active, codebase, and since regression testing is more robust for programs than for mages. However, that didn't result in a single repository, but rather a close working relationship.
(2) Working with Apple. I do it in JS all the time. See above. We have a pretty good relation with them, where the ideas bounce back and forth, get developed in one repository, and then get incorporated into an another, usually getting improved in the process. It's an unorthodox setup, perhaps, but it lets us work at our own paces and styles and have some reasonable differences
based on those in our goals and value systems.
So what are my concerns, then?
I am opposed to:
(1) Dropping our source tree w/o a good undestanding of what's being regressed.
(2) Dropping our source tree w/o being sure that the interests of KDE community are going to be represented, and that the development setup will not be isolated from KDE contributors.
I do not think our interests can survive long term if we don't provide a way for people to get interested in web stuff when they originally didn't plan of it. This should actually not be too hard these days, because a lot of Apple people have earned our utmost respect, unlike some of the folks alluded to by the very last bullet
(3) Dropping our source tree in a way that drops API compatibility. It doesn't matter what tree the renderer is based on, one can still provide a libkhtml that's backwards compatible for all applications. The only thing that would cause problems for doing that would be using whatever TT ships, since it would have a different API and hide the internals.
(4) Having to rely on someone else to get bugfixes out to our users (or more importantly security fixes). Call me selfish, but if I spend a weekend fixing something, I want to know that it'll get to KDE users by a certain KDE release, and not when TrollTech feels like shipping a release. I want to be able to provide improvements with each KDE release, I don't care about versions of Safari or Qt including it or not.
I am more than disappointed by:
(1) Attempts by people who have never touched KHTML to bypass concerns of the active maintainers and contributors by misleading PR campaigns, such as articles making definitive statements on future of something, written without asking people working on it. Or, by defining maintainer as "someone who didn't touch something for 3 or more years".
Canvasing the vectors
Submitted by sad eagle on Mon, 10/15/2007 - 22:34. KDE GeneralAs some of you may have known, KHTML in trunk has support for the <canvas> element. Unfortunately, it was based on some very old and borderline insane Apple code, which meant that except for the nice graphics bits written by Zack, it was all wrong, and when it worked, did so mostly by accident.
Well, not any more. Over Friday evening and parts of Saturday I rewrote most of it, doing my best to bring it in line with HTML5. Allan helped out by making it parse right. Well, it works pretty well now, good enough for the obligatory screenshot:
![]()
Yes, there are still bugs. There are some missing features (some due to Qt limitations, some due to me thinking they are horrific ideas, and lots due to me not being sufficiently familiar with modern inefficient vector graphics), but it should all be incremental from this.
Animated GIFsanity
Submitted by sad eagle on Sun, 10/07/2007 - 22:24. KDE GeneralSo I thought I would spend a tiny bit of time on the weekend trying to get khtml 4.0's gif decoder all finished. Yeah, right. Decoding the frames themselves is easy: giflib does it for us. The messy part comes when it comes to putting them together into an animation.
The way this roughly works is the following: gif has a canvas, which it calls the screen. It provides a palette, the index for the background color in it, and of course the dimensions.
For an animated gif, there is then a sequence of frames, each of which specifies the portion of the screen the frame touches. There may also be a per-frame palette, and a transparency colorkey. More interestingly there is a disposal mode, which specifies how to transition to the next frame:
- unspecified (always a good sign in a spec. Not!)
- leave screen as is
- clear to background
- revert to state before this frame
Sounds easy enough? Well, too bad it's not the entire picture.
Consider for example the mode 2: clear to background. For most images it behaves by clearing to transparency. What's the big deal? Well, the place the background color is specified is with the global palette... and there is no transparency in there! Transparency colorkey is specified per-image, so... how exactly is it supposed to work? Does one interpret background color inside the current frame's palette (which may be a local palette, or the global palette with the transparency colorkey overlaid..)? Does one just use transparency for background if there is transparency involved? Beats me.
And that, actually, isn't the worst. The messy part comes from compositing images. The images have transparency, so when one draws the new frame over the current canvas state, one has to combine them together. There are 2 ways of doing it:
- only draw non-transparent pixels (the over operator).
- copy over everything, overwriting non-transparent
pixels with transparency (the src operator).
So which one is right? Both. There are images that need one mode, and there are images that need another... and one can easily construct images where both are in use, and it's entirely unclear how e.g. mozilla decides on which way to do things.
Anyone reading this know what's going on there?