[MUD-Dev] ColdStore. Belated response from a developer.

colin at field.medicine.adelaide.edu.au colin at field.medicine.adelaide.edu.au
Sat Apr 22 10:19:59 CEST 2000


I write this in response to a thread from December 1999, of which I've just 
become aware.  In the thread, Miro <silovic#zesoi,fer.hr> attempts some 
helpful criticism of ColdStore, which I seek to rebut here.

Miro writes, of ColdStore,

> It's a C++ library that mmaps a file, and then handles the allocation and refcounting. This is very fast, of course, as the allocation handles the locality, but that's the only good thing one can say this approach. Problems:

>- mmap is limited by the architecture. With normal databases you can download 
as needed, and the db file(s) can be bigger than the address space - if you 
carefully split your db, for example. With mmap, you're limited to the largest 
contiguous segment in your address space, which really is about 1 gb on most 
OSes.

That's true.  64bit machines are around the corner: when the machine's address 
space exceeds your available disk storage this limitation disappears.

>This seems a lot but I know of at least one production MUD whose db size hit 
1gb at one point (that's when they rewrote much of their code for data size 
efficiency) - and that was Cold db that compresses small integers, so it'd be 
1.5-2gb of pure mmapped binary.

ColdStore compresses small integers too.

I'd have thought the storage between Cold and ColdStore was comparable.

>- bug recovery is nonexistent. If your broken C++ code hits mmaped memory, 
you can say goodbye to the entire db.

ColdStore doesn't set out to make C++ programming safe, because that's 
impossible.  It sets out to provide a toolkit for supporting higher-level 
interpreted languages in which one would write applications.

It's certainly necessary to thoroughly engineer the C++ classes you use and to 
avoid world-stopping bugs, however Miro's argument could apply to any complex 
piece of code upon which your world depends, the o/s, the db backend.

You could look at ColdStore as a C++-extensible database engine which has been 
optimised for the kinds of storage one would require for MUDs.  Certainly, if 
the database is buggy your MUD will be toast.  Recommend: don't extend the db 
with buggy code.

>- versioning issues. While upgrading ColdStore may be handled, If you change 
layout of your objects, well... conversion is impossible, since you've just 
mmaped the binary.

ColdStore defines a virtual protocol based roughly on Python's API.  One of 
the extensions is a toconstructor() call, which is intended to be used to 
serialise objects for the purpose of reconstruction.

>Note that mmapped is okay if you make it possible to serialize the object in 
some intelligent way and then copy them into the mmapped memory.

One could certainly use the toconstructor() facility for changing the raw 
layout of objects.

This would be painful, however, and one would be well advised to think through 
the raw layout of lowest level objects before committing them to persistent 
store.

>- db format is highly non-portable. It's not just architecture dependant, 
it's C++ compiler dependant (as object layout may change).

Certainly.  It was a design decision to localise the cost of moving between 
architectures to the time when one might wish to actually move them, rather 
than seek to support an abstracted/portable format for which one pays on each 
access.

Many database formats are not immediately/binary portable, usually the 
databases have to be serialised or marshalled before moving them.

>- refcounting. Well. Some people swear by it. Usually the same people who 
haven't explored its interactions with threading.

I was in the process of writing it right out in favour of GC, when someone 
pointed out to me that refcounting is a great storage optimiser - ColdStore 
collections and vector types share all substructure, and implement Copy On 
Write semantics on low level objects.

> The issue is that increasing refcount needs to be done atomically - when you have LOTS of threads, well... that just won't work.

Of course it will work.  It just entails some possible contention.  Most 
modern (like, post Z80 :) CPUs provide for atomic increment/decrement of 
integers because, as Miro says, there's a lot of contention for counters.

>You either have to use extra spin lock or use inline assembly for atomic 
increment. And since you increment/decrement refcounts a LOT (even passing 
pointers as parameters may cause refcounts to bump), this is major issue.

I don't see the problem with using inline assembly for atomic increments, 
that's what inline assembly is for.  It's what we use, nicely wrapped in a 
Counter class.

Maximising data locality by sharing substructure will always tend to increase 
contention between threads at the same time as it tends to decrease page 
faults.  This is a classic trade-off: throughput vs. responsiveness.  Are 
networks really fast enough, yet, that response-lag is an issue?

As long as the time taken to swap a page from disk is much longer than a 
thread context switch, I'll tend to worry more about locality than thread 
performance, most particularly since most of large MUD architectures don't 
even have real multitasking.

>BTW, has there been any discussion on the list on incremental/generational 
GC? (that works best for MUDs by far, IMHO - you can really bump up your 
realtime response once you implement incrementality properly).

As mentioned, while concurrent GC is a really interesting field, refcounting 
is not merely a garbage collection facility.

>- no way to logically split your db into multiple files. ColdStore stores 
direct binary pointers.

Later versions may provide for a tiling of mmaps over the address space.

> You also have Texas Persistent Store [...] ColdStore authors chose not to implement this because, according to them, it performs really slowly.

Yes, according to reported benchmarks it performs 10,000 times slower than the 
equivalent direct pointer access methods.

Additionally, the authors of Texas don't answer email, the build process 
entails heavy use of a hacked gdb (using STABS to generate object 
interpretation code for swizzling) and Texas has no support for dynamically 
loading new objects into a store.

>I'd say [ColdStore] is great for small MUDs that need to run on tiny (read: 
outdated) servers and aren't changed a lot after the initial hardcode is in 
place.

I'd never seek to write any MUD but a trivial MUD directly on ColdStore layer1 
object protocol, but then that's not what ColdStore was designed for.

I think layer1 is a fairly good base for implementing virtual machines, at 
what we've called layer2, and would welcome criticism of ColdStore with this 
intended use in mind.

We're currently developing languages and their associated virtual machines at 
layer2, I think it would make sense to use the languages being built on layer2 
to implement a MUD-like system.

>It's faster than anything that uses separate db engine and it handles small 
dbs efficiently. But I think it'd be a mistake to use it for a (potentially) 
large size world.

I don't consider 1.75Gb to be small, on a 32bit machine.  And given our 
current rate of progress, 64bit systems will be prevalent by the time we 
deliver our first Dispute Resolution System object :)

Colin.





_______________________________________________
MUD-Dev mailing list
MUD-Dev at kanga.nu
http://www.kanga.nu/lists/listinfo/mud-dev



More information about the mud-dev-archive mailing list