Quick-and-dirty DIY 19″ rack

Why buy an expensive 19″ rack when you can build it yourself for 8 Euro and a bit of work?

There is no magic here. The ingredients are really simple actually: A few pieces of wood, screws and glue.
The construction is rigid. No angles are required due to self-stability of the quadratic frames. Just make sure the inner length of each edge is exactly 19″ (48.26 cm). Glue and screw the pieces together and that’s it.

Nightly Builds of Quasar Media Player available

Quasar Media Player

It’s been some time since the last update. In my previous post I mentioned I was in the process of setting up a nightly build system. This system has been running silently since May.
I guess it is finally time for me to officially announce the nightly builds of Quasar Media Player:

http://www.katastrophos.net/downloads/quasar/nightly/

Along with the most current sourcecode tarball, binaries are available for 4 platforms:
Windows (win32), OS X (universal binary), Sharp Qtopia and pdaXrom Linux (both for Zaurus PDA)
The Windows version comes in two styles: a generic setup (EXE) and a self-contained portable version (7z archive)

Enjoy and please leave a comment.

Upgrading the Fujitsu U810 with 64GB SSD

I recently decided to upgrade my Fujitsu U810 with a solid state drive.
Unfortunately, since the U810 only offers a PATA interface the options are quite limited to just a few high-priced (compared to SATA) 1.8″ SSD models by either Samsung, Sandisk (SanDisk SSD UATA 5000, discontinued) or MTRON (MSD-PATA3018-032-ZIF2 et al.).
I went for a 64 GB SLC drive manufactured by Samsung. The exact model name is MCCOE64GEMPP. The same 1.8″ PATA-drive is available as bulk version without the metal enclosure that is protecting the PCB: MCCOE64GQMPQ

Here are some photos of the drive itself and how to install it in the U810. Note, the drive is 5 mm high and will fit into the U810 without any modifications.
Also keep in mind that the U1010 has a different connector (50-pin IDE instead of ZIF), so these ZIF-drives will not work here. However, there are reports on UMPC Portal that suggest that it is possible to get a replacement connector flat band cable for the U810 that is the 50pin IDE cable, so I guess it is also possible the other way around for the U1010.


dsc00321dsc00323
dsc00238dsc00324

Here are the obligatory benchmarks comparing the new SSD against the old Toshiba MK1011GAH 100 GB hard drive that was previously installed in the U810:


Toshiba MK1011GAH:

hdtune_info_toshiba_mk1011gahhdtune_benchmark_toshiba_mk1011gah
crystal50crystal100crystal500


Samsung MCCOE64GEMPP:

hdtune_info_samsung_pza064_ssdhdtune_benchmark_samsung_pza064_ssd
crystal50_samsung_pza064_ssdcrystal100_samsung_pza064_ssdcrystal500_samsung_pza064_ssd

Needless to say that applications cold-launch a lot faster with the SSD. (Firefox with 12 add-ons: ~10 s before -> ~6 s after, Chrome: ~3 s before, ~1 s after, Thunderbird: ~8 s before -> ~3 s after).

Startup time was reduced quite a bit but not dramatically. However, returning from sleep and hibernate saw a huge improvement. Unfortunately I can not provide values of the old drive, so no comparison.
I did not notice longer battery run times. However, the whole system runs a lot cooler because the SSD naturally does not produce heat as extensive as the HDD did.

I am satisfied with this upgrade – especially since it has boosted compile-times when working with CodeGear RAD Studio and Delphi – due to the great performance when accessing, reading and writing small files. Your mileage may vary.

Q…/Free: Bug in QProcess writeToStdin

All right, this post is just to stop somebody else’s suffering in figuring out why writing to stdin in QProcess on Version 3.3.x-8 of Q…/Free doesn’t work on Windows. Well, actually it works but just for the first line you write to stdin. There is a bug in qprocess.cpp at line 730:

void QProcess::writeToStdin( const QString& buf )
{
    QByteArray tmp = buf.local8Bit();
    tmp.resize( tmp.size() - 1 ); // drop the implicit \0
    writeToStdin( tmp );
}

should be:

void QProcess::writeToStdin( const QString& buf )
{
    QByteArray tmp = buf.local8Bit();
    tmp.resize( buf.length() );
    writeToStdin( tmp );
}

Verision 3.3.7-7 includes the latter method, same as the latest Qt 4.3 sources. So, it’s actually a regression in 3.3.x-8. If you require the latest Qt 3 / Q…/Free for your open source application and need to write to some other processes’ stdin, you can just use a wrapper workaround that uses the latter method and directly uses writeToStdin( const QByteArray& buf ) instead of the QString variant.

rdesktop: Connect to Windows 7 and Vista with ClearType font smoothing enabled

