Hi again Chris,
Chris Muller wrote:
Hi Florian, recall from http://wiki.squeak.org/squeak/2638:
"The minimumDepth is how far it reads for any object, all objects, every time, all the time."
My understanding of this is that if I ask Magma for a Player object with a minDepth of 3, it will follow references and reify objects on a depth of 3.
"As a programmer, you can change this default 0, 1, 2 or 3 (or maybe even 4, but I wouldn't go beyond that) by supplying a ReadStrategy."
My problem is that my application is a game. And every 12h it need to go through the whole hierarchy of the whole players to update them. If I let the minDepth to 1, the read, update and commit of one player takes something like 15min due to the heavy number of requests to magma (lot of very small objects). So I want to reify the whole object hierarchy of my Player before updating it. Therefore I use a minDepth of 10 (the max depth is : Player->(1)Dungeon->(*)MonsterRoom->(*)Adventurer->(1)Treasure->(*)SmallInteger).
And it works great for Players without any Letters, it only takes something like 30s instead of several minutes. But if the Player has some Letters, Magma will reify the recipients and therefore other Players. The read-update-commit then takes ~5-7min (quite annoying to get a real value).
So here are a couple of options for you.
Option 1:
The minimumDepth is the global minimum that cannot be overridden except by using a negative depth on a variable-specific specification; but I tend to prefer staying positive just for clarity. So you could just specify a very low minimumDepth and then larger depths for each variable you want to go deeper on:
myReadStrategy := MaReadStrategy minimumDepth: 0. (Player allInstVarNames copyWithout: 'letters') do: [ : each | myReadStrategy forVariableNamed: each onAny: Player readToDepth: 10 ]
Something like that. Since a minimumDepth of 0 can really thrash the server with a lot of small requests, you should specify 1 for everything else. Not too much trouble though, do you have a main superclass for your hierarchy?
myReadStrategy onAny: GameObject readToDepth: 1
Player, even though it inherits from FlorianGame will still employ a minimum-depth of 0. This is a convenience feature for just this situation.
I didn't have the need to a single superclass for the whole hierarchy (~30 class) but it could be bothersome, but if needed I could try.
I didn't test this option because my need is the opposite : full depth everywhere and no depth for Desk. And the object hierarchy of a Player is quite complex. I could use reflection to specify a depth of 1 to every variable except myDesk but it's a little bit heavy.
Option 2:
Even still, option 1 you don't get a minimumDepth of 1 for everything else outside your GameObject, like Associations or other out-of-the-box Smalltalk classes (you do with Collections, they always get 1).
So, another option would be to stick with a minimumDepth of 1 everywhere but then "back up" one level just for Players letters:
myReadStrategy := (MaReadStrategy minimumDepth: 1) forVariableNamed: 'letters' onAny: Player readToDepth: -1; yourself.
Even though it uses a negative, this might be easier..
I tried this method :
session readStrategy: ( (MaReadStrategy minimumDepth: 10) forVariableNamed: 'myDesk' onAny: Dungeon readToDepth: -1; yourself ).
But the Desk is still reified. I tried with -11 but with the same result :/. Did I miss something ?
Florian
- Chris
On 7/5/07, Florian Minjat florian.minjat@gmail.com wrote:
Hi Chris, I did some tests and have to ask for this again : As you saw I have a Desk with letters which refers to other Players. But Players also have Rooms with Adventurers and Treasure. The structure can be simplified like that (varName:varType):
Player ->(1)Desk->(*)Letter ->(*)Room->(*)Adventurer->(1)Treasure->(1)SmallInteger
I don't want theses letters to be reified but I want object deeper like the value of the treasure of an Adventurer to be reified. So I tried something like that :
session readStrategy: ( (MaReadStrategy minimumDepth: 10) forVariableNamed: 'letters' onAny: Desk readToDepth: 0 )
But it didn't seem to work : ((player instVarNamed: 'desk') instVarNamed: 'letters') class => OrderedCollection (((player instVarNamed: 'desk') instVarNamed: 'letters') instVarAt: 1) class => Array ((((player instVarNamed: 'desk') instVarNamed: 'letters') instVarAt:
instVarAt: 1) class => Letter
So how can I make the rule on Desk precedes the more global rule ?
Currently, retrieving a Player without Letters takes a few seconds, with Letters a few minutes :/.
Florian
Dear Florian,
I had similar problems.
If I understand correctly with the current scheme a negative value on a variable will not prevent that variable actually being read. It may lessen the propagation of the depth of that strategy down that branch.
I finally gave up on the existing numeric/array type implementation of the read strategy scheme and reimplemented it with a proper object oriented model that I could fully understand and am able to dissect in order to test alternative approaches.
The existing approach works best with a cautious read strategy, one which reads 1 level as normal with high levels reserved for those objects which are entirely safe to read en-mass
If you do specify higher levels you run the risk of an infinite recursion if your model has circular references. I.e. get me an A which contains B which points to A which I haven't got yet so, get me A.
I wanted to use read strategies which say, read lots, except this branch. Or if not reading lots, at least ensure you read frequently indexable attributes such as id, name, type.
This work is part of the "Magma seaside" package, and you can simply use WAMagmaReadStrategyDefault instead of the standard read strategy class. You may also find the WAMagmaReadStrategyWithQ2Logging helpful. It uses the Q2Log from Gjallar project, which I think is also available on SqueakMap under another name. (SLog or SLLog ?)
My basic approach is the same, except that I fully support negative depths.
In my scheme: for any class you can specify a default depth for all vars, or all vars that are mine, (i.e. not the inherited inst vars) or for a specific variable name. These specifications are inherited by subclasses, including any as yet unspecified vars will inherit the defaults from their superclasses.
best regards
Keith
Hi again Chris,
Chris Muller wrote:
Hi Florian, recall from http://wiki.squeak.org/squeak/2638:
"The minimumDepth is how far it reads for any object, all objects, every time, all the time."
My understanding of this is that if I ask Magma for a Player object with a minDepth of 3, it will follow references and reify objects on a depth of 3.
"As a programmer, you can change this default 0, 1, 2 or 3 (or maybe even 4, but I wouldn't go beyond that) by supplying a ReadStrategy."
My problem is that my application is a game. And every 12h it need to go through the whole hierarchy of the whole players to update them. If I let the minDepth to 1, the read, update and commit of one player takes something like 15min due to the heavy number of requests to magma (lot of very small objects). So I want to reify the whole object hierarchy of my Player before updating it. Therefore I use a minDepth of 10 (the max depth is : Player->(1)Dungeon->(*)MonsterRoom->(*)Adventurer->(1)Treasure->(*)SmallInteger).
And it works great for Players without any Letters, it only takes something like 30s instead of several minutes. But if the Player has some Letters, Magma will reify the recipients and therefore other Players. The read-update-commit then takes ~5-7min (quite annoying to get a real value).
So here are a couple of options for you.
Option 1:
The minimumDepth is the global minimum that cannot be overridden except by using a negative depth on a variable-specific specification; but I tend to prefer staying positive just for clarity. So you could just specify a very low minimumDepth and then larger depths for each variable you want to go deeper on:
myReadStrategy := MaReadStrategy minimumDepth: 0. (Player allInstVarNames copyWithout: 'letters') do: [ : each | myReadStrategy forVariableNamed: each onAny: Player readToDepth: 10 ]
Something like that. Since a minimumDepth of 0 can really thrash the server with a lot of small requests, you should specify 1 for everything else. Not too much trouble though, do you have a main superclass for your hierarchy?
myReadStrategy onAny: GameObject readToDepth: 1
Player, even though it inherits from FlorianGame will still employ a minimum-depth of 0. This is a convenience feature for just this situation.
I didn't have the need to a single superclass for the whole hierarchy (~30 class) but it could be bothersome, but if needed I could try.
I didn't test this option because my need is the opposite : full depth everywhere and no depth for Desk. And the object hierarchy of a Player is quite complex. I could use reflection to specify a depth of 1 to every variable except myDesk but it's a little bit heavy.
Option 2:
Even still, option 1 you don't get a minimumDepth of 1 for everything else outside your GameObject, like Associations or other out-of-the-box Smalltalk classes (you do with Collections, they always get 1).
So, another option would be to stick with a minimumDepth of 1 everywhere but then "back up" one level just for Players letters:
myReadStrategy := (MaReadStrategy minimumDepth: 1) forVariableNamed: 'letters' onAny: Player readToDepth: -1; yourself.
Even though it uses a negative, this might be easier..
I tried this method :
session readStrategy: ( (MaReadStrategy minimumDepth: 10) forVariableNamed: 'myDesk' onAny: Dungeon readToDepth: -1; yourself ).
But the Desk is still reified. I tried with -11 but with the same result :/. Did I miss something ?
Florian
- Chris
On 7/5/07, Florian Minjat florian.minjat@gmail.com wrote:
Hi Chris, I did some tests and have to ask for this again : As you saw I have a Desk with letters which refers to other Players. But Players also have Rooms with Adventurers and Treasure. The structure can be simplified like that (varName:varType):
Player ->(1)Desk->(*)Letter ->(*)Room->(*)Adventurer->(1)Treasure->(1)SmallInteger
I don't want theses letters to be reified but I want object deeper like the value of the treasure of an Adventurer to be reified. So I tried something like that :
session readStrategy: ( (MaReadStrategy minimumDepth: 10) forVariableNamed: 'letters' onAny: Desk readToDepth: 0 )
But it didn't seem to work : ((player instVarNamed: 'desk') instVarNamed: 'letters') class => OrderedCollection (((player instVarNamed: 'desk') instVarNamed: 'letters') instVarAt: 1) class => Array ((((player instVarNamed: 'desk') instVarNamed: 'letters') instVarAt:
instVarAt: 1) class => Letter
So how can I make the rule on Desk precedes the more global rule ?
Currently, retrieving a Player without Letters takes a few seconds, with Letters a few minutes :/.
Florian
Magma mailing list Magma@lists.squeakfoundation.org http://lists.squeakfoundation.org/mailman/listinfo/magma
Hi Keith,
If I understand correctly with the current scheme a negative value on a variable will not prevent that variable actually being read. It may lessen the propagation of the depth of that strategy down that branch.
I don't understand why everyone wants to use negatives; they're really not necessary and staying positive is, to me, much clearer. A depth-specification is local to the class hierarchy you are specifying for. If you use a negative depth then it would seem to be making a suggestion for the referencing classes; which, to me, is counter-intuitive to encapsulated thinking, at best.
The first time this came up, I thought I tried a negative once in a workspace and it worked. I will investigate it even though I'm not seeing a good reason for them. Won't someone explain it to me?
I finally gave up on the existing numeric/array type implementation of the read strategy scheme and reimplemented it with a proper object oriented model that I could fully understand and am able to dissect in order to test alternative approaches.
Yes, this is one area of Magma that was originally optimized to a compactly-serialized model, because the ReadStrategy's used to be sent on every read request. Since then they were cached on the server and therefore the compact benefit was reduced. But it already worked and still better when frequently changing ReadStrategy's, since each change means it serializes a new one and ships it up to the server.
Still, I will be interested to look at your reification. Is it on SqueakSource?
If you do specify higher levels you run the risk of an infinite recursion if your model has circular references. I.e. get me an A which contains B which points to A which I haven't got yet so, get me A.
Absolutely not. The main thrust of Magma is to permit a rich, deep, unfettered domain model, complete with cycles. Disallowing them would not be transparent at all.
Magma keeps track of where its been in any read-operation. A and B will materialize in the image pointing to each other.
I wanted to use read strategies which say, read lots, except this branch. Or if not reading lots, at least ensure you read frequently indexable attributes such as id, name, type.
Ok, I see the wanting-to-use-negatives mindset here. I'm pretty sure this can be achieved by just specifying deep at a fairly abstract superclass and, additionally, a shallow depth for the particular branch you want to except. Isn't that simple?
Regards, Chris
Florian Minjat a écrit :
Hi again Chris,
Chris Muller wrote:
Hi Florian, recall from http://wiki.squeak.org/squeak/2638:
"The minimumDepth is how far it reads for any object, all objects, every time, all the time."
My understanding of this is that if I ask Magma for a Player object with a minDepth of 3, it will follow references and reify objects on a depth of 3.
"As a programmer, you can change this default 0, 1, 2 or 3 (or maybe even 4, but I wouldn't go beyond that) by supplying a ReadStrategy."
My problem is that my application is a game. And every 12h it need to go through the whole hierarchy of the whole players to update them. If I let the minDepth to 1, the read, update and commit of one player takes something like 15min due to the heavy number of requests to magma (lot of very small objects). So I want to reify the whole object hierarchy of my Player before updating it. Therefore I use a minDepth of 10 (the max depth is : Player->(1)Dungeon->(*)MonsterRoom->(*)Adventurer->(1)Treasure->(*)SmallInteger).
I got such a kind of problem (well I envision I will have it). One solution I found was to redesign my objects to get a more flat structure where it is easy to do where: request to retrieve the exact object I need. Try to get more top level Magma collection in your design.
Not sure it can apply to your problem...
Hilaire
magma@lists.squeakfoundation.org