[Pharo-project] Ideas for CompiledMethod proxies?
leves at elte.hu
Sat Nov 20 12:34:12 CET 2010
On Fri, 19 Nov 2010, Mariano Martinez Peck wrote:
> Hi. I am developing kind of proxies for unused compiled methods. I want to
> detect them, put a proxy instead of them, and swap them to disk. Then, in
> case they are used, I put back the original ones. With this, I want to
> realease memory. This is why I need the proxy objects to be as small as
> Right now, I do something like this:
> aProxy := CompiledMethodProxyReferenceStreamWithFileName installOn:
> ClassWith1Var selector: #foo.
> this will instantiate the proxy, do the ClassWith1Var methodAt: #foo put:
> proxy, write the original compiledMethod that was in #foo into a file,
> and then if I do "ClassWith1Var new foo", then using the #run:with:in I
> load the file from disk and I put back the original method. To know WHICH
> file I have to load, I have to store the fileName in the proxy object.
> In addition, if I DON'T execute the compiled method, but instead I send a
> message, for example:
> (ClassWith1Var >> #foo) literals
> this has to do the same: load and put back the original compiled method. To
> do this, I use the doesNotUnderstand:.
> This is easy to do if I store the fileName in the proxy instance. Right now,
> I am using as fileName this: CLASS >> SELECTOR. For example, in this case,
> the file would be named "ClassWith1Var >> #foo"
> Now.....with this solution, I need create an proxy instance for each
> compiled method, and these instances have also another instance for the
> filename. If I could use the same proxy instance for everybody, the amount
> of memory released would be muuuuch more. So I thought that maybe from the
> context I can "guess" the filename if I use conventions.
> For example, if you do "ClassWith1Var new foo" then in the #run:with:in I
> receive all the information to KNOW that the fileName should be
> "ClassWith1Var >> #foo". So, no problem here.
> But for the second case, suppose "(ClassWith1Var >> #foo) literals", I don't
> see a way to know this. In this case, #literals is intercepted by the
> doesNotUnderstand: of my proxy, and here I should load back the original
> compiled method from disk. The problem is that I cannot know in which CLASS
> and SELECTOR this proxy was put. The only way I know to do this, is to store
> the class + selector in the proxy instance....but it is the same...I will
> need an instance per compiled method. In such case is even easier to
> directly store the fileName.
> Anyway, if someone has a solution or advice on this, I would be appreciated
> that. I tried with thisContext, but it didn't help me.
In a 15MB image all CompiledMethods use only ~3MB, so this technique
won't save much space IMHO.
To minimize the space usage, use SmallIntegers as proxies. To avoid the
(Object >> #hash) literals problem swap back the real method in
MethodDictionary >> #at:ifAbsent:.
A SmallInteger has 31 bits which can easily identify the file index and
position where the swapped out method is. For example you can use 7 bits
for index and 24 bits for position. That allows you to have 128 files
which can hold 16MB data each.
Or you can store a single method in a file, this way the SmallInteger
identifies the file.
More information about the Pharo-project