So Windows Vista finally allows to enable ClearType font smoothing for Remote Desktop / Terminal Services sessions. Update: Windows XP SP3 does too!
If you try to connect to a machine running Windows XP SP 3 or later using rdesktop, you won’t get smoothed font typing since at the time of this writing rdesktop does not officially offer an option to control this feature. However, here is a workaround:
Continue reading “rdesktop: Connect to Windows 7 and Vista with ClearType font smoothing enabled”

“Yet Another Zaurus Media Player”… not dead yet: “Quasar Media Player”

Alright, this blog has been very quiet for the last few months. That’s partially due to me being very busy with other stuff.
I’m slowly picking up pace and getting things done again.

So, here is a short update on the media player that I’m currently developing for my Zaurus. Well, actually it’s been in long-term testing mode for ages now… :)
I finally have a name for it. It will be called “Quasar Media Player” – or shorter “Quasar”. Below are some screenshots of the current development version running on Qtopia. I hope to have a release ready soon.

{Quasar} Shown is the new toolbar and play list selector.{Quasar} The new play info screen. Cover art is supported and rendered in this funky view. Any Satch fans out there? ;){Quasar} More eyecandy.{Quasar} Normal list view filtered.

“Yet Another Zaurus Media Player”… done differently . (Phase 2.1: Development progress 2)

Yet another short update on the development of my still untitled media player for the Zaurus. In the meantime it’s called YAZMP.

Again, I’ve been working on improving performance – this time on the performance when loading playlists.
Before I continue, let me give a brief overview of the structure:

Library -> Playlists < -> Media Cache

YAZMP doesn’t manage a library similar to i*Tunes. Instead it solely relies on playlists. Metadata (title, artist, album, etc.) is kept in the database and will be associated to once the playlist is loaded. The reason for this is pretty simple: Scanning audio files (and media files in general) each and every time a playlist is loaded will definitely take a lot of time. So, for every file the gathered metadata will be saved in the DB. Think of it as a cache.
Continue reading ““Yet Another Zaurus Media Player”… done differently . (Phase 2.1: Development progress 2)”

SQLite performance tuning and optimization on embedded systems

Based on the experience I gained while developing my Zaurus media player, here is a short compendium of optimization rules, tweaks and hints when using SQLite on an embedded system (may apply to other systems as well):

  • Simplify the database schema as much as possible – even if that means redundant data or illogical structure
  • Don’t generalize the database schema – generalization will mostly sacrifice performance and one can’t afford that on an embedded system with its tight restrictions, even if it is more convenient for the developer.
  • Only use relations (via IDs etc.) where absolutely necessary. The overhead for lookup and joining tables is considerable, even with an index on the relation.
  • Order the tables correctly in SELECTs. Put a table left-most if it is lacking an index on the relation. More details are here.
    In general: Check the order of tables in the SELECT statement. A different permutation may be more optimal. Profile.
  • Prepare your statements and bind values where applicable. This way you can get rid of the parser and VM creation overhead in tight loops (e.g. when inserting and updating).
  • Use transactions – even if you’re just reading the data. This may yield a few milliseconds.
  • Use temporary tables for intermediate results. They are fast and stay in cache most of the time. Depending on how your SQLite instance is set up, data will only be swapped into an external file if the cache is saturated.
  • Try to avoid using views for data you’re constantly accessing. If you can afford it, create temporary tables and insert data there. This will eliminate the overhead imposed by the view evaluation.
  • Avoid sub-queries since they tend to create temporary tables and insertion of the intermediate results into those tables may be expensive.
  • Try to use indices only on static data or data that changes rarely. Building an index on live or temporary data can be expensive performance-wise. Only do so if the time required for the data lookup considerably outweights the time required for building the index.
  • Alternative to indices: hashkeys – Instead of using indices on very long strings, you may store the hash values of those strings as keys in the same table. A lookup via hash values may be a whole lot more efficient. This method is also very effective when you can’t afford the creation of an index due to performance reasons. Downside: You have to take care of the hashkeys. (See remarks in the comments below.)
  • No useless indices. Create indices only if your queries actually use the indices on the table (check with EXPLAIN). Having useless indices around may pollute otherwise precious database cache space.
  • Be cache-friendly. Depending on the memory conditions, creating temporary tables and indices may bash the cache. Reloading data back into the cache is expensive.
  • Double-check your queries and profile them. The SQLite optimizer doesn’t perform as well as the optimizers of big DBs (Firebird / Interbase, PostgreSQL, Oracle etc.).
  • Check compiler settings. A higher optimization setting in your C-compiler may very well yield a few tens of milliseconds. Make sure to inline functions (-O3 for GCC 2.95.x, -O2 for GCC 3.x.x and higher). Optimize for architecture and CPU. Omit stack frame pointers (-fomit-frame-pointer) if you’re not producing executables with debug symbols. This may free an additional register for the compiler to use.
  • Disable unused SQLite features. This helps to reduce binary size and may also affect performance.

