Morten Johan Sørvig
Qt
Test
Aggregated
 in Qt, Test, Aggregated
 on Friday, December 05, 2008 @ 13:03

One of the focus areas for 4.5 is performance. To that end, we decided to add a couple of benchmarking extentions to our beloved QTestLib.

There is exactly one new API, the QBENCHMARK macro:

    QString str1 = "foo";
    QString str2 = "foo";

    QBENCHMARK {
        str1.localeAwareCompare(str2);
    }

(Full example is available at $QTDIR/examples/qtestlib/tutorial5.)

Under the hood, the benchmark macro starts the timing measurements, and then repeats the code under test enough times to get a measurable result. Running this test produces the following output:

RESULT : TestBenchmark::simple():
     0.00094 msec per iteration (total: 31, iterations: 32768)

The default measuring back-end is based on QTime, and in this case we needed 32768 iterations in order to get a result. Repeating the code this many times is not ideal, since it takes a lot of time and might give inaccurate results due to caching effects. On select platforms we therefore have CPU tick counters available, which can be invoked by specifying “-tickcounter” on the command line:

./mytest -tickcounter
RESULT : TestBenchmark::simple():
     3,206 ticks per iteration (total: 3206, iterations: 1)

There is also callgrind-based measurer available on linux/x86 systems, which produces 100% reliable instruction counts, but does not take things like I/O waits into account.

Benchmarking a single API is fun, but to be useful we have to compare it against something. Let’s add some data:

void TestBenchmark::series_data()
{
    QTest::addColumn(”useLocaleCompare”);
    QTest::addColumn(”stringSize”);

    for (int i = 1; i < 10000; i += 2000) {
        QByteArray size = QByteArray::number(i);
        QTest::newRow(("locale aware compare--" + size).constData()) << true << i;
        QTest::newRow(("standard compare--" + size).constData()) << false << i;
    }
}

We’re benchmarking QString::localeAwareCompare() vs QString::operator==(), for different string sizes. The test function now looks like this:

void TestBenchmark::series()
{
    QFETCH(bool, useLocaleCompare);
    QFETCH(int, stringSize);

    QString str1 = QString().fill('A', stringSize);
    QString str2 = QString().fill('A', stringSize);
    int result; // assign to result to prevent the optimizer from optimizing the compare away.
    if (useLocaleCompare) {
        QBENCHMARK {
            result = str1.localeAwareCompare(str2);
        }
    } else {
        QBENCHMARK {
            result = (str1 == str2);
        }
    }
}

This gives lots of results:

RESULT : TestBenchmark::series():"locale aware compare--1":
     0.00067 msec per iteration (total: 22, iterations: 32768)
RESULT : TestBenchmark::series():"standard compare--1":
     0.000019 msec per iteration (total: 41, iterations: 2097152)
RESULT : TestBenchmark::series():"locale aware compare--1001":
     0.016 msec per iteration (total: 33, iterations: 2048)
RESULT : TestBenchmark::series():"standard compare--1001":
     0.00056 msec per iteration (total: 37, iterations: 65536)
RESULT : TestBenchmark::series():"locale aware compare--2001":
     0.031 msec per iteration (total: 32, iterations: 1024)
...

