01 Sep, 2010, ProjectMoon wrote in the 1st comment:
Votes: 0
So, I have a bunch of game objects. I need to keep track of them. UUIDs (java UUID object, to be specific) identifies the actual object. Being that RingMUD is entirely XML-based and document-oriented, the way to find objects is via XPath. The hard XML is stored in an XML database, and the game objects are stored in memory (loaded with JAXB, if anyone cares).

To expose an API for finding game objects, I have a "database index document" that copies the XML of all currently loaded game objects along with a UUID -> Object map that stores the actual game object pointers. An XPath query is sent to the database, and a list of UUIDs returned. These are then sent to the Map, which finally returns the objects in a List.

This works, and is the basis of the (currently non-existent) event handling system in RingMUD. However, is it efficient? I do not think it is. So, I am looking for ways to improve it. My initial ideas are:
1. Trim the XML going into the Index Document. Right now it copies EVERYTHING, when all it needs is a skeletal structure.
2. Remove the Index Document entirely and actually just require document as part of the XPath parameter.

I think I'll be going with #2, but I want to see if anyone else has any ideas.
01 Sep, 2010, David Haley wrote in the 2nd comment:
Votes: 0
If the document map is implemented in a remotely sane fashion, it will be rather efficient. Of course, you want to give the retrieval API as much information as you can so that it can use its internal indexing etc.; you don't want to query some big list just to run additional queries on the results.

Of course, if you often have the case where you already have the document object, then allow that case in your API and in that case skip the initial lookup.
03 Sep, 2010, ProjectMoon wrote in the 3rd comment:
Votes: 0
David Haley said:
If the document map is implemented in a remotely sane fashion, it will be rather efficient. Of course, you want to give the retrieval API as much information as you can so that it can use its internal indexing etc.; you don't want to query some big list just to run additional queries on the results.

Of course, if you often have the case where you already have the document object, then allow that case in your API and in that case skip the initial lookup.


Well, the only thing the Map contains is a UUID->Object relation. The only reason the XPath is forwarded to the XML database is for efficiency reasons. I figured the people who wrote the XML database have written a far more efficient XPath parser than I will ever be able to cook up. It also seemed smarter than storing all of the XML in memory.
03 Sep, 2010, David Haley wrote in the 4th comment:
Votes: 0
Well, yes, it is likely that their XPath parser is more efficient, so you should be sending stuff to them when possible. I might have misunderstood your initial post because that wasn't clear to me at first. There are cases where you can build a special-purpose, optimized index that will beat their general-purpose indices, so it's hard to say for sure without having the full picture.
06 Sep, 2010, ProjectMoon wrote in the 5th comment:
Votes: 0
David Haley said:
Well, yes, it is likely that their XPath parser is more efficient, so you should be sending stuff to them when possible. I might have misunderstood your initial post because that wasn't clear to me at first. There are cases where you can build a special-purpose, optimized index that will beat their general-purpose indices, so it's hard to say for sure without having the full picture.


Well the end goal of this is to enable a jQuery-esque event-handling API. An XPath expression returns you a set of game objects, which all then have an event handler applied to them. My main issue, though, is "live" events. Certain things can only be achieved if an event handler is applied to every object matching a certain selector as it is loaded. jQuery can accomplish this because of the unique way DOM elements are handled. I do not have that same luxury here. I guess I just maintain a list of live events and check selectors as they come in?

The problem with this is that I'd have to wait for them to be added to the database index document, and then hit the index document. That's a lot of DB hits every time an object is loaded. If you have 50 live event handlers, you'd have 50 database hits (or a really big XQuery statement) every time you want to load an object. That's what I'm trying to figure out how to get around.

Perhaps just pass the XML of the unmarshalled object and do it all in memory?
06 Sep, 2010, David Haley wrote in the 6th comment:
Votes: 0
I guess I don't really have enough context or knowledge of the full picture here to comment intelligently on the problem. It does seem wrong that you'd need to hit the DB so many times when you create an object. What exactly is a "live event"? If you have a list of them, why can't you manually pass the newly created object rather than put it in the DB and have the events go searching through the DB? Again I don't really know what all you've set up here, so I'm not sure there's much I can say here that will be terribly useful.
06 Sep, 2010, ProjectMoon wrote in the 7th comment:
Votes: 0
David Haley said:
I guess I don't really have enough context or knowledge of the full picture here to comment intelligently on the problem. It does seem wrong that you'd need to hit the DB so many times when you create an object. What exactly is a "live event"? If you have a list of them, why can't you manually pass the newly created object rather than put it in the DB and have the events go searching through the DB? Again I don't really know what all you've set up here, so I'm not sure there's much I can say here that will be terribly useful.


Maybe I can explain it better in this post. It would help if you have used jQuery's event handling API. With jQuery, you pass a DOM selector string to the $() function. It returns a set of DOM elements matching whatever you passed. You can then call event-handling functions such as click() or change(). These functions take an event handling callback as a parameter, and then bind your event. So,
$('div').click(function() { 
alert('click');
});

binds an onclick event to all <div>s on the page that will cause them to pop up the alert when clicked.

There is also the concept of "live" events. Normally, events bind only to the elements currently on the page. Any elements added later dynamically (via AJAX, whatever) do not receive an event handler. By making a live event, all current and future elements matching the selector will receive event handlers.

The event-handling API for RingMUD is similar (but still very different!) to the jQuery API. Instead of DOM selectors, it uses XPath. Instead of returning DOM elements, it returns game objects. I don't know if I'll use the same API style with anonymous callback functions, particularly since Python lambdas are only one line long usually. But that's all beside the point.

Just like a web browser, it is not guaranteed that all game objects will loaded at server start. Currently, the event-handling API can only work with objects that have been loaded beforehand. So, I need a way of efficiently applying events to objects that are newly loaded. If at all possible, I would like them to match XPath selectors set up by user code previous to the loading event. The only other alternative I can think of is exposing a special "onLoad" event that all objects get, and then allow the end developers to bind to that event when creating code to load a game object. I think that's the *easy* way, but it's not the most powerful or flexible.

Here is a very pseudocodish example for what my ideal "live" event API would be:
#Load some handlers for all current goblins
goblins = select("//mobile/baseModel[name='Goblin']")
goblins.onMove = goblinMoves
goblins.beforeDeath = goblinScreamOfAgony

# Load an event handler for all future goblins to equip them.
futureGoblins = futureSelect("//mobile/baseModel[name='Goblin']")
futureGoblins.onLoad = equipGoblin
08 Oct, 2010, ProjectMoon wrote in the 8th comment:
Votes: 0
After thinking about this, I will probably have to take an approach similar to the way DOM event bubbling works. jQuery live events work by exploiting browser DOM bubbling and then matching against selectors.

For the MUD, I can store a list of "future selectors". Whenever a result from the database is returned, it gets unmarshalled from XML into a Java object. Before I do the unmarshalling, I can run XPath against the returned XML and check for live event matches. The only problem is that will return XML fragments, so now I need a way to hook those fragments to the actual game objects. The easiest way off the top of my head would be to unmarshal the XML fragment, and then check for object equality during the unmarshal events of the real XML. But that seems grossly inefficient when there's large objects or lots of live events.

Is there a better way to handle this?
0.0/8