Here are some additional docs to consider:

http://www.sqlite.org/cvstrac/wiki?p=PerformanceTuning
http://www.sqlite.org/cvstrac/wiki?p=PerformanceTuningWindows
http://www.sqlite.org/cvstrac/wiki?p=PerformanceConsiderations
http://www.sqlite.org/optoverview.html
http://web.utk.edu/~jplyon/sqlite/SQLite_optimization_FAQ.html

“Yet Another Zaurus Media Player”… done differently . (Phase 2: Development progress, no release yet.)

So, like I’ve already mentioned in my previous comment, I’ve got some free time to work on my pet project here.

Development progress

I’ve been optimizing a lot under the hood. Tons of blood, sweat and tears have already run into optimizing the core parts.
Coming from a different background in programming, namely a desktop background, doing embedded development is a whole new experience for me. And let me say this: it’s definitely a refreshing one.
Development for embedded devices can be quite challenging if you have hard memory limitations and performance restrictions CPU-wise. These limitations go even further than the ones I’m used to when doing component or graphics development. And I’m doing quite a lot of that…

Just so you get the idea:
My essential requirement for this project is that the player is able to cope with thousands of files in a playlist.

With that being said, I’ve already rewritten the playlist management four times. :)
The first approach was fast but ate RAM for breakfast. Incremental searching on a playlist was fast but also required additional memory. The second approach was more memory-friendly, but searching was slow. Besides, some Qt widgets make development a real pain – at least in Qt/E 2.3.x. For instance, QListView can pose an incredible hog on performance. I’m currently using several hacks to speed things up. However, I’m still thinking about replacing the whole component or doing some custom coding to improve it…

Anyway, since I couldn’t really get rid of the memory problems, I finally decided to give SQLite a try. SQLite offers very sophisticated caching, which helps getting rid of the RAM problem. I really could use the enhanced features of a SQL database. And let me say this: SQLite is awesome. And it’s as fast as it could be on such a small device – that is, if you know how to use it…

With that being said, different rules in database design apply for embedded systems:
In the third approach I already created a pretty decent database schema. Something I naturally would have done on a desktop system. Keeping the layout clean, using relations where applicable, minimizing data storage requirements.
On a desktop system dereferencing and joining tables is fast. However, not so on my Zaurus: Simple left-joins over three tables would take up to a few hundred milliseconds. In contrast, these queries are almost unmeasurable on my desktop system, meaning they were faster than 10 ms.
Now add a few other equally expensive queries to that and imagine, you’re doing a search on your playlist with 2000 items. Do you want to wait 3 seconds or longer for the result? That’s not what I call interactive.
So, I had a nice profiling, optimizing and testing marathon last weekend. To make a long story short, after analyzing the bottlenecks and also having a lengthy discussion with a DB-guru friend, I ended up simplifying the database schema in a direction I wouldn’t normally take on a desktop system. It’s not totally ugly now, but it’s just not as relational as you might expect a SQL database to be. Also, some data is redundantly held in temporary tables, which isn’t nice either, but helps performance A LOT.
In order to do the profiling I made some changes to the SQLite codebase, which I will post shortly along with some optimization hints. Update: Hints here, patch here.

Screenshots

No release yet, sorry! I have to finalize some features first.
However, here are some new screenshots that show the new overview feature in action. The design of the application is temporary, stay tuned! :)

{YAZMPDD} YAZMPDD - Work In Progress Screenshot 4: Overview feature with multi-selection in action.{YAZMPDD} YAZMPDD - Work In Progress Screenshot 5: Search filter + Overview filter{YAZMPDD} YAZMPDD - Work In Progress Screenshot 6: Portrait window mode. Note: This is the contrast skin, which will change in the future.

Installing OS X 10.4 Tiger (PowerPC) from a Firewire harddrive

Last weekend I had the pleasure (!) to install Tiger on an ancient PowerMac that doesn’t feature any DVD-ROM drive. I don’t happen to have the special CD-version of 10.4 and trying to boot from an external DVD drive somehow failed. However, this Mac already had Firewire, so here is a little hint on how to install Tiger using a spare Firewire drive:

First off, you’ll need psync. I’ve tried Carbon Copy Cloner, but for some reason that didn’t work.
So, if you have Fink installed, do this:

$ fink install psync

Format the Firewire drive with HFS Extended. You don’t need Journaling, so please disable it.
Now, assuming you’re Tiger Install DVD is mounted at /Volumes/Mac OS X Install DVD and your formatted volume is mounted at /Volumes/OSX, type this into your Terminal to clone the content of the DVD over to the harddrive.

$ sudo psync -d "/Volumes/Mac OS X Install DVD/" /Volumes/OSX

Finally make the whole copy bootable by blessing it:

$ sudo bless --folder "/Volumes/OSX/System/Library/CoreServices" --bootinfo

Now, you may unmount and install. Fin .