Archive for the 'tech' Category

Solid-State Drives and You

Wednesday, January 28th, 2009

While solid-state drives (SSDs) seem to be all the rage in net-/laptops at the moment, most of their advantages (mostly negligible access times) also make sense for a desktop system, whereas their disadvantages (price / small size) are not as constricting as you can have multiple physical discs in a desktop system.
I’ve bought a 64GB SLC SSD drive in a 3.5″ SATA version for my Mac Pro and use it solely as an OS and applications drive, while my home-directory (where the bulk of my data obviously sits) is still on a normal, spacious hard-drive. The speed-up (in spite of Mac OS X’s already quite fast boot / application start-up times) is very noticeable.
The OS migration from the HDD to the SDD was very painless. I used Carbon Copy Cloner to copy everything but my username’s home directory, rebooted from the SSD, logged in as the user with administration privileges (which your everyday user account shouldn’t have) and changed the home-directory for my non-admin user (under System Preferences – Accounts – Right-Click on the account – Advanced Options – Home Directory).
Almost all applications (baring Xcode) cold-start approximately half-way through the first Dock-icon bounce and World of Warcraft flies with this setup. :)
If I didn’t need more than 64GB total space on my MacBook Pro, I’d also fit it with such an SSD drive without hesitation. But as it is, I need more space. Alas, when the next laptop is on the horizon I can definitely see myself shelling out for an SSD upgrade. Maybe mainboards should come with something like 64GB of on-board flash for use as operating system and application drive…

WowPlot 0.1.2

Wednesday, July 23rd, 2008

WowPlot has been updated to version 0.1.2, featuring the following improvements:

  • Added an option to automatically create new plots when splitting (by holding the Alt(⌥)-key).
  • Added new 2.4.3 combat log events (at least the ones I could find).
  • Removed PetFixers entries for Shaman’s summoned elementals (as 2.4.3 fixes this).
  • Added Fire Bomb spell to belong to Jan’Alai.
  • Updated Sparkle to 1.5b4.

WowPlot 0.1.1

Thursday, May 29th, 2008

WowPlot has been updated to version 0.1.1, featuring the following improvements:

  • loading / saving of plots
  • more speed (back-end is now multi-threaded using NSOperation)
  • Sparkle auto-updating
  • better parsing
  • some error-messages
  • more consistent splitting

Announcing WowPlot

Saturday, May 24th, 2008

WowPlot is a graphical analysis tool for World of Warcraft® combat logs (compatible only with the new combat log format introduced in version 2.4). Its main focus lies in evaluating time-dependant combat performance in a very free-form fashion, which is in contrast to the mainly statistical approach of other tools.
WowPlot Example Layout
WowPlot requires Mac OS X Leopard (10.5) and is a Universal application.

Wavelet 3.4.0

Tuesday, July 10th, 2007

A slightly bigger release, which brings two major changes. Not compatible with older files due to the the reorder-changes. The improvements to bit.c are not terribly well tested. More here, as usual. As an aside, Kompressor is now served in a ZIP-archive, instead of a DMG…

Changelog

  • Overhauled the reordering-code to make the table used independent of the aspect-ratio of the image. This makes old images incompatible with this version of the code. The smallest dimension (in wv_create_reorder_table) is now relevant for the largest table entry. Any image whose smallest dimension is smaller than the one used to create the table originally can safely use it.
  • Added a “min bits” criterion to the scheduler, that reserves a certain amount of bits for certain channels. Perceived image quality has improved a fair amount, the same default values are used in Kompressor and main.c.
  • We can now pass a write buffer into bit_open(), added bit_free() for deallocating automatically allocated regions. Only accepts lower-case mode-strings now.
  • Fixed (and simplified) scheduler preparations for very large absolute target errors.

It’s wavelet bugfix time — 3.3.4 is here!

Thursday, April 19th, 2007

While compressing a multi-channel file with a target bitrate and no specific target MSEs the resulting bit distribution between the channels seemed rather odd, and comparing the results to an older version revealed that it was indeed totally bogus!
So I changed the target MSE computation in main.c to be more inline with what happens in Kompressor.app, which revealed a another bug where tiny negative (i.e. relative) target MSEs passed to wv_query_scheduler() / wv_encode() were converted to 0 (instead of the smallest negative fixed point number representable) and thus interpreted as absolute target MSEs.
Both of these are fixed in 3.3.4 (and Kompressor.app has also been recompiled with the relevant fix).
Other than those two fixes (both of which only relate to target MSE evaluation when compressing), the code is identical to (and thus fully compatible with) version 3.3.3.

Darcs Repository

Wednesday, March 7th, 2007

Thanks to PHPDarcsView (which is very useful if you are on a hosted server where you are unable to run darcs itself) you can now browse the Wavelet-repository online; the official documentation and Kompressor.app are still here.

Interested in Leopard / Mac OS 10.5?

Thursday, January 25th, 2007

It might pay off to search the internet for NSOperationQueue

Cocoa Worker Thread

Friday, January 5th, 2007

For Kompressor.app, I’ve written a group of Foundation classes for implementing a worker-thread paradigm in Objective-C. The general idea is you have some non-trivial amount of processing you want done and then (optionally) be notified when it’s done.