It’s hard to make heads or tails of all this, so we decided to create a few tools to help us out. Unfortunately these tools didn’t make the cut for 4.5 (”Shipping Software Means Prioritizing”), but instead we’re making them available here on labs, with bugs and all. (run “git clone http://labs.trolltech.com/gitweb?p=qtestlib-tools” to download.)

So, to generate the nice graph pointing upwards, run the test in xml mode and then feed that xml to the generatereport tool.

./mytest -xml > results.xml
generatereport results.xml

A graph generated by QTestLib (adm: Added a smaller version of the graph)

englich
Qt
Aggregated
Posted by englich
 in Qt, Aggregated
 on Thursday, October 23, 2008 @ 08:44

Thank you, to all who attended Dev Days 2008 in Munich. For me it was really great to talk to so many users and hear about all the baffling projects that people pull off with Qt. And of course, to hear how people use and what people need, in terms of Qt’s XML support.

One customer told about how sub-classes of QObject are used for representing data, and are converted to such from XML. So, why not add a little helper class to Qt for this?

The class, which currently only is a research idea and missed the feature freeze for Qt 4.5, is called QXmlToQObjectCreator, and hopefully the documentation explains it all:

QXmlToQObjectCreator API Documentation

In other words, it’s a very simple class that builds a QObject tree corresponding to the output of QXmlQuery. The current sketched code is pasted here, for those interested.

In what way can this class be made more useful?

      
englich
Qt
Aggregated
Posted by englich
 in Qt, Aggregated
 on Wednesday, September 10, 2008 @ 14:35

A couple of weeks ago, I merged the development branch for XSL-T into our main line, heading for Qt 4.5. The idea is that Qt will carry an XSL-T 2.0 implementation with as usual being cross-platform, having solid documentation, and easy of use.

Using it is should straightforward. Either on the command line:

xmlpatterns yourStylesheet.xsl yourInputDocument -param myParam=myValue

Or using the C++ API[1]:

QXmlQuery myQuery(QXmlQuery::XSLT20);
myQuery.bindVariable("myParam", QVariant("myValue");
myQuery.setQuery("http://example.com/myStylesheet.xsl");
QFile out("outFile.xml");
out.open(QIODevice::WriteOnly);

myQuery.evaluateTo(&out);

See the documentation for the QXmlQuery class on the overloads available for setQuery() and evaluateTo(), for instance.

However, due to the beast XSL-T 2.0 is — I agree that it’s larger than XQuery — we’ve decided to do this according to the “release early release often” approach. The first, in Qt 4.5, will carry a subset, and subsequently be complemented in Qt 4.6. The current status is documented in the main page for the QtXmlPatterns module, which can be viewed in the documentation snapshot.

Therefore, while the current implementation probably falls short on more complex applications(such as Docbook XSL), it can run simpler things, users can plan ahead, and we trolls can receive feedback on what features/APIs that are missing, and what needs focus. So feel free to do that: send a mail to qt-bugs@trolltech.com, or say hello on IRC(FransE, on Free Node).

The code is accessible through the Qt snapshots.

What is XSL-T anyway?

XSL-T is a programming language for transforming XML into XML, HTML or text. Some implementations,  such as QtXmlPatterns or Saxon, provides mechanisms to map XML to other data sources and hence widens the scope of the language by letting the XML act as an abstract interface. Wikipedia has a good article on XSL-T. Version 2.0 of XSL-T extends the language heavily by putting a rigid type system and data model in the backbone, and adds many features that was a pain to miss when programming in XSL-T 1.0. XSL-T 2.0 use XPath 2.0, and shares the same large function library as XQuery.

1.

Over time, Java bindings through QtJambi and ECMAScript bindings through QtScript, will likely arrive.

Andreas
Uncategorized
Aggregated
Posted by Andreas
 in Uncategorized, Aggregated
 on Tuesday, February 05, 2008 @ 17:36

On my way home from work today, I somehow found myself in an awkward situation, laughing as I saw an elder man that I don’t know hit the ground with a thump. Didn’t look too serious, but it most certainly hurt, and it really made my day. Hehe! A wonderful sense of euphoria went through my body as I wondered whether or not I should flip a coin into the air towards this unfortunate fellow, for reasons that probably wouldn’t strike your average observer as being glaringly obvious (in contrary, for also-oh-so-unobvious reasons this might have been perceived as a very rude thing to do, but I don’t quite know why).

So it all started when I was humming and strolling through the streets, past the shops near where I live. Sometimes I enjoy looking at all the funny people around me, at the silly signs people put up outside their stores. I decided to take a trip into the indoor mall. As the weather is pretty harsh sometimes in this country (rain/snow/wind) the mall has this double set of automatic glass doors, mounted like the sluice in a shape ship, to make sure cold air doesn’t get in, and warm air doesn’t get out. So anyway. As I close in on these doors from the outside, I suddenly stop up, and realize that the doors open very slowly today. They’re set up at about half speed. Probably because weather has been bad. I think, “That’s funny, hehe”, and then I continue walking in once the doors are completely open.

Please Spare Some Change

Now, as I’m on my way out again after buying a bag of raisin buns, I see two teenage girls approaching from the outside, all poshed up and chatting like teenage girls do, and suddenly I hear a loud “Bang!” as one of the girls has managed to bang her forehaid on the door as she walked in. “Hehe,” I found myself bursting out aloud. Her reaction was to give me, and then the half-open door the evil eye before shouting “Fy F#¤N i H#”#¤e, er det muuulig!?” [*] And so her friend naturally immediately concurred, “Ja fy f#¤n er det mulig.”

This is truly the age where on one side of the street, your average lady is facing a closed door, and blinking her eyes, hoping that that’ll remove this funny obstruction which she hasn’t encountered before. The door, on its side, is presenting its knob as best it can, wishing it could just say “Here!!! it’s right here!! it’s a KNOB!! you can use it to open me!!”. Your average guy walks straight into the shop window (i.e., that glass thing with no handles, next to the door) BANG, and curses the heavens above, rubbing his forehead and rushing away. These people are angry and upset with a wooden board, or a sheet of glass, failing to meet with their absolute requirements of not being in the way. Ah, astonishing.

And so it happens. Within two seconds after the last girl had just caught her breath, the guy, a man whom I do not know, walks BANG right into the same half-open door. The door did not open (with the speed that he was expecting). His predicted trajectory intersected that of the door-which-moveth-too-slow. ;-) This was an underperforming lame excuse for an automatic door. And so, he fell backwards, dropped his two bags, and whammed into the ground, and of course, he too, cursed out loud, and angry.

And I laughed. I’m evil. I’m sorry. I laughed out loud. :-D

[*] The first girl’s outburst translates to “Oh, darn you bad devil from hell, is this not completely stupid, if at all possible?!?”. The other girl’s response would be something like “Yeah, I soo agree darn, you bad devil, it’s quite stupid, and not likely possible at all.” :-D Norwegian teenage cursing is great fun :-D.

Bradley T. Hughes
Qt
Aggregated
Contributors
 in Qt, Aggregated, Contributors
 on Wednesday, January 30, 2008 @ 06:00

The news about Nokia’s intentions to acquire Trolltech is very exciting and sobering at the same time. I would characterize my own opinions and thoughts as “cautiously optimistic.” As Trolls, we are still digesting the idea, discussing it amongst ourselves, and processing the incoming information from our own management team as well as the information from Nokia.

I hope that our community, both commercial and open-source alike, don’t get too distraught about a seemingly quiet Trolltech team. We, like you, just found out about this yesterday morning and need time to absorb what this means for us, for you, for everyone. After everything sinks in, we will come out with more information in the near future, and we appreciate your patience until then.

Rest assured, Nokia has the best intentions in making this move. More information will be available soon., however the message from Nokia is clear: development, sales, open-source and community support, etc. will continue as usual. Lee Williams, Senior VP, R&D at Nokia, told us Monday that Nokia wants us to teach them how to do cross-platform and open-source development on the desktop (and not just on mobile phones). This is a bit of a special acquisition because both Trolltech, in its current organizational form, and Nokia will be working together on what the future will bring.

englich
Uncategorized
Aggregated
Posted by englich
 in Uncategorized, Aggregated
 on Tuesday, December 11, 2007 @ 14:12

I have not yet seen an API for XQuery in which integrating the data model, atomic values, nodes and all, into the interfacing language has been a walk in the park.

At the top of the list of things people tend to ask on the forums around is “How do I get XML represented as a sequence of bytes in Java/C++ into my query?”, whose result is clear — a tree fragment for the query to operate on — but whose method for reaching is not that given if you ask me.

There is no “bytestream” type in XQuery. Should the user build the tree herself and then pass the tree to the query? Should the implementation in some voodoish way be instructed how to treat a string or custom type? Shouldn’t the query engine do it such that its scope of analysis is increased and its done the way it prefers it?

What I sense have been the problem with some solutions is that they mix the data, the bytestream, with interpretation.

In Qt this manifestate itself with that the content of a QIODevice should appear in a QXmlQuery. The way it’s now provided, is that when a QIODevice is bound to a variable using QXmlQuery::bindVariable(), the query sees a URI(an instance of xs:anyURI) which behind the scenes maps to the QIODevice the user bound. Hence, if the purpose is to build an XML document, one passes the URI to the builtin fn:doc() function.

I hope this is clean. Since it’s handled like any other URI, custom extensions stays at a minimum, error reporting is consistent, and the interpretation hasn’t been coupled with the data. For instance, later on I hope to merge in support for XInclude and XQuery Update, and in those cases the URI is again simply passed to for instance fn:put().

One can weight quite well on URIs and the abstraction the XPath Data Model provides, it seems.

Bradley T. Hughes
Qt
Labs
Aggregated
 in Qt, Labs, Aggregated
 on Thursday, November 22, 2007 @ 13:54

A couple of years ago (3, to be exact), my girlfriend and I bought a house about 45 minutes outside of Oslo. The little village is just far enough and small enough to not get cable TV. So, that means we have to have satellite. I consider myself a lucky geek, because my tuner runs Linux.
Read the rest of this entry »

englich
Qt
Aggregated
Patternist
Posted by englich
 in Qt, Aggregated, Patternist
 on Thursday, November 15, 2007 @ 10:52

People have asked for Qt’s XQuery & XPath support to not be locked to a particular tree backend such as QDom, but to be able to work on arbitrary backends.

Any decent implementation(such as XQilla or Saxon) provide that nowadays in someway or another, but I’d say Patternist’s approach is novice, with its own share of advantages. So let me introduce what Qt’s snapshot carries.

<ul>
    {
        for $file in $exampleDirectory//file[@suffix = "cpp"]
        order by xs:integer($file/@size)
        return <li>
                    {string($file/@fileName)}, size: {string($file/@size)}
                  </li>
    }
</ul>

and the query itself was set up with:

QXmlQuery query;FileTree fileTree(query.namePool());
query.setQuery(&file, QUrl::fromLocalFile(file.fileName()));
query.bindVariable("exampleDirectory", fileTree.nodeFor(QLibraryInfo::location(QLibraryInfo::ExamplesPath)));
if(!query.isValid())
     return InvalidQuery;
QFile out;
out.open(stdout, QIODevice::WriteOnly);
query.serialize(&out);

These two snippets are taken from the example found in examples/xmlpatterns/filetree/, which with about 250 lines of code, has virtualized the file system into an XML document.

In other words, with the tree backend FileTree that the example has, it’s possible to query the file system, without converting it to a textual XML document or anything like that.

And that’s what the query does: it finds all the .cpp files found on any level in Qt’s example directory, and generate a HTML list, ordered by their file size. Maybe generating a view for image files in a folder would have been a tad more useful.

The usual approach to this is an abstract interface/class for dealing with nodes, which brings disadvantages such as heap allocations and that one need to allocate such structures and hence the possibility to affect the implementation of what one is going to query.

But along time ago Patternist was rewritten to use Qt’s items & models pattern, which means any existing structure can be queried, without touching it. That’s what the FileTree class does, it subclasses QSimpleXmlNodeModel and handles out QXmlNodeModelIndex instances, which are light, stack allocate values.

This combined with that the engine tries to evaluate in a streamed and lazy manner to the degree that it thinks it can, means fairly efficient solutions should be doable.

So what does this mean? It means that if you would like to, you can relatively cheaply be able to use the XQuery language on top of your custom data structure, as long as it is somewhat hierarchical.

For instance, a backend could bridge the QObject tree, such that the XQuery language could be used to find Human Interface Guideline-violations within widgets; molecular patterns in a chemistry application can concisely be identified with a two or three liner XPath expression, and the documentation carries on with a couple of other examples. No need to convert QWidgets to nodes, or force a compact representation to sub-class an abstract interface.

A to me intriguing case would be a web robot that models the links between different pages as a graph, and finds invalid documents & broken links using the doc-available() function, or reported URIs that a website shouldn’t be linking to(such as a public site referencing intranet pages).

Our API freeze is approaching. If something is needed but missing, let me know.

englich
Qt
Aggregated
Patternist
Posted by englich
 in Qt, Aggregated, Patternist
 on Tuesday, October 23, 2007 @ 09:26

Attention to details is ok, but compiler messages has historically not received it. Here’s an example of GCC’s output:

qt/src/xml/query/expr/qcastingplatform.cpp: In member function 'bool CastingPlatform::prepareCasting():
qt/src/xml/query/expr/qcastas.cpp:117: instantiated from here
qt/src/xml/query/expr/qcastingplatform.cpp:85: error: no matching function for call to ‘locateCaster(int)’
qt/src/xml/query/expr/qcastingplatform.cpp:93: note: candidates are: locateCaster(const bool&)

Typically compiler messages have been subject to crude printf approaches and dignity has been left out: localization, translation, consistency in quoting style (for instance), adapting language to users (e.g, to not phrase things preferred by compiler engineers), good English, and just generally looking sensible.

To solve that it requires quite some work, and that’s probably the explanation to why it often is left out. To have line numbers, error codes, names of functions, and whatever available and flowing through the system requires quite some plumbing and room in the design.

Another thing is that nowadays we really should expect that compiler messages within IDEs or other graphical applications should be sanely typeset. If not, we’ve lost ourselves in all this UNIX stuff. Keywords and important phrases should be italic, emphasized, colorized depending on the GUI style.

For shuffling compiler messages around it is customary to pass a set of properties: a URI, line number, column number, a descriptive string, and possibly an error code. Apart from that it falls short reaching the goals outlined in this text, it encounters a problem which I think is illustrated in the above example with GCC. What does one do if the message involves several locations?

Even if a message involves several locations, it is still one message and should be treated so, and presented as so. The approach of using a struct with properties falls short here, and chops the message into as many parts as it has locations.

For Patternist I wanted to make an attempt at improving messages. So far it is an improvement at least. For instance, for this message that the command line tool patternist outputs:

cli.png

the installed QAbstractMessageHandler was passed a QSourceLocation and a message which read:

<p>Operator <span class='XQuery-keyword'>+</span> is not available between atomic values of type <span class='XQuery-type'>xs:integer</span> and <span class='XQuery-type'>xs:string</span>.</p>

It was subsequently converted to local encoding and formatted with ECMA-48 color codes. (The format is not spec’d yet, it will probably be XHTML with specified class ids.)

While using markup for the message is a big improvement, it opens the door for formatting and all, this API still has the problem of dealing with multiple locations.

What is the solution to that?

Striking the balance between programmatic interpretation(such that for instance source document navigation is doable) and that the message reads naturally as one coherent unit is to… maybe duplicate the information, but each time tailored for a particular consumer?

<p xmlns:l="http://example.com/">In my <l:location href="myDocument.xml" line="57" column="3">myQuery.xq at line 57, column 3</l:location>, function <span class="XQuery-keyword">fn:doc()</span> failed with code <span class="XQuery-keyword">XPTY0004</span>: the file <l:location href="myDocument.xml" line="93" column="9">myDocument.xml failed to parse at line 93, column 9</l:location>: unexpected token <span class="XQuery-keyword">&</span>.</p>

This is complicated by that language strings cannot be concatenated together since that prevents translation. But I think the above paragraph is possible to implement. As above, the message reads coherently, but still allows programmatic extraction. A language string and formatted data sits in opposite corners of extremity, and maybe markup is the balance between them.

Would this give good compiler messages and allow slick IDE integration? If not, what would?

englich
Qt
Aggregated
Patternist
Posted by englich
 in Qt, Aggregated, Patternist
 on Tuesday, September 18, 2007 @ 10:03

The Qt snapshots now includes support for XPath 2.0 and XQuery 1.0.

Being part of the XML library, the idea is that Qt 4.4 will ship with a C++ API for running and evaluating such queries. On the side too, is a command line tool called patternist, for quickly testing queries, scripting and old-school web solutions. But who cares, blogs with screenshots is the thing:

cli.png

Stronger XML support in Qt has been consistently asked for by users over a long time, with XPath being one of the main requests. Hopefully Patternist, with the help of KDE folks, users, and customers expressing what’s missing, will please those needs. Considering the similarities of XQuery and XSL-T, Patternist also serves as a foundation for implementing XSL-T, if so decided.

For KDE folks all this might ring a bell. Patternist was indeed first developed for a long time in the KDE repository, as part of KDOM. We just thought it would make a lot more use as part of Qt.

And I think exactly that makes this exciting. W3C’s XQuery working group has registered an astonishing number of exciting implementations. But for users, reliability is what matter in the end. Whether bugs will be fixed, whether people can answer questions, whether the piece is maintained and documented. Persistency. Trolltech swiftly carries this on its shoulders(assuming I brush my teeth and all that).

Combined with that Qt is open source and the Patternist SDK used for development is as well, this is like eating some nasty chocolate while at the same time singing a little duet with Miss Piggy. I can’t sing, nor can Piggy (although she tries), but you get my point.

Humble modesty aside, it is worth to mention that this still needs work. About 94% of the test suite is passed, the API needs more work, and there is performance issues.

Nailing test cases and trimming code paths are problems that have known solutions (though typically horrible to carry out). Harder is to know what people need and how they need it. It’s hard to guess what kind of APIs or extensions Amarok or KOffice or a GNOME or web application need.

If you got input, feel free to add a comment to the blog, send a report to Trolltech, grab me(FransE) on the Open Projects IRC network, or ask a question or two on the qt-interest mailing list.

The documentation starts over here.



© 2008 Nokia Corporation and/or its subsidiaries. Nokia, Qt and their respective logos are trademarks of Nokia Corporation in Finland and/or other countries worldwide.
All other trademarks are property of their respective owners.