Hi,
I am trying to do something like this: I have a class LoadProjectTest that is essentially a singleton and the LoadProjectTest class is in category eToys-Tests. I'd like to do something like this: In the image where this class originates, I am creating the instance, and setting one instance variable with some value from a local file. I'd like the instance to be stored in Monticello, when I "save" the category. Then, when the MCZ is loaded into another image, the instance would be there, filled with the value as created in the originating image.
However, when I load the MCZ into another image, the instance is null; although I was assuming otherwise, that makes sense as the Monticello repository stores code not live objects.
Is it possible to, somehow, to make Monticello to keep the instance, so it is deserialized from the MCZ when the MCZ is loaded into the target image?
Thanks Milan
On Sun, Feb 11, 2007 at 10:07:48PM -0500, Milan Zimmermann wrote:
Hi,
I am trying to do something like this: I have a class LoadProjectTest that is essentially a singleton and the LoadProjectTest class is in category eToys-Tests. I'd like to do something like this: In the image where this class originates, I am creating the instance, and setting one instance variable with some value from a local file. I'd like the instance to be stored in Monticello, when I "save" the category. Then, when the MCZ is loaded into another image, the instance would be there, filled with the value as created in the originating image.
However, when I load the MCZ into another image, the instance is null; although I was assuming otherwise, that makes sense as the Monticello repository stores code not live objects.
Is it possible to, somehow, to make Monticello to keep the instance, so it is deserialized from the MCZ when the MCZ is loaded into the target image?
You would write some class initialization code that creates this instance, and stores it where you see fit. Put your code in the class-side initialize method.
A good example of a code that does just that is the class ExternalType in category FFI-Kernel. Look at the methods in category "class initialization"
Thanks Milan
Hope it helps.
Mathew,
do you mean class-side initilization that would run when the MCZ is loaded in the image on the "target" system? If so, that is not what I am looking for - I am explicitly trying to initialize that member only on the first system that creates the MCZ. In more detail, when creating resource for the test, I stream eToys .pr file into a String, and the tests then stream Projects from this string as if they were loading the .pr file. The reason I need that, is I cannot (and do not want to) ship these .pr files around with the tests.
Milan
On 2007 February 12 00:27, Matthew Fulmer wrote:
On Sun, Feb 11, 2007 at 10:07:48PM -0500, Milan Zimmermann wrote:
Hi,
I am trying to do something like this: I have a class LoadProjectTest that is essentially a singleton and the LoadProjectTest class is in category eToys-Tests. I'd like to do something like this: In the image where this class originates, I am creating the instance, and setting one instance variable with some value from a local file. I'd like the instance to be stored in Monticello, when I "save" the category. Then, when the MCZ is loaded into another image, the instance would be there, filled with the value as created in the originating image.
However, when I load the MCZ into another image, the instance is null; although I was assuming otherwise, that makes sense as the Monticello repository stores code not live objects.
Is it possible to, somehow, to make Monticello to keep the instance, so it is deserialized from the MCZ when the MCZ is loaded into the target image?
You would write some class initialization code that creates this instance, and stores it where you see fit. Put your code in the class-side initialize method.
A good example of a code that does just that is the class ExternalType in category FFI-Kernel. Look at the methods in category "class initialization"
Thanks Milan
Hope it helps.
A workaround would be to put that string into a method, and unserialize the project into the class var in the class-side #initialize.
A totally hackish thing would be to include the project file in the MCZ, which is just a ZIP archive after all, and when #initialize is called on your class, walk up the call chain to find the Monticello instance that initiated the load - peek into its innards to get at the file ;-)
- Bert -
On Feb 12, 2007, at 13:50 , Milan Zimmermann wrote:
Mathew,
do you mean class-side initilization that would run when the MCZ is loaded in the image on the "target" system? If so, that is not what I am looking for - I am explicitly trying to initialize that member only on the first system that creates the MCZ. In more detail, when creating resource for the test, I stream eToys .pr file into a String, and the tests then stream Projects from this string as if they were loading the .pr file. The reason I need that, is I cannot (and do not want to) ship these .pr files around with the tests.
Milan
On 2007 February 12 00:27, Matthew Fulmer wrote:
On Sun, Feb 11, 2007 at 10:07:48PM -0500, Milan Zimmermann wrote:
Hi,
I am trying to do something like this: I have a class LoadProjectTest that is essentially a singleton and the LoadProjectTest class is in category eToys-Tests. I'd like to do something like this: In the image where this class originates, I am creating the instance, and setting one instance variable with some value from a local file. I'd like the instance to be stored in Monticello, when I "save" the category. Then, when the MCZ is loaded into another image, the instance would be there, filled with the value as created in the originating image.
However, when I load the MCZ into another image, the instance is null; although I was assuming otherwise, that makes sense as the Monticello repository stores code not live objects.
Is it possible to, somehow, to make Monticello to keep the instance, so it is deserialized from the MCZ when the MCZ is loaded into the target image?
You would write some class initialization code that creates this instance, and stores it where you see fit. Put your code in the class-side initialize method.
A good example of a code that does just that is the class ExternalType in category FFI-Kernel. Look at the methods in category "class initialization"
Thanks Milan
Hope it helps.
On 2007 February 12 08:06, Bert Freudenberg wrote:
A workaround would be to put that string into a method, and unserialize the project into the class var in the class-side #initialize.
Yes, this is basically what I am trying to do now. Basically (sort of ) a copy and paste from the live string into a method and adding ^'' around (through a ByteArray and a few hoops, as I cannot just copy and paste).
Speaking of copy/paste: When I do Alt-p on something like:
(ProjectsToTestContainer getContainedProjectHolders at: 1) getProject
It shows something like:
a ByteArray(80 75 3 4 20....etc...)
when the result is very long, it shows "...etc" at the end. Same if I print to Transcript. Is there some way to force showing all the contents?
A totally hackish thing would be to include the project file in the MCZ, which is just a ZIP archive after all, and when #initialize is called on your class, walk up the call chain to find the Monticello instance that initiated the load - peek into its innards to get at the file ;-)
Maybe not as hackish ;) I think this would allow a less "manual" process when adding another project to test.
Thanks Milan
- Bert -
On Feb 12, 2007, at 13:50 , Milan Zimmermann wrote:
Mathew,
do you mean class-side initilization that would run when the MCZ is loaded in the image on the "target" system? If so, that is not what I am looking for - I am explicitly trying to initialize that member only on the first system that creates the MCZ. In more detail, when creating resource for the test, I stream eToys .pr file into a String, and the tests then stream Projects from this string as if they were loading the .pr file. The reason I need that, is I cannot (and do not want to) ship these .pr files around with the tests.
Milan
On 2007 February 12 00:27, Matthew Fulmer wrote:
On Sun, Feb 11, 2007 at 10:07:48PM -0500, Milan Zimmermann wrote:
Hi,
I am trying to do something like this: I have a class LoadProjectTest that is essentially a singleton and the LoadProjectTest class is in category eToys-Tests. I'd like to do something like this: In the image where this class originates, I am creating the instance, and setting one instance variable with some value from a local file. I'd like the instance to be stored in Monticello, when I "save" the category. Then, when the MCZ is loaded into another image, the instance would be there, filled with the value as created in the originating image.
However, when I load the MCZ into another image, the instance is null; although I was assuming otherwise, that makes sense as the Monticello repository stores code not live objects.
Is it possible to, somehow, to make Monticello to keep the instance, so it is deserialized from the MCZ when the MCZ is loaded into the target image?
You would write some class initialization code that creates this instance, and stores it where you see fit. Put your code in the class-side initialize method.
A good example of a code that does just that is the class ExternalType in category FFI-Kernel. Look at the methods in category "class initialization"
Thanks Milan
Hope it helps.
Hi Milan,
I used this solution in EasyMorphicGUI to store GUI prototype as a bytearray in a class method named serializedPrototype. Serialization and deserialization are done using class methods EMGGuiMorph class>>savePrototype EMGGuiMorph class>>restorePrototype
Code is available at http://csl.ensm-douai.fr/EasyMorphicGUI
Cheers, Noury Le 13 févr. 07 à 07:35, Milan Zimmermann a écrit :
On 2007 February 12 08:06, Bert Freudenberg wrote:
A workaround would be to put that string into a method, and unserialize the project into the class var in the class-side #initialize.
Yes, this is basically what I am trying to do now. Basically (sort of ) a copy and paste from the live string into a method and adding ^'' around (through a ByteArray and a few hoops, as I cannot just copy and paste).
Speaking of copy/paste: When I do Alt-p on something like:
(ProjectsToTestContainer getContainedProjectHolders at: 1) getProject
It shows something like:
a ByteArray(80 75 3 4 20....etc...)
when the result is very long, it shows "...etc" at the end. Same if I print to Transcript. Is there some way to force showing all the contents?
A totally hackish thing would be to include the project file in the MCZ, which is just a ZIP archive after all, and when #initialize is called on your class, walk up the call chain to find the Monticello instance that initiated the load - peek into its innards to get at the file ;-)
Maybe not as hackish ;) I think this would allow a less "manual" process when adding another project to test.
Thanks Milan
- Bert -
On Feb 12, 2007, at 13:50 , Milan Zimmermann wrote:
Mathew,
do you mean class-side initilization that would run when the MCZ is loaded in the image on the "target" system? If so, that is not what I am looking for - I am explicitly trying to initialize that member only on the first system that creates the MCZ. In more detail, when creating resource for the test, I stream eToys .pr file into a String, and the tests then stream Projects from this string as if they were loading the .pr file. The reason I need that, is I cannot (and do not want to) ship these .pr files around with the tests.
Milan
On 2007 February 12 00:27, Matthew Fulmer wrote:
On Sun, Feb 11, 2007 at 10:07:48PM -0500, Milan Zimmermann wrote:
Hi,
I am trying to do something like this: I have a class LoadProjectTest that is essentially a singleton and the LoadProjectTest class is in category eToys-Tests. I'd like to do something like this: In the image where this class originates, I am creating the instance, and setting one instance variable with some value from a local file. I'd like the instance to be stored in Monticello, when I "save" the category. Then, when the MCZ is loaded into another image, the instance would be there, filled with the value as created in the originating image.
However, when I load the MCZ into another image, the instance is null; although I was assuming otherwise, that makes sense as the Monticello repository stores code not live objects.
Is it possible to, somehow, to make Monticello to keep the instance, so it is deserialized from the MCZ when the MCZ is loaded into the target image?
You would write some class initialization code that creates this instance, and stores it where you see fit. Put your code in the class-side initialize method.
A good example of a code that does just that is the class ExternalType in category FFI-Kernel. Look at the methods in category "class initialization"
Thanks Milan
Hope it helps.
Noury ------------------------------------------------------------------ Dr. Noury Bouraqadi - Enseignant/Chercheur ARMINES - Ecole des Mines de Douai - Dept. I.A. http://csl.ensm-douai.fr/noury
European Smalltalk Users Group Board http://www.esug.org ------------------------------------------------------------------
On my wish list is the ability to manage Workspace and ScriptManager contents in Monticello.
Keith
___________________________________________________________ Copy addresses and emails from any email account to Yahoo! Mail - quick, easy and free. http://uk.docs.yahoo.com/trueswitch2.html
On 2007 February 13 10:57, Keith Hodges wrote:
On my wish list is the ability to manage Workspace and ScriptManager contents in Monticello.
Hi Keith,
that sounds interesting, could you elaborate? Do you have in mind storing objects/state in general, only instances of the 2 above or something else :)
Thanks Milan
Keith
Copy addresses and emails from any email account to Yahoo! Mail - quick, easy and free. http://uk.docs.yahoo.com/trueswitch2.html
On Feb 13, 2007, at 7:35 , Milan Zimmermann wrote:
On 2007 February 12 08:06, Bert Freudenberg wrote:
A workaround would be to put that string into a method, and unserialize the project into the class var in the class-side #initialize.
Yes, this is basically what I am trying to do now. Basically (sort of ) a copy and paste from the live string into a method and adding ^'' around (through a ByteArray and a few hoops, as I cannot just copy and paste).
Speaking of copy/paste: When I do Alt-p on something like:
(ProjectsToTestContainer getContainedProjectHolders at: 1) getProject
It shows something like:
a ByteArray(80 75 3 4 20....etc...)
when the result is very long, it shows "...etc" at the end. Same if I print to Transcript. Is there some way to force showing all the contents?
Use #storeString instead of #printString.
OTOH, a common way is base64 encoding your binary data into a string.
A totally hackish thing would be to include the project file in the MCZ, which is just a ZIP archive after all, and when #initialize is called on your class, walk up the call chain to find the Monticello instance that initiated the load - peek into its innards to get at the file ;-)
Maybe not as hackish ;) I think this would allow a less "manual" process when adding another project to test.
Well, it is a one-time hack because you cannot reproduce a similar MCZ by writing it out again.
- Bert -
On 2007 February 13 06:10, Bert Freudenberg wrote:
Use #storeString instead of #printString.
Hi Bert,
Thanks for your comments along the way. I ended up storing each project as "manually serialized" ByteArrays returned from a method.
Along the way I found a problem related to compiler which prevented me from using the "storeString" for large volume.
-# I used MultiByteFileStream to stream project into a ByteArray, for example byteArr:=#(80 75 3 4 20 0 0 0 0 0 76 134 203 ....). Then I tried something like:
byteArr := #(80 75 3 4 20 0 0 0 0 0 76 134 203) asByteArray. byteArrStoreString := byteArr storeString. method := 'method1 ^', '''', byteArrStoreString, ''''. TestCompile compile: method classified: 'my-compile-test'
This worked for the short ByteArray above, but for a long one, I get an Error from CompileMethod:
"Error: Cannot compile - too many literal variables"
There are limits in the CompileMethod code such as: nTemps > 63 ifTrue: [^ self error: 'Cannot compile -- too many temporary variables']. nLits > 255 ifTrue: [^ self error: 'Cannot compile -- too many literals variables']. A naive question, does this have to do with the way classes are represented in the VM?
-# So I ended up "manually serializing" the ByteArray, esentially as a literal String such as '80 75 3 4 20 0 0 0 0 0 76 134 203' in the small example above. Then deserialized after the method answered.
OTOH, a common way is base64 encoding your binary data into a string.
I looked at the Base64MimeConverter but I already had the project as ByteArray so I did a simple manual serialize/desirialize as space separated decimals 0-255 which works. I should replace it with using the Base64MimeConverter.
Thanks Milan
A totally hackish thing would be to include the project file in the MCZ, which is just a ZIP archive after all, and when #initialize is called on your class, walk up the call chain to find the Monticello instance that initiated the load - peek into its innards to get at the file ;-)
Maybe not as hackish ;) I think this would allow a less "manual" process when adding another project to test.
Well, it is a one-time hack because you cannot reproduce a similar MCZ by writing it out again.
- Bert -
Hi Milan,
on Sat, 24 Feb 2007 09:53:50 +0100, you wrote:
On 2007 February 13 06:10, Bert Freudenberg wrote:
Use #storeString instead of #printString.
Hi Bert,
Thanks for your comments along the way. I ended up storing each project as "manually serialized" ByteArrays returned from a method.
Along the way I found a problem related to compiler which prevented me from using the "storeString" for large volume.
-# I used MultiByteFileStream to stream project into a ByteArray, for example byteArr:=#(80 75 3 4 20 0 0 0 0 0 76 134 203 ....). Then I tried something like:
byteArr := #(80 75 3 4 20 0 0 0 0 0 76 134 203) asByteArray. byteArrStoreString := byteArr storeString. method := 'method1 ^', '''', byteArrStoreString, ''''. TestCompile compile: method classified: 'my-compile-test'
This worked for the short ByteArray above, but for a long one, I get an Error from CompileMethod:
"Error: Cannot compile - too many literal variables"
There are limits in the CompileMethod code such as: nTemps > 63 ifTrue: [^ self error: 'Cannot compile -- too many temporary variables']. nLits > 255 ifTrue: [^ self error: 'Cannot compile -- too many literals variables']. A naive question, does this have to do with the way classes are represented in the VM?
Since I am [in part] responsible for having the above checks in a consistent way, here's my part of the answer:
No. These limits exist because the header field in CompiledMethod has room for just these respective number of bits.
Has nothing to do with, how classes are represented in the VM, but with, how CompiledMethods are represented in the VM.
-# So I ended up "manually serializing" the ByteArray, esentially as a literal String such as '80 75 3 4 20 0 0 0 0 0 76 134 203' in the small example above. Then deserialized after the method answered.
Correct. This way you have only one literal in the CompiledMethod, instead of one literals for each value less than -1 or greater than 2 :)
/Klaus
On Feb 24, 2007, at 10:07 , Klaus D. Witzel wrote:
Hi Milan,
byteArr := #(80 75 3 4 20 0 0 0 0 0 76 134 203) asByteArray. byteArrStoreString := byteArr storeString. method := 'method1 ^', '''', byteArrStoreString, ''''. TestCompile compile: method classified: 'my-compile-test'
This worked for the short ByteArray above, but for a long one, I get an Error from CompileMethod:
"Error: Cannot compile - too many literal variables"
-# So I ended up "manually serializing" the ByteArray, esentially as a literal String such as '80 75 3 4 20 0 0 0 0 0 76 134 203' in the small example above. Then deserialized after the method answered.
I was suggesting using #storeString on the Form, not the ByteArray. This is more efficient because it uses words instead of bytes, and it uses only one literal. This way, the parsing work is done only once when compiling. Reading decimal from a String at runtime is particularly inefficient. Don't do that ;)
- Bert -
On Sat, 24 Feb 2007 12:08:47 +0100, Bert Freudenberg wrote:
On Feb 24, 2007, at 10:07 , Klaus D. Witzel wrote:
Hi Milan,
byteArr := #(80 75 3 4 20 0 0 0 0 0 76 134 203) asByteArray. byteArrStoreString := byteArr storeString. method := 'method1 ^', '''', byteArrStoreString, ''''. TestCompile compile: method classified: 'my-compile-test'
This worked for the short ByteArray above, but for a long one, I get an Error from CompileMethod:
"Error: Cannot compile - too many literal variables"
-# So I ended up "manually serializing" the ByteArray, esentially as a literal String such as '80 75 3 4 20 0 0 0 0 0 76 134 203' in the small example above. Then deserialized after the method answered.
I was suggesting using #storeString on the Form, not the ByteArray. This is more efficient because it uses words instead of bytes, and it uses only one literal. This way, the parsing work is done only once when compiling. Reading decimal from a String at runtime is particularly inefficient. Don't do that ;)
Milan, listen to Bert and Don't do that ;)
- Bert -
On 2007 February 24 06:08, Bert Freudenberg wrote:
I was suggesting using #storeString on the Form, not the ByteArray. This is more efficient because it uses words instead of bytes, and it uses only one literal.
I misunderstood ... by Form, do you mean the project contents read from file, I am not clear on that.
This way, the parsing work is done only once when compiling. Reading decimal from a String at runtime is particularly inefficient. Don't do that ;)
I live to learn :) - and thanks for help.
Trying to be quick I misrepresented my wording about Decimals, the deserialization does:
serializedByteArrayContentsAsString do: [ :b | (b = Character space) ifTrue: [coll addLast: token asInteger. token := ''.] ifFalse: [token := token,b asString.].]. "process last snipped" coll asByteArray. It is a hack and not very fast, but seems ok in the context of this being done once for all tests. Would this be considered slow, I am not sure what to compare it to. Maybe it is even slower than reading decimal from a String. I should really replace it.
Milan
- Bert -
On Feb 24, 2007, at 23:54 , Milan Zimmermann wrote:
On 2007 February 24 06:08, Bert Freudenberg wrote:
I was suggesting using #storeString on the Form, not the ByteArray. This is more efficient because it uses words instead of bytes, and it uses only one literal.
I misunderstood ... by Form, do you mean the project contents read from file, I am not clear on that.
I think I misremembered ... you are trying to embed a project, right? I thought it was a picture (class Form).
This way, the parsing work is done only once when compiling. Reading decimal from a String at runtime is particularly inefficient. Don't do that ;)
I live to learn :) - and thanks for help.
Trying to be quick I misrepresented my wording about Decimals, the deserialization does:
serializedByteArrayContentsAsString do: [ :b | (b = Character space) ifTrue: [coll addLast: token asInteger. token := ''.] ifFalse: [token := token,b asString.].]. "process last snipped" coll asByteArray. It is a hack and not very fast, but seems ok in the context of this being done once for all tests. Would this be considered slow, I am not sure what to compare it to. Maybe it is even slower than reading decimal from a String. I should really replace it.
Base64 has a space overhead of about 33%, it encodes 3 bytes in 4 characters. Printing each byte as decimal number plus a space adds about 250% on average, each byte takes 2 to 4 characters to encode. So space-wise base64 should be vastly more efficient. We can test that:
a := ((1 to: 100000) collect: [:i | i \ 256]) asByteArray. "encoding" s1 := String streamContents: [:s | a do: [:each | s print: each; space]]. s2 := (Base64MimeConverter mimeEncode: a readStream) contents. "decoding" t0 := [coll := OrderedCollection new. token := ''. s1 do: [ :b | (b = Character space) ifTrue: [coll addLast: token asInteger. token := ''.] ifFalse: [token := token,b asString.].]. a0:= coll asByteArray] timeToRun. t1 := [r1 := s1 readStream. a1 := ByteArray streamContents: [:s | [r1 atEnd] whileFalse: [s nextPut: (Integer readFrom: r1). r1 skip: 1]]] timeToRun. t2 := [a2 := (Base64MimeConverter mimeDecodeToBytes: s2 readStream) contents] timeToRun. {'Original'. a0=a. s1 size. t0. 'Decimal'. a1=a. s1 size. t1. 'Base64'. a2=a. s2 size. t2}
#('Original' true 356992 2334 'Decimal' true 356992 1064 'Base64' true 135187 103)
So your code (t0) can be optimized a bit (t1), making it half as slow. But doing base64 (t2) is an additional 10 times faster.
So ... 10 times faster ... using a third of the space ... base64 wins hands down, IMHO ;)
- Bert -
On 2007 February 25 08:09, Bert Freudenberg wrote:
On Feb 24, 2007, at 23:54 , Milan Zimmermann wrote:
On 2007 February 24 06:08, Bert Freudenberg wrote:
I was suggesting using #storeString on the Form, not the ByteArray. This is more efficient because it uses words instead of bytes, and it uses only one literal.
I misunderstood ... by Form, do you mean the project contents read from file, I am not clear on that.
I think I misremembered ... you are trying to embed a project, right? I thought it was a picture (class Form).
Yes, a project the is read from a pr file.
<<snip>>
Base64 has a space overhead of about 33%, it encodes 3 bytes in 4 characters. Printing each byte as decimal number plus a space adds about 250% on average, each byte takes 2 to 4 characters to encode. So space-wise base64 should be vastly more efficient. We can test that:
a := ((1 to: 100000) collect: [:i | i \ 256]) asByteArray. "encoding" s1 := String streamContents: [:s | a do: [:each | s print: each; space]]. s2 := (Base64MimeConverter mimeEncode: a readStream) contents. "decoding" t0 := [coll := OrderedCollection new. token := ''. s1 do: [ :b | (b = Character space) ifTrue: [coll addLast: token asInteger. token := ''.] ifFalse: [token := token,b asString.].]. a0:= coll asByteArray] timeToRun. t1 := [r1 := s1 readStream. a1 := ByteArray streamContents: [:s | [r1 atEnd] whileFalse: [s nextPut: (Integer readFrom: r1). r1 skip: 1]]] timeToRun. t2 := [a2 := (Base64MimeConverter mimeDecodeToBytes: s2 readStream) contents] timeToRun. {'Original'. a0=a. s1 size. t0. 'Decimal'. a1=a. s1 size. t1. 'Base64'. a2=a. s2 size. t2}
#('Original' true 356992 2334 'Decimal' true 356992 1064 'Base64' true 135187 103)
I will not argue with 10x performance gain and provided code on top of it :) and will replace my code with Base64MimeConverter
Thanks!
Milan
So your code (t0) can be optimized a bit (t1), making it half as slow. But doing base64 (t2) is an additional 10 times faster.
So ... 10 times faster ... using a third of the space ... base64 wins hands down, IMHO ;)
- Bert -
Hi Klaus,
On 2007 February 24 04:07, Klaus D. Witzel wrote:
Hi Milan,
on Sat, 24 Feb 2007 09:53:50 +0100, you wrote:
<<snip>>
There are limits in the CompileMethod code such as: nTemps > 63 ifTrue: [^ self error: 'Cannot compile -- too many temporary variables']. nLits > 255 ifTrue: [^ self error: 'Cannot compile -- too many literals variables']. A naive question, does this have to do with the way classes are represented in the VM?
Since I am [in part] responsible for having the above checks in a consistent way, here's my part of the answer:
No. These limits exist because the header field in CompiledMethod has room for just these respective number of bits.
Has nothing to do with, how classes are represented in the VM, but with, how CompiledMethods are represented in the VM.
Thanks for explaining it. Considering my zero level awareness of how image interacts with the VM, and that I never looked at VM code, I should take this to the newbies list .. but anyway. I assume this limit only applies to methods compiled dynamically using ClassDescription>>compile:classified: and friends, not to methods code that I type in browser, is that correct? Also, I wonder how other VMs handle this, is it a performance reason that Squeak (apparently) allocates fixed space to CompileMethod header (instead of maybe making it a linked list)?
Milan
-# So I ended up "manually serializing" the ByteArray, esentially as a literal String such as '80 75 3 4 20 0 0 0 0 0 76 134 203' in the small example above. Then deserialized after the method answered.
Correct. This way you have only one literal in the CompiledMethod, instead of one literals for each value less than -1 or greater than 2 :)
/Klaus
Hi Milan,
on Sun, 25 Feb 2007 00:03:22 +0100, you wrote:
Hi Klaus, On 2007 February 24 04:07, Klaus D. Witzel wrote:
Hi Milan,
on Sat, 24 Feb 2007 09:53:50 +0100, you wrote:
<<snip>>
There are limits in the CompileMethod code such as: nTemps > 63 ifTrue: [^ self error: 'Cannot compile -- too many temporary variables']. nLits > 255 ifTrue: [^ self error: 'Cannot compile -- too many literals variables']. A naive question, does this have to do with the way classes are represented in the VM?
Since I am [in part] responsible for having the above checks in a consistent way, here's my part of the answer:
No. These limits exist because the header field in CompiledMethod has room for just these respective number of bits.
Has nothing to do with, how classes are represented in the VM, but with, how CompiledMethods are represented in the VM.
Thanks for explaining it. Considering my zero level awareness of how image interacts with the VM, and that I never looked at VM code, I should take this to the newbies list .. but anyway. I assume this limit only applies to methods compiled dynamically using ClassDescription>>compile:classified: and friends, not to methods code that I type in browser, is that correct?
No :) There is but one CompiledMethod class so the way you compile doesn't matter.
Also, I wonder how other VMs handle this, is it a performance reason that Squeak (apparently) allocates fixed space to CompileMethod header (instead of maybe making it a linked list)?
You can see the four parts of CompiledMethod better than I can describe them here, in a debugger inspect the thisContext item in the bottom right pane (second from right); in that inspector inspect the CompiledMethod. For example ('abc' at: 0) will start you the debugger, select the line which says UndefinedObject>>DoIt.
The part you refer to is the literals array which is directly indexed by bit quantities in the bytecode; there's no time for chasing a slow linked list ;-)
/Klaus
Milan
-# So I ended up "manually serializing" the ByteArray, esentially
as a
literal String such as '80 75 3 4 20 0 0 0 0 0 76 134 203' in the
small
example above. Then deserialized after the method answered.
Correct. This way you have only one literal in the CompiledMethod, instead of one literals for each value less than -1 or greater than 2 :)
/Klaus
Hi Klaus,
On 2007 February 24 20:14, Klaus D. Witzel wrote: <<>>
No :) There is but one CompiledMethod class so the way you compile doesn't matter.
ok thanks that makes sense, i will also play with just pasting the same method content into browser
Also, I wonder how other VMs handle this, is it a performance reason that Squeak (apparently) allocates fixed space to CompileMethod header (instead of maybe making it a linked list)?
You can see the four parts of CompiledMethod better than I can describe them here, in a debugger inspect the thisContext item in the bottom right pane (second from right); in that inspector inspect the CompiledMethod. For example ('abc' at: 0) will start you the debugger, select the line which says UndefinedObject>>DoIt.
ah that is interesting, I never drilled in thisContext in debugger (or looked at the bytecodes).
The part you refer to is the literals array which is directly indexed by bit quantities in the bytecode; there's no time for chasing a slow linked list ;-)
Thanks for the tips, (much Squeak to learn still),
Milan
/Klaus
Milan
-# So I ended up "manually serializing" the ByteArray, esentially
as a
literal String such as '80 75 3 4 20 0 0 0 0 0 76 134 203' in the
small
example above. Then deserialized after the method answered.
Correct. This way you have only one literal in the CompiledMethod, instead of one literals for each value less than -1 or greater than 2 :)
/Klaus
You might well find
http://www.rowledge.org/tim/squeak/OE-Tour.html
useful as well.
tim -- tim Rowledge; tim@rowledge.org; http://www.rowledge.org/tim Computer Science: solving today's problems tomorrow.
On 2007 February 27 00:57, tim Rowledge wrote:
You might well find
thanks Tim.
useful as well.
tim
tim Rowledge; tim@rowledge.org; http://www.rowledge.org/tim Computer Science: solving today's problems tomorrow.
But I don't think that is what he is asking.
Smalltalk gives us a new way to develop. I often make some class for something, create the display code for it, but I don't get around to making code to instantiate the objects. Instead I just go in a doit or something and make my objects from there and manually insert them where they need to go.
This is a *major* speed increase from any other system I have ever used because in a "cult of the dead" language I have to either (a) create a throw-away method that makes the instances I need or (b) stop my train of thought and go build an interface for making the objects.
But given this power, I use it fairly often. So the question I think he has, and I know I have had is, how do I put this in a format that I can export to another image? In my case it happens to all be web stuff, so I will (at some point) install magma and then I expect to be able to just switch images and everything work.
From: Matthew Fulmer tapplek@gmail.com Reply-To: The general-purpose Squeak developers listsqueak-dev@lists.squeakfoundation.org To: The general-purpose Squeak developers listsqueak-dev@lists.squeakfoundation.org Subject: Re: How to store live objects in Monticello? Date: Sun, 11 Feb 2007 22:27:08 -0700
On Sun, Feb 11, 2007 at 10:07:48PM -0500, Milan Zimmermann wrote:
Hi,
I am trying to do something like this: I have a class LoadProjectTest
that is
essentially a singleton and the LoadProjectTest class is in category eToys-Tests. I'd like to do something like this: In the image where this class originates, I am creating the instance, and setting one instance variable with some value from a local file. I'd like the instance to be stored in Monticello, when I "save" the category. Then, when the MCZ is loaded into another image, the instance would be there, filled with the
value
as created in the originating image.
However, when I load the MCZ into another image, the instance is null; although I was assuming otherwise, that makes sense as the Monticello repository stores code not live objects.
Is it possible to, somehow, to make Monticello to keep the instance, so
it is
deserialized from the MCZ when the MCZ is loaded into the target image?
You would write some class initialization code that creates this instance, and stores it where you see fit. Put your code in the class-side initialize method.
A good example of a code that does just that is the class ExternalType in category FFI-Kernel. Look at the methods in category "class initialization"
Thanks Milan
Hope it helps.
-- Matthew Fulmer -- http://mtfulmer.wordpress.com/ Help improve Squeak Documentation: http://wiki.squeak.org/squeak/808
_________________________________________________________________ Search for grocery stores. Find gratitude. Turn a simple search into something more. http://click4thecause.live.com/search/charity/default.aspx?source=hmemtaglin...
From: "J J" azreal1977@hotmail.com Reply-To: The general-purpose Squeak developers listsqueak-dev@lists.squeakfoundation.org To: squeak-dev@lists.squeakfoundation.org Subject: Re: How to store live objects in Monticello? Date: Mon, 12 Feb 2007 18:18:32 +0000
Smalltalk gives us a new way to develop. I often make some class for something, create the display code for it, but I don't get around to making code to instantiate the objects. Instead I just go in a doit or something and make my objects from there and manually insert them where they need to go.
What I meant here was, I don't create the GUI code for creating the object. I have the methods for making it from a model point of view, but not a pretty display like a web page input or something.
I often use the class browser "instance of" function to find the instance I am looking for and call the methods on it right in the inspector.
_________________________________________________________________ Dont miss your chance to WIN 10 hours of private jet travel from Microsoft Office Live http://clk.atdmt.com/MRT/go/mcrssaub0540002499mrt/direct/01/
El 2/12/07 3:18 PM, "J J" azreal1977@hotmail.com escribió:
But given this power, I use it fairly often. So the question I think he has, and I know I have had is, how do I put this in a format that I can export to another image? In my case it happens to all be web stuff, so I will (at some point) install magma and then I expect to be able to just switch images and everything work.
See class ObjectOut, some ideas could be used. Edgar
__________________________________________________ Preguntá. Respondé. Descubrí. Todo lo que querías saber, y lo que ni imaginabas, está en Yahoo! Respuestas (Beta). ¡Probalo ya! http://www.yahoo.com.ar/respuestas
On Feb 12, 2007, at 4:07 , Milan Zimmermann wrote:
Hi,
I am trying to do something like this: I have a class LoadProjectTest that is essentially a singleton and the LoadProjectTest class is in category eToys-Tests. I'd like to do something like this: In the image where this class originates, I am creating the instance, and setting one instance variable with some value from a local file. I'd like the instance to be stored in Monticello, when I "save" the category. Then, when the MCZ is loaded into another image, the instance would be there, filled with the value as created in the originating image.
However, when I load the MCZ into another image, the instance is null; although I was assuming otherwise, that makes sense as the Monticello repository stores code not live objects.
Is it possible to, somehow, to make Monticello to keep the instance, so it is deserialized from the MCZ when the MCZ is loaded into the target image?
I'm not sure that is a good idea, but in principle, yes, this is possible.
MC is extensible, it asks each class in the package it is going to store for its "classDefinitions". You can return an Array with multiple definitions, not only the MCClassDefinition that is usually returned. You could try to add a special MCDefinition that would represent a serialized instance. Might be quite hard, though.
Much easier would be to use a SAR that can bundle an MCZ with any other files.
- Bert -
Bert, and everyone else who replied, thanks!. A few notes inline:
On 2007 February 12 07:21, Bert Freudenberg wrote:
On Feb 12, 2007, at 4:07 , Milan Zimmermann wrote:
<<snip>>
Is it possible to, somehow, to make Monticello to keep the instance, so it is deserialized from the MCZ when the MCZ is loaded into the target image?
I'm not sure that is a good idea, but in principle, yes, this is possible.
MC is extensible, it asks each class in the package it is going to store for its "classDefinitions". You can return an Array with multiple definitions, not only the MCClassDefinition that is usually returned. You could try to add a special MCDefinition that would represent a serialized instance. Might be quite hard, though.
This is quite intriguing, this sounds like with such extension, MC could be used to maintain code as well as serialized objects! I looked at MCClassDefinition, but it seems at this point the MC extension you described is beyond my reach, time and skill wise it seems :(
Much easier would be to use a SAR that can bundle an MCZ with any other files.
I was trying to avoid shipping files around, and had everything nicely working holding the projects as string in an instance, only to be torpedoed by my not realizing I cannot ship the instance in a MCZ - right now I am trying to convert the contents of the "project in string" into a literate ByteArray that I would paste into a method and return it as String. In this view, using sar, or adding the .pr file into the MCZ manually as you suggested in another email, sounds like less of a hack than what I am doing :)
Thanks for your comments, Milan
- Bert -
squeak-dev@lists.squeakfoundation.org