Friday, September 24, 2004

JXUnit Tests
I expected that converting the tests for the new pseudo-model into a set of scripted JXUnit tests would be trivial, but this was not the case.

It didn't take too long to create the XML for the tests. The XML results took a little longer, but a set of vi macros applied to the results from the iTQL GUI helped here. However, when the tests were run, the expected results were not obtained.

The first test looked for all statements with subjects of type URIReference. This worked fine. The second test looked for all statements with objects of type rdfs:Literal, but here is where the strangeness started.

The query looks like this:

select $s $p $o

from lt;rmi://servername/server1#camera>
where $s $p $o
and $o <rdf:type> <rdfs:Literal>
in <rmi://servername/server1#type>
order by $s $p $o;
When executed against the camera ontology, the results look like:
  node60 <http://www.w3.org/2000/01/rdf-schema#comment> "

Camera OWL Ontology

Author: Roger L. Costello
Acknowlegements: Many thanks to the following people for
their invaluable input:
Richard McCullough, Yuzhong Qu,
Leo Sauermann, Brian McBride and
Jim Farrugia.
"
_node159 <http://www.w3.org/2002/07/owl#cardinality> 0
However, when run inside the JXUnit framework the results were merely:
  _node159 <http://www.w3.org/2002/07/owl#cardinality> 0
After working on this for some time I started asking if anyone else might have ideas. DM pointed out that he had left a bug in the string pool which could cause a single element list (of literals, for instance) to show up as an empty list. This didn't appear to be the problem, and a bug fix for the problem demonstrated that it wasn't.

Since the original code for the pseudo-models was from SR, I started to question him on a few possibilities. The first thing he suggested was to do a query from just the pseudo-model like this:
select $l

from lt;rmi://servername/server1#camera>
where $l <rdf:type> <rdfs:Literal>
in <rmi://servername/server1#type>
In iTQL it returned:
"

Camera OWL Ontology

Author: Roger L. Costello
Acknowlegements: Many thanks to the following people for
their invaluable input:
Richard McCullough, Yuzhong Qu,
Leo Sauermann, Brian McBride and
Jim Farrugia.
"
0
[true]
[EMPTY_GROUP]
These values were expected, with the first two coming from the camera ontology, and the second two coming from the system model. However, when I put the same query into the JXUnit tests the output file reported an OutOfMemoryException. Of course, exceptions of this nature don't come with a stack trace, so I had no real indication of the specific cause of the problem. The JXUnit code does not set up any logging either, so I'm unable to get any debug statements from the system.

I thought that perhaps the string pool was returning too much data for "node type" code to deal with. There should not be a size problem here, but if there were, then having a lot of literals in the string pool could be enough to trigger it. Based on this idea, I went and tracked down every model created in the JXUnit tests, and put in TQL to drop all of them. Unfortunately, this had no effect.

While looking at the specifics of the implementing code, SR pointed out that it could use a shortcut if the variable were already bound. Rather than retrieving all nodes of a requested type, the value bound to the variable could be looked up directly in the string pool. If the value is present, then the "unconstrained" tuples can be returned, else the "empty" tuples would be returned. This is much faster, and would not use any memory for operations when the other constraints return fewer results than the "type" constraint would return.

I went and implemented this suggestion, and demonstrated that it worked by testing against an interactive iTQL. This was an easy test, as all the variables could be removed from the TQL:
select 'dummy'

from lt;rmi://servername/server1#camera>
where '7'^^<http://www.w3.org/2001/XMLSchema#double> <rdf:type> <rdfs:Literal>
in <rmi://servername/server1#type>;
So with this working, any significant number of literals in the string pool would be avoided if a limited set of nodes were returned from another constraint.

With these adjustments in place I tried running the JXUnit tests again. Once more, the required query returns only the second line, and the query for all literals still throws an OutOfMemoryException (the latter was not surprising, as the old code path should still have been executed).

Since the queries all work fine from an interactive iTQL session, and with no logging available when running the JXUnit tests, I'm in a quandary for my next move. SR has suggested running a memory profiler during the tests to track down the OOM. This is the best suggestion I've had so far, so I'll be trying that on Monday morning.

No comments: