Thursday, August 31, 2006

Caching and O/R mapping

I was forwarded an article titled Why a cache in an O/R mapper doesn't make it fetch data faster and felt the need redirect the audience to some examples demonstrating the benefits of a well designed caching systems.

The author appears to be concerned you don't know if the data in the cache is dirty.  Although, fails to point at the reason for this uncertainty.  There are many reasons this could be the case, but why not provide an API or services for external applications, forcing them through you O/R framework (perhaps in an abstracted way), ensuring the cache is kept up to date.  I've read several articles (and my own tests with applications I've worked with) that demonstrate typical applications perform a greater percentage of reads than writes, further suggesting a cache is beneficial.

What’s a cache?

I’d like to refer to this definition, in particular “A cache stores recently-used information in a place where it can be accessed extremely fast.”. I disagree that the Identity Map (or uniqing) Frans refers to is necessarily the only cache used in O/R frameworks.

Caches and queries: more overhead than efficiency

Quoting from the author’s article,

So, when does this efficiency the myth talks about occur exactly?  Well, almost never.  In fact, using a cache is often less efficient.  I said almost, as there are situations where a cache can help, though these are minor or require a lot of consessions.

NHibernate (Hibernate ported to .NET) was developed with 2nd level caching at its core, allowing you to control the caching options per class, such as whether it writes-through or invalidates it's entry on a write to the database, which I think is important in demonstrating a cache’s benefits.  Additionally, NHibernate can cache query results as a list of IDs, furthering the benefit of its cache and increasing the hits.

The 2nd level cache is completely pluggable, so you have many options, including the ASP.NET cache. For even greater scalability, consider a distributed caching solution such as memcached or NCache. This is counter to the point ‘.NET’ doesn’t have support for cross process or server object awareness.True, it’s not built in to the framework, but solutions certainly exist.

I now want to direct you to this article, Hibernate: Truly Understanding the Second-Level and Query Caches, which goes in to all the detail you need to understand just how powerful a well designed O/R framework and caching subsystem can be.

In the author’s example, we could create a named NHibernate query, with appropriate parameters, represented in HQL as

IQuery query = session.CreateQuery("from Customer C inner join C.Orders O where C.Orders.size > 5 and O.ModifyDate > :date").SetDateTime("date", DateTime.Now.AddDays(-30));

For the cache to be effective and accurate, all changes to the database must notify the cache, so we know the entry in the cache is current, and therefore do not need to go to the database.

August CTP Sandcastle buildchm.bat update

Here is an updated buildchm.bat that works with the August CTP of Microsoft Sandcastle. The steps were derived from the Sandcastle blog. If you need to add additional assembly dependencies, edit the .BAT file, and locate the large comment. Cheers

Wednesday, August 30, 2006

sharp-64 - A Commodore 64 emulator in C#

What is it?

As of today, I've scoured the internet, and think it is fair to say sharp-64 (#64) is the first Commodore 64 emulator for the .NET platform. I could go as far to say it's the first 'emulator' for the CLR, given various searches on google turned up nothing on the subject of emulation related to .NET / C# / CLR. #64 is written entirely in C#, using SDL.NET as the sound and audio library. By using SDL.NET, I expect to build #64 as a cross platform executable.


I've always had an interest in emulation and software emulators for old 8-bit platforms, such as the Commodore 64 and Atari 800XL (both of which I had as a youngster). I hacked around both machines quite a bit as a kid, learning 6502 assembler and playing with their excellent graphics and sound capabilities (of their time).
I also was interested in seeing how well the CLR handled the demands of an emulator, and how much I could optimize the code to gain every ounce of performance out of it.


I cannot claim to have written the emulator from scratch - the credit goes to the excellent Frodo project. A very well designed and modular emulator written in C++. It is also a cycle exact emulator, meaning all the 'emulated' chips are in sync with each other, to the clock cycle. This allows emulation of practically every hardware hack on a real C64. Given the nature of cycle-exact emulators, they also require a greater demand of the platform it is executed upon, allowing me to further push the CLR.

Where is it at today?

It is a fully functioning C64 emulator, with sound and 1541 emulation via D64 virtual disks and mapping a directory. Sound and graphics use SDL.NET, with an extension to SDL.NET audio support for access to the streaming audio capabilities of SDL.
It has no user interface, besides the C64 itself, and therfore is not user friendly, nor is it recommended for a wide audience. Yet.
I have found a couple games do not work; however, they do fail with the official Frodo emulator, suggesting bugs in the original emulation code. I will try to troubleshoot this when I get some time.
#64 does have a few unsafe blocks, using pointers to access the emulated RAM, however I am planning to create some conditional defines and make these optional, to see how much overhead is incurred by the array bounds checks.

How does it perform?

When speed limiting is turned off, sharp-64 runs at greater than 400% of an original C64 on my 1.83GHz Core Duo Dell notebook.
I have tried various demos, such as those with FLI, FLD, DYCP, open borders, multiplexed sprites, timing dependent decoders, fast loaders etc, and they work great.
This is currently a straight port, so we may even be able to get closer to the C++ native version, which runs about twice the speed after some optimizations.

Can I play?

The full source is currently available via svn on, There is no documentation on getting it running, so it's up to you to hack around for now. The place to modify which d64 or directory is used for the 1541 disk drive is in prefs.cs.

Screen shots?

Basic CBM Basic

Decath Decathalon

BlueMax  Blue Max