Magma Answered
Last updated at 4:47 pm UTC on 28 December 2012
mergeMe into Magma
Does MagmaServer deliver an object to a client upon request?
If it does, in what format will the object be delivered?
If it does not, would you consider this as a feature request?
- A: The only object that is ever explicitly "requested" by a client is the root object. Initially, objects which the root attaches are Proxy objects which are only delivered if the root object sends a message to one of its proxies. The request is done automatically, the object retrieved from the server, and the Proxy become:d to the real object.
- Because the tests utilize multiple Squeak images, you cannot simply click on Run All in the SUnit browser. I plan to post the page about how to test Magma's functionality on the Swiki.
Q: I notice that you are assigning oids to every object that is stored in Magma and using a WeakKeyIdentityDictionary for storing the oids. One issue I had with that approach is that I think it runs into scalability issues when you approach and surpass 4096 objects (due to the number of bits available for the identity hash). Is there a way to make this scheme more scalable? Or, is it possible that it will be rare to have more than 4000 persistent objects cached on the client?
- A: Magma uses its own proprietary WeakKeyIdentityDictionary developed by Igor Stasenko. Squeak's standard WeakKeyIdentityDictionary also have been significantly improved in 2010.
Q: How are you tracking the changed objects?
- A: There are two different approaches Magma uses for this, 1) WriteBarrier and 2) Buffer-comparison. The WriteBarrier option is turned on by default and is used for most objects. When a Session is connected, any objects retrieved have a single anonymous subclass compiled for them which overrides all of the methods that potentially change its state.
For objects which cannot use the WriteBarrier method, their original Buffers from the read are kept around for as long as the object is referenced in memory. When a commit occurs, the objects are compared to their original buffers to determine whether any changes occurred.
- After I wrote the email, I discovered this...very clever! Since you only need to do the scan when you commit, it's not a horrible price to pay. I was baffled by how Magma was able to detect changes in brand new instances I was creating...I even tried to fool it, but it worked like a charm. It looks new objects get stored (during commit) when they are referenced from other objects that are already in the db...when they are stored, you then record the shallowCopy backup...that way the object is part of the scan to detect changes. Is that correct?
It takes a long time to establish a MagmaSession (especially after some objects have been populated in the server)...can you describe what's happening when connecting?
- A: A newly-created MagmaSession should not take a long time to connect (never > 1 second). However, MagmaSessions can disconnect and reconnect, can survive image restarts, even when they are in a transaction. For those old sessions, when they reconnect, they may have accumulated quite a few objects which they had read in the past. Magma has no choice but to refresh those upon reconnect so that the state of that Sessions view of the persistent model is correct and up-to-date.
- I haven't posted the Swiki page yet about how to tell Magma to "upgrade" a class to a new version, but you can see examples in MagmaTestCase.
I see that you are using a stubbing mechanism (ala GemStone) that uses a ProtoObject and #doesNotUnderstand: to transparently forward messages to the real object. Are you also using #become: to change these objects into their real counterpart? If so, won't this present a performance issue under certain circumstances (where one or both of the objects are in old space)? Also, did you implement a "stubbing level" mechanism ala GemStone?
- A: Squeak's primitive become operation supports multiple objects at a time. Magma minimizes the number of calls to become: by saving them up in batches for 30-second periods and doing them all together.
In addition to this, the number of becomes: can be reduced by setting a ReadStrategy on the Session. Magma, by default, reads +1 level deep whenever it reifies a proxy, leaving references at +1 level down also proxies (unless they cycle back to a "higher" place in the model which had already been retrieved, of course). But this is a balancing act, since it also means that the Read's will be larger and take longer.
For OLTP applications, +1 level is generally fine for end-user performance expectations.
Is there any kind of cache control in Magma? For example, if I have a client that is running for many weeks and accessing lot's of objects, once they are pulled from the server to the client, are they going to stay in the client indefinitely? Is there some way of controlling how many objects are retained in the client's object memory?
- A: The only "caching" Magma does is in weak collections, so there shouldn't be anything that you don't cache yourself.
- Right, but once a stub gets replaced with a real object, the real object will never get replaced back with a stub, correct? Which means that, since the session has a reference to the root, and the root has a reference to every other object in the database, once an object is pulled into the client it will never be garbage collected unless it is removed from the database. This can be a problem for long running clients. I think what Stephen is suggesting is that, for example, you periodically becomeForward: objects back into stubs that have not been used for a certain length of time.
Yes, any object can be converted back to a "stub" (Proxy) by telling it to #stubOut:.