Skip to content
Daniel Cheng edited this page Mar 17, 2015 · 1 revision

Introduction

Attributes are currently stored on a per-object linked list. There are advantages and disadvantages to this. Raevnos is working on a rewrite that keeps the advantages and eliminates some of the disadvantages, hopefully without introducing too many new ones.

Details

History

Once upon a time, the linked lists used for holding attributes were very very simple. Adding a new attribute involved pushing a new node onto the head of the list for that object. The order of the attributes as they showed up in example and lattr() and the like changed each time the game was @shutdown and restarted. Iterating through all the attributes on an object was very simple; just walking the list. Looking up specific attributes involved O(N) time; every attribute had to be checked before you could tell that it wasn't on an object.

Then Raevnos changed things so that the list was sorted. This looks nicer on examine, and improves the performance slightly when looking up a nonexistent attribute. If you're looking for an attribute named DOG, you can stop looking when you find you're at EMU. Code was slightly more complicated by this.

Then Talek added attribute trees. Attributes are still stored in a sorted linked list, but displayed differently. Code was vastly more complicated by this, and some things like @mvattr and @cpattr that seem like they should work on an entire tree at once don't.

Clearly, something must be done. We want fast iteration through all attributes, as well as faster lookup of individual attributes, especially on objects with lots of them.

How should it be done?

The Competition

Other mushish code bases tend to store attributes in a disk-based hashtable. This results in fast lookups, but slower iteration. The lookups might not also be fast -- memory is so much faster than disks that if looking up an attribute involves a disk seek and read, it can be much slower than walking a list (Penn has this problem too to a lesser extent, since attribute contents can be on disk.) Anyways, that's not an approach we're really interested in taking.

Some Considerations

Once upon a time, I scraped a bunch of typical databases for some statistics. One of the more notable things I found was that most objects have 5 or fewer attributes: A description for rooms, a description and messages for exits. It's code and data objects that have tons. Think Kieran's BB system.

If our solution involves a lot of extra memory per object, we actually loose. Looking at every attribute on an object with 3 of them isn't worth optimizing. To me, this rules out trees.

The Solution

Here's what I've settled on: For objects with only a few attributes, just keep the current sorted linked lists. When the object acquires more than X attributes, where X is semi-arbitrarily set as 6, the list turned into a skip list. This can be done seamlessly, without having to touch the current attributes, or even adding extra fields to the attribute struct. The bookkeeping needed can be stored in the bitfield used for attribute flags, at a cost of having fewer than 32 flags. This shouldn't be a problem.

I haven't quite settled on a way to represent attribute trees. I'm leaning towards something tree-like instead of the current inline representation.