This implementation has a number of advantages compared to others:

  • Threads are created once and reused, no expensive thread creation for each work unit.
  • Non-polling (using NSConditionLock).
  • Low communication overhead (e.g. no Distributed Objects).
  • Small (although the code is spread out over 3 classes / files).

How do you use it?

  1. Create an instance of SIWorkManager (usually there should only be one); by default it creates as many worker threads as CPU cores are available.
  2. For each unit of work, create an SIWorkUnit object (which contains the target object and selector where the actual computation is done, as well as an optional didEndSelector which is called on the main-thread of your application with either the result of calling [target selector] or the originally given argument). The target and argument are retained by the work unit.
  3. Tell the work manager object about the work unit (via addWorkUnit:).
  4. Done!

If you want to wait for a batch of N work units to be done, create an NSConditionLock L, and at the end of the work selector, you do [L lock]; [L unlockWithCondition:[L condition] + 1];. After dispatching all the work units in the main thread (or wherever), you wait with [L lockWhenCondition:N]; [L unlockWithCondition:0];.

An (untested as I am only on a Linux machine at the moment) example demonstrating both simple usage as well as waiting for a batch to be finished is in BatchExample.m.

Remember to only access shared data structures (or your user-interface) in the didEndSelector. SIWorkManager also has messages for removing work on or referring to a given object. Use nil to remove all pending work units.

Here is the source code with all required files. Feedback / fixes appreciated.

Kompressor.app and Wavelet Image Compression Library 3.3.3

Friday, December 29th, 2006

Shortly before the year is out (and as result of my vacation), there is some fresh software to be had… :)
I’ve now written an Mac OS 10.4 application called Kompressor.app to compress, inspect and display WKO images. This release goes hand in hand with version 3.3.3 of the wavelet image compression library itself.
Because this is the first (semi-)proper Mac-application I’ve written, I would welcome any form of testing or feedback people can provide, especially on the user-interface side. The application is universal and thus should work on PPC and Intel Macs.
Here’s a bit (all of it actually) of the supplied online help to get started… (more…)

Low-Level Libraries and High-Level Languages

Wednesday, October 18th, 2006

If you want to write a library that could relatively easily be used in embedded systems (say Xbox 360 / PS3) as well as being generally portable (Windows, Linux, Mac OS), then you end up in a bit of a bind. You can use C and be on the safe side, but for some types of programming C is rather cumbersome (see for example the Io language). You can use C++ (or one of its subsets), but now any client of the library has to understand the C++ ABI (which AFAIK only C++ does). Another option is to use whichever language is best suited to solving the problem you’re addressing in the library, but that usually imposes constraints on what can use or bridge to the library (e.g. if I were to write a library in Python, how do I use that from an application written in C++?).

Now, if whatever you’re coding is a low-level component, then this restriction becomes even more imposing because many higher-level pieces are now depending on and interacting with the library itself.
If you restrict yourself to running on Windows only (as that is the only platform where you can realistically rely on the CLR run-time being available) and don’t mind its overhead, then using .NET and the CLR will solve this problem for you nicely. For running on anything else, you’re pretty much screwed… :(

Rate-Distortion Graph

Friday, May 12th, 2006

I’ve invested a bit of time in getting some nice rate-distortion graphs out of my wavelet image compression library. Now that it’s embedded, the process is fairly easy: Compress once into a single file and then decompress only enough bits from the file until the desired rate is achieved. As such, the graph also shows the quality over the progress of the file.

Here is an example of one such graph, for a 708×1024 image of Mena Suvari (which unfortunately comes from a JPEG source and thus has block noise), as the Lena image (notice the name similarity? ;) ) is past its prime IMO, especially the color version has plenty of noise in the blue channel. The image was encoded in the YCoCg colour-space, which explains the slightly higher quality of the green channel and why even the highest rate is not lossless. Compared to the RGB version, the YCoCg representation incurs a mean-square error of ~0.25 (which results in the root mean-square error of 0.5 shown).

Rate / Distortion curve for a colour image of Mena Suvari

In theory, the rate/distortion graph should have a negative, but monotonically increasing derivative (which in normal language means something like “bigger improvements are closer to the beginning of the file”). We try achieve this by scheduling data units (which are essentially bitplanes of blocks) by how much they reduce the error in the coded image for each bit of their size. There are two reasons for this “close-but-not-quite-monotonically-increasing-slope”. One is that the error (distortion) is not computed exactly; instead I use an approximiation that based on the wavelet transform used. The other is the fact that we deal with packets / data units / blocks of finite size, and as soon as more than one channel is written to a single file, it becomes evident that a single packet will only improve a single channel - which in turn means the other channels have a stagnating improvement (zero derivative) for the size (or duration) of that packet.

These plots also make it easier to spot differences (usually either improvements or regressions) for changes in the code, so I’ve created graphs for all my test images, so that I can make these comparisons more easily in the future.

I’ve also taken an old pre-3.1 version (thank you, darcs!) that still used the recursive quantizer selection to produce similar plots (taking much longer as the image had to be compressed anew for each rate) and the result was pretty much a draw, in spite of the embedded version having to store a bit more sideband data (number of bitplanes for each block in the header, and which block is coded next in the bitstream itself). All of which makes the embedded version the “better choice”, due to its other advantages such as simpler code and “compress once, decompress at any rate”.