sad eagle's blog

    sad eagle's picture

    News from the land of Konquerors

    2008
    22
    May

    A bunch of exciting things have happened to Konqueror in preparation for 4.1 Beta 1 this weekend.

    First of all, KHTML guru Germain Garand has committed the bulk of the designMode/contentEditable editing code. It's not 100% done yet, but it's a monumental amount of work, and it should enable the various rich-text editor apps to work in KHTML.

    In the UI land, Eduardo Elvira has committed some fancy session management features such as crash recovery.

    But, I am gonna be bit a bit selfish, and mostly talk about what I did: my performance/bytecode version of KJS - KJS "Frostbyte" - is now in kdelibs trunk, and part of KDE4.1 Beta 1. This brings some significant pure ES performance improvements over previous versions, and lets us put up some great numbers. On the SunSpider benchmark suite, this version does:

    • 2.27x better than Firefox 2
    • 2x better than QtWebKit from Qt4.4
    • About 1.4x faster than KJS 4.0 "Blizzard"
    • About 1.152x faster overall than Opera 9.5 beta 2, but it's really a wash, with both engines winning lots of individual benchmarks...

    .. but about 1.77x slower than Firefox 3rc1. Ouch. Well, at least we beat them on Acid3, and it might just keep my head from getting too big. Great job by the Mozilla guys there, though. And the Apple guys of course aren't standing still either --- the development versions of JavaScriptCore/Safari have excellent optimizations we lack, and will likely be getting their own bytecode engine, SquirrelFish, soon (I name things after weather. They name them after weird animals. I think you can see who lives in California, and who lives in New York State).

    Thankfully, I have some tricks left up my sleeve. Which isn't very comfortable, since I am wearing a t-shirt.

    And if you care, or are really bored, the numbers are under the cut.

    sad eagle's picture

    People who rock

    2008
    21
    Apr

    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 picture

    Say hello to KJS/Frostbyte -40.9° and Icemaker

    2008
    10
    Mar

    If 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:

    1. The virtual machine main loop
    2. Instruction description tables, which with some enhancement could
      perhaps be used to drive a dataflow engine
    3. 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.

    sad eagle's picture

    Progress...

    2008
    25
    Feb

    ... can take many forms. Some less exciting than others:
    [image:3297]

    sad eagle's picture

    Debugging the debugger.

    2007
    19
    Dec

    I'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:
    [image:3159]
    ... 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.

    sad eagle's picture

    KHTML: a position statement

    2007
    24
    Oct

    I 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".

    sad eagle's picture

    Canvasing the vectors

    2007
    15
    Oct

    As 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:
    [image:3032]

    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.

    sad eagle's picture

    Animated GIFsanity

    2007
    7
    Oct

    So 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:

    1. unspecified (always a good sign in a spec. Not!)<.li>
    2. leave screen as is
    3. clear to background
    4. 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:

    1. only draw non-transparent pixels (the over operator).
    2. 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?