Forum OpenACS Development: Re: Usage of XoTCL objects vs. database queries

Collapse
Posted by Malte Sussdorff on
Hi Stefan, I did not confuse the matter, maybe I just did not make the "Object" part big enough. What you explained is exactly what I realized after reading Gustaf's message.

I knew about the methods needing to reside in the interpreter-per-thread, what I was unsure about is if the XoTCL methods are loaded into the interpreter separately from the object, but thinking about the ability to mixin objects and overlay object methods, that might not be going to work.

As you pointed out, the serializing of an object works very nice for caching purposes. But this does not allow me to access the object in multiple threads except through the single point of entry (in my example "get_instance_from_db"). So yes, if I want to instantiate an object from the DB and prohibit me going to the DB all the time, ns_cache works like a charm as I can instantiate the object in the current thread through "get_instance_from_db" from the one stored in the ns_cache instead of the db. But it's not the same as using the same object copy in memory, as each thread has it's own copy of the ns_cache object and I can manipulate each of them independently.

So, it is a TCL issue with not having a place to store variables and methods in a global, thread independent place, yet access it in each thread with the option to overlay it in each thread. Would ttrace help here (http://wiki.tcl.tk/2770) ? Probably not, because it still requires me to make the object known to the thread and creating a resource copy in that thread.

Thanks again for you answers, I understand the issue now much better and stay happy that I have the persistent "cross threads" tool called database to use 😊.

Collapse
Posted by Stefan Sobernig on

Would ttrace help here (http://wiki.tcl.tk/2770) ? Probably not, because it still requires me to make the object known to the thread and creating a resource copy in that thread.

You already hinted it, ttrace addresses a different issue. ttrace does not realise sharing of commands, procs (and objects), it solves the problem of the eager initialisation of interpreters. Based on Tcl's unknown mechanism, it sources procs on demand. This helps to address the issue of AOLServer/ Naviservers extensive blueprinting need ... unfortunately, it provides challenges to tcl's (and xotcl's) introspection mechanism which assume an entirely initialised surrounding ...


But it's not the same as using the same object copy in memory, as each thread has it's own copy of the ns_cache object and I can manipulate each of them independently.

Indeed, you don't have a shared state, compartimentalised into objects, available. If you try to achieve that, you may choose a different strategy: Realise object representations by ns_set et al. ... XOTcl slots provide an elegant way of introducing such an representation strategy, instead of accessing per-object state (in the strict sense), the slot-provided accessor/mutator methods write to and read from ns_sets ... Well, this implies other remedies and might not be scalabale open-end, but may be a valid optimisation strategy ... Objects residing in each thread are then mere PROXIES to a single shared state, under a single, db-provided identity.

Collapse
Posted by Andrew Piskorski on
Stefan, that's very interesting... So rather than using ns_set, can XOTcl transparently layer its objects on top of nsv/tsv?

tsv::lock makes it easy to atomically perform multiple tsv commands, which might be ideal for implementing that sort of safe transparent multi-threaded object access in XOTcl.

However, I don't see any direct mention of this sort of stuff in the XOTcl docs nor its slots tutorial. Is there better info or examples somewhere on using XOTcl slots in this way?

Collapse
Posted by Andrew Piskorski on
it is a TCL issue with not having a place to store variables and methods in a global, thread independent place

Malte, of course Tcl has such a place, it's called "nsv" (in AOLserver; in the Tcl Threads Extension the same thing is called "tsv").

Of course, nsv/tsv supports only base Tcl types, strings and in some cases more complicated values like lists (with Zoran's clever perforamance hacks to avoid type shimmering). Can all the XOTcl objects you care about be serialized to from nsv/tsv? Efficiently? Between the two of them, Gustaf and Zoran should be able to tell you for sure.

Another option is to dedicate one single thread (and its associated Tcl interpretor) as your "XOTcl db" thread. Then have other threads send it messages with requests to read/write data. Everything will be serialized through that single "db" thread of course. In theory that could be much less scalable than the hash bucketized multi-threaded design of nsv/tsv, but in practice it might be simpler and faster, especially if the XOTcl objects are large but the read/write requests are small.

Collapse
Posted by Gustaf Neumann on
Can all the XOTcl objects you care about be serialized to from nsv/tsv?
Sure, the serialization of an XOTcl object is a string, such strings can be saved in nsvs, one can use the ttrace mechanism, etc. By serializing and deserializing objects, one creates a copy of the object. So, changing one instance variable in one object does not affect the other. So, serializing to nsv is in this respect the same as ns_cache.

However, it is as well possible to store the instance variables of XOTcl objects in nsvs, so value changes of instance variables effect the values in other threads immediately. I have implemented such an interface a few years ago as an experiment, but so far, i have not seen valuable usage of this. In general, one needs locking and sometime rollbacks, clustering over multiple instances is expensive. In my experience the basic approach via ns_cache is much simpler and is quite fast.

Concerning the "single thread" idea: Yes, having one (or a few) thread(s) dedicated for "object pools", which provide for certain classes an interface to the db is certainly an option, especially together with thread::send and the libthread's event loop. A connection thread can query the object pool and get e.g. the serialized object back. This approach could work similar to ttrace, but provide as well a write interface. Note that one can have multiple such thread for e.g. different classes. Note however, that this does not address the additional need for locking and transactions. Direct database manipulations (inserts, writes, deletes) bypassing the object interface are certainly as well a problem (especially for OpenACS, where this is often the common practice).

... ns_set ...
I am not sure, how ns_set could help here.

However, I don't see any direct mention of this sort of stuff in the XOTcl docs nor its slots tutorial. Is there better info or examples somewhere on using XOTcl slots in this way?
The XOTcl docs do not address aolserver specific interfaces. Slots provide a way to provide accessor methods for instance variables, and more general, manage their state. Some basic introduction is in
http://alice.wu-wien.ac.at:8000/s5-xotcl-core-tutorial/slides (not going more into details than the xotcl docs), examples are certainly in the source code (xotcl-core/tcl/05-db-procs.tcl).