Hola gente!
Mariano: entiendo tu solucion, interesante. Interesante tambien lo de volcar
en disco objetos no usados, similar a los EJB de entidad, que recuerde.
Andres: jeje... perdon que insista en mi punto, pero todos esos temas de
serializacion, en Java/.NET no los tengo. Es interesante, y veo que cada vez
MAS interesante, comenzar a pensar en implementar VM Smalltalk, Self u
otras, sobre esas tecnologias.
Mariano, a lo de objetos volcados a disco, podria sugerir lo siguiente:
- Pensar un VM con objetos
- Pero los objetos estan en varias maquinas fisicas, algunos en una maquina
M1, otros en una maquina M2
- Una VM en la cloud? ;-)
- Cuando una maquina M1 tiene mucho trabajo, puede pasar los objetos no
usados a un dispositivo mas firme, como disco o base de datos.
- Y ese objeto serializado a disco, en vez de levantar en M1, quizas, la
proxima vez se levante en M2.
- No es fino? ;-) ("chiste solo para argentinos" ;-)
- Tambien podria decir: "la maquina M1 la vamos a apagar, tonche, que
serialize sus objetos", cuando alguna maquina requiera uno de esos objetos,
cualquiera de los otros Mn levantara a ese objeto.
- Podriamos poner, como en implementaciones de NoSql, que una maquina M1, en
realidad, son varias maquinas M1:1, M1:2, ... que van sincronizando sus
objetos, de tal manera que si una maquina se cae, la otra tiene los objetos
en un estado interesante.
Pero ya se, tengo que dejar la cerveza bock, y volver a la light ;-) (a la
Liberty, aca en Argentina).
Back to topic, become.
Ahora, mi solucion al become, es como la de Mariano, pero por excepcion,
digamos, como ya vimos. El pone un objeto intermedio en todos los objetos.
Yo solo en los becomeados. Mas abajo, en este email, hay una solucion (en mi
implementacion) sin objeto intermedio.
Mariano: En el caso que planteabas:
anObject == otherObject
Escribias
si te mando hago anObject become: x y despues hago anObject == otroObject
(suponiendo que otroObject apunta al mismo objeto) eso va a dar
true....execpto que te pongas a modificar todos los bytecodes speciales.
hmmm... a ver si entendi. Eso de "otroObject apunta al mismo objeto" quiere
decir "otroObject apunta al anObject ANTES del become", y por eso te
preocupa que ahora anObject (que representa ahora x) de igual con
otroObject... Bien, dos puntos:
- Tranqui puedo cambiar los bytecode (en mi pet project) porque estan todos
concentrados en pequenias rutinas de .NET, bajo TDD. Una razon para ir por
este camino, es justamente poder hacer cambios que YO entienda y que me
resulte A MI faciles. De ahi que no tome una VM ya existente, que me parece
algo "overwhelming" entenderla para despues hacer cambios rapidos y
consistentes.
- Con respecto al ==, no veo que tendria que cambiar mucho. En el bloque en
ejecucion, mantengo una pila de valores. Cuando evaluo anObject (que ahora
su clase apunta a una clase especial que deriva a x), y lo voy a poner en la
pila, ya envio en la pila a x, porque me doy cuenta que es un objeto
"derivado" a otro. Asi, luego apilo otroObject (que en mi interpretacion de
tu planteo, apunta directamente a x), y cuando el == se aplica a los dos al
tope de la pila, se aplica x == x.
- Disculpen que coloque algo de codigo no Smalltalk ;-), pero en mi solucion
puedo poner:
if (obj.Class.RealObject != null)
executionctx.Push(obj.Class.RealObject)
else
executionctx.Push(obj);
o, quizas ma-mejor, ponerlo en el objeto, una propiedad
RealObject { get { return this.Class.RealObject != null ?
this.Class.RealObject : this } }
quedando en la ejecucion
executionctx.Push(obj.RealObject);
Tengo pensado agregar a cada clase (que tambien es un objeto, pero decorada
con algunas propiedades que puedo invocar directamente en el lenguaje de
implementacion, en este caso C#) un RealObject, que solo tendra sentido para
esas clases especiales. Y solo ocupa lugar para las clases especiales.
Internamente, es una propiedad que devuelve null, y esta sobreescrita en la
clase especial, para devolver el objeto real al que deriva el objeto
"becomeado" ;-)
- Algo asi aplique en un interprete Lisp, cuando tuve que implementar un
valor cuyo calculo es delayed. Al principio pense que tenia que cambiar en
varios lugares, en varias primitivas, poner en varios lados la
resolucion/calculo del valor delayed, pero al final, hubo que cambiar en muy
pocos puntos: cuando realmente se va a usar el valor.
- Si alguna vez llego a compilar todo esto (no creo que me "de el cuero",
pero podria usar Dynamic Language Runtime u otra alternativa), puedo
reemplazar a la pila por variables intermedias. El "setear" una de esas
variables, tendra el mismo tratamiento de arriba: los objetos "derivados" se
"resuelven" al objeto que apuntan.
- Pienso que eso tambien funciona con objetos y otros bytecodes especiales
que se me ocurran, como + (creo que en el Blue Book de Smalltalk-80, el +
era un bytecode especial, mas que un mensaje #+).
- No recuerdo quien escribio por aca, la forma que una companiera de
trabajo/tesista implemento objetos con metodos propios, en vez de metodos de
instancia en la clase. Habia modificado la maquina virtual de Squeak,
agregando a cada objeto un puntero. Cuando lo lei, estuve por escribir esto,
pero no se si aportaba. Ahora, con mas contexto, puedo escribir: Yo hubiera
usado el truco de, ni bien el objeto tenga un metodo para el solito, cambiar
su referencia a su clase original, para apuntar a una nueva clase, solita
para el, que a su vez termina apuntando a la clase original. Habria que
determinar que hacer con la evaluacion de
anObj class
Me imagino poder poner
anObject compileMethod: '.....'
y que quede para eso objeto. Y luego, usarlo como prototipo:
anObject new
crearia un nuevo objeto que tambien apunta a la misma clase especial que
tiene anObj. Hasta imagino que esto se puede hacer en Smalltalk normal, si
vi, por ahi alguna vez
protoObject class: ...
cambiarle la clase a un objeto.
- Volviendo a anObject become: x. No me preocupa mucho que anObject apunte a
una clase especial durante la vida de la imagen. Pero tambien puedo
implementar esto: cada vez que durante la ejecucion, que encuentro en un
slot (variable de instancia, indexada, de algun objeto) al consultarlo para,
seguramente, apilarlo en la pila del contexto de ejecucion, si al examinarlo
veo que es un objeto que deriva a otro "reseteo" ese slot al objeto
derivado, de forma transparente a todo el resto del sistema.
- Como serializo el objeto que esta derivado a otro? Cada objeto tiene un
metodo de serializacion unico. Tengo que modificar ese metodo, para que
serialize el objeto al que fue becomeado. Si, eso, por alguna causa se
complica, otro approach es: al serializar un objeto, me fijo en los slots
que tiene, y si uno de eso es un objeto derivado a otro, me salteo el objeto
intermedio, y serializo el otro (jeje, tambien se contempla que este otro a
su vez sea become a otro... ;-)
- Pero todo esto del become: con la solucion que describi hasta ahora. Hay
otro camino, mas facil, pero que tengo que pensar (la descripcion hasta
ahora, algo lo tenia implementado en un interprete C++, del 2002, pero que
no avanzo mucho). Internamente, cada objeto es un objeto .NET con variables
privadas
private IBehavior class;
private object[] variables; // slots
Entonces, si tengo que hacer anObject become: x, lo que tengo que hacer, es
intercambiar esos valores (en C#), tipo (disculpen tanto C#! ;-):
IBehavior beh = this.class;
this.class = x.class;
x.class = beh;
object[] vars = this.variables;
this.variables = x.variables;
x.variables = vars;
y voila! un objeto become el otro.
Lo unico a contemplar nuevo, es si uno de los objetos tiene variables
indexadas, y el otro no. Mi primera opcion: hacer que todos los objetos,
internamente, tengan un tercer dato, en general en null, pero que ocuparia
el lugar de un "puntero" en TODOS los objetos (ahora, solo lo tienen los
objetos de clases indexadas):
private IBehavior class;
private object[] variables; // slots
private object[] indexed; // variables indexadas
Veo que todo lo de arriba funcionaria en esta implementacion en C# (al
contrario de la solucion que habia escrito para C++), porque esta vez no
segui el camino de Smalltalk clasico de tener objetos con WORDS, POINTERS,
BYTES y demas variantes. En Smalltalk clasico, en las VM clasicas
(corrijanme si no entendi) los objetos tienen diferente implementacion
interna dependiendo si representan bytes, words y asi. Aca no. Todos los
IObject (asi es la interfaz de C# que tienen que cumplir) hasta ahora, en mi
implementacion, tienen la misma estructura interna (excepto el caso de
indexed variables que tendre que evaluar de cambiar).
Como escribia Mariano "Implementar un become: sin object table es lento".
Bueno, en mi implementacion, me aprovecho de la estructura interna para
contrarrestar eso.
Y en caso que los dos objetos en 'anObject become: x' sean de estructura
interna diferente, puedo pasar a la solucion que describi anteriormente.
Todos los IObject tiene al menos la referencia a una clase.
Mariano, pasando a lo que escribiste proxies, no entendi todavia, pero voy a
releer tranquilo tu mensaje, despues pregunto. Pero una cosa:
- Trataste de hacer un unaClase become: MyProxy new ? Cuando luego le
mandas un mensaje a una instancia de unaClase, se rompe todo. Principalmente
porque el proxy es un objeto no una clase (obviemos el detalle que una clase
es un objeto), y la VM para acceder al MethoDict accede DIRECTAMENTE al
offset the las variables. O sea, asume que la clase tiene X cantidad de
variables y que el methodDIct esta en la posicion X.
Hmmm.. Yo no necesito, en mis casos de uso que tengo pensado, combinar
become: con proxy. Tendria que pensarlo, pero no lo necesito. Voy a meditar
si con mi implementacion de become: igual se soluciona o no lo que planteas.
Mi idea de proxy es:
^anObject asProxy
o si quers
^aClass asProxy
es decir, obtener un nuevo objeto que sea un proxy a otro objeto. Y enviar
ese proxy a otra maquina fisica. Hoy, si desde un nodo A invoco a nodo B
con:
nodoB: evaluate '...expression... '
El nodo B lo evalua y devuelve un objeto, que se serializa y reifica en nodo
A. Es la conducta por default. En cambio si
myObj := nodoB: evaluate '(....expresssion... ) asProxy'
lo que viaja es un proxy al objeto que resulto de la evaluacion de la
expresion. Desde ahi, en nodo A, cada vez que se invoca:
myObj msg: par1
se serializan los parametros, y el simbolo del mensaje, se ejecuta en nodo
B, y devuelve algo, desde B a A, o no, tal vez nil.
Si un parametro par1, digamos, no quiero que viaje serializado a B,
tranquilamente:
myObj msg: par1 asProxy
Bien, temas interesantes. Espero que la longitud del email, sea compensada
por lo (espero) interesante de la discusion.
Nos leemos!
Angel "Java" Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez
2010/10/13 Mariano Martinez Peck <[email protected]>
> Mi idea para un become: rápido y para poder experimentar infinito era
> implementar "first class references". Esto es, en vez de que un objeto
> apunte directamente a otro objeto, apunta a un objeto intermedio, y ese
> apunta al objeto de verdad. Obviamente que hay un overhead importante
> (estimamos 15%, por un trabajo similar de Adrian Lienchard), y la memoria
> bueno....practicamente se duplica.
>
> Lo bueno es que el become es simplemtne cambiar ese objeto intermedio y
> listo.
>
> Obviamente que implica bocha de cambios en la VM, esa es la paja jajajaja.
>
> saludos
>
> Mariano
>
> 2010/10/13 Mariano Martinez Peck <[email protected]>
>
>
>>
>> 2010/10/13 Angel Java Lopez <[email protected]>
>>
>>> Hola gente!
>>>
>>> Mariano, interesantisimo tu email... Por ahora (en medio de mi cena),
>>> contesto solo lo sobre become:...
>>>
>>> Recuerdo que cuando vi a Squeak, me causo impresion el tema de como
>>> implementaban become:... se terminaban "bailando la conga", como bien
>>> indicas, no tenian Object Table (desconozco como sera actualmente Squeak, lo
>>> habre visto a fines de los noventa, no estoy seguro).
>>>
>>
>>
>> Sigue siendo asi :(
>>
>>
>>
>>>
>>> Lo que tengo pensado en mi implementacion, en mi pet project (no
>>> implementado todavia), es que become: lo que hace es:
>>>
>>> - Cambiar el "puntero" de un objeto X a su clase.
>>> - Esa referencia, cambia a un nuevo objeto especial en mi implementacion,
>>> que dice, no es una clase cualquiera, es una clase que envia todos sus
>>> mensajes, no al objeto original, sino a otro objeto, el parametro de lo que
>>> era become:
>>> A ver si puedo explicarme...
>>>
>>
>>
>> Entendi perfecto.
>>
>>
>>
>>>
>>> Si
>>>
>>> anObject become: x
>>>
>>> el anObject class cambia su clase a una "clase" especial, que hace que
>>> todo mensaje dirigido a anObject, se deriva al x del become:
>>> En cuanto guarde la imagen, puedo reemplazar toda referencia al anObject
>>> original al nuevo x.
>>
>>
>>
>> Este es el mayor problema de tu solucion para mi. Porque si tenes
>> otroObject apuntando al mismo objeto, no se va a actualizar sino hasta que
>> se guarde la imagen ?
>>
>>
>>
>>> Pero mientras no guarde la imagen, puedo usar el "trick" que describo (no
>>> se si se entendio mi explicacion)
>>>
>>> - Toda referencia a anObject no necesita cambia. Lo que pasa, que
>>> cualquier envio de mensaje a anObject, termina siendo redirigida al x del
>>> become: x.
>>>
>>
>> "todo menesaje" ->>> revisa bien el tema de los bytecodes. Ponele, si te
>> mando hago anObject become: x y despues hago anObject == otroObject
>> (suponiendo que otroObject apunta al mismo objeto) eso va a dar
>> true....execpto que te pongas a modificar todos los bytecodes speciales.
>>
>>
>>>
>>> - Cuando grabe la imagen, en vez de anObject, se graba directamente x,
>>
>>
>> como haces eso?
>>
>>
>>> entonces, al cabo de algunos dias, cuando levante la imagen, toda
>>> referencia a anObject, termina apuntando a x.
>>>
>>> - No tengo problemas con false, true.... terminan funcionando igual (en
>>> mi implementacion son bool false, y bool true, de la maquina VM de abajo, en
>>> este caso, .NET). Es decir, todos los false y true, serializados o no,
>>> funcionan igual.
>>>
>>> - Los symbol, para mi, en mi pet project, son simples String. Como la VM
>>> "de abajo", sea .NET o Java, identifican como "iguales" todo string que
>>> tenga el mismo valor, inclusi cuando se usan como keys en diccionarios. Es
>>> decir
>>>
>>> "pepe".Equals("pepe")
>>>
>>> no importa que "pepe" sea un objeto "distinto" (ocupando otro lugar en la
>>> memoria) de "pepe".
>>>
>>> Y cualquiera "pepe" tiene el mismo HashTag de cualquier otro "pepe".. y
>>> como todo String es inmutable.. .no hace falta distinguir entre Symbol y
>>> String.... por lo menos en mi implementacion (no me supe explicar del todo,
>>> cualquier duda, me preguntan).
>>>
>>> En caso de que fuera necesario, podria implementar Symbol como
>>> "pepe".intern() que transforma un string en su represatacion canonica, de
>>> tal forma que todo "pepe".intern() sea exactamente igual , a cualquier
>>> "pepe".intern()
>>>
>>> Algunos puntos mas:
>>>
>>> - Puedo serializar un metodo compilado, aunque todavia no encontre que
>>> fuera necesario.
>>>
>>> Bueno, escribi rapido, no se si se entendio todo... acabo de ver
>>> #BenditaTv, aca en Argentina, tengan piedad ... ;-)
>>>
>>>
>> jajajaja
>>
>>
>>
>>> Maniana, espero, pregunto sobre dudas que me quedaron del email de
>>> Mariano...
>>>
>>> Vermu con papa fritas, y gud show! ;-) (chiste para argentinos)
>>>
>>>
>>> Nos leemos!
>>>
>>> Angel "Java" Lopez
>>> http://www.ajlopez.com
>>> http://twitter.com/ajlopez
>>>
>>>
>>>
>>> 2010/10/12 Mariano Martinez Peck <[email protected]>
>>>
>>> Hola angel. Quiero opinar sobre 2 cosas que estoy laburando en mi PhD y
>>>> están bastante relacionados. Proxies y serializacion. Uno cree que son
>>>> faciles, pero ninguno de los dos es asi.
>>>>
>>>> Problemas con proxies:
>>>>
>>>> - Acordate que en ST todo son objetos. Por lo tanto el objeto que vas a
>>>> convertir en proxy, puede ser cualquier cosa: Clases, CompiledMethods,
>>>> Closures, etc.
>>>>
>>>> - Cuando en ST nos quedamos sin Object Table, el #become ES LENTO. Se
>>>> tiene que traversar todos los objetos de la memoria. Por esto en Gemstome
>>>> el
>>>> become anda mas rapido (tienen object table)
>>>>
>>>> - Trataste de hacer un unaClase become: MyProxy new ? Cuando luego le
>>>> mandas un mensaje a una instancia de unaClase, se rompe todo.
>>>> Principalmente
>>>> porque el proxy es un objeto no una clase (obviemos el detalle que una
>>>> clase
>>>> es un objeto), y la VM para acceder al MethoDict accede DIRECTAMENTE al
>>>> offset the las variables. O sea, asume que la clase tiene X cantidad de
>>>> variables y que el methodDIct esta en la posicion X.
>>>>
>>>> - Muchas veces el doesNotUnderstand: no es suficiente. En varios casos
>>>> podes usar el hack de poner el methodDict en nil, e implementar
>>>> #cannotInterpret: en la superclase.
>>>>
>>>> - Lo mismo para los CompiledMethod. Poner un proxy no es igual que para
>>>> todo el mundo. Tenes que implementar #run:with:in: y algunos otros
>>>> mensajes mas.
>>>>
>>>> - Hay un montón de mensajes que no van como un bytecode send comun, sino
>>>> con bytecodes especiales. Por lo tanto el dnu o cannotInterpret: pueden ni
>>>> llamarse. Evalua "ProtoObject class" y vas a que anda..sin embargo
>>>> ProtoObject no implementa #class. Y asi como #class hay varios bytecodes
>>>> speciales que te cagan. Mira Smalltalk specialSelectors.
>>>>
>>>> - Tenes que tener mucho cuidado a lo que becomeas con un proxy. Podes
>>>> romper todo muy facil. Hay cosas core que no se pueden reemplazar.
>>>>
>>>> - Debugear es muy dificil porque el mismo debugger manda mensajes para
>>>> imprimirlos o cosas asi entonces te los vuelve a traer jjajajaj
>>>>
>>>> - Si un objecto X tiene como instancia una refencia a un objeto Y, y
>>>> haces un become de X a un proxy, el proxy no va a apuntar a Y. POr lo
>>>> tanto,
>>>> si nadie mas estaba apuntando a Y, el GC te llevó a Y. ImageSegments
>>>> soluciona esto de una manera muy buena.
>>>>
>>>>
>>>>
>>>> Respecto a Serializacion:
>>>>
>>>> - Es muy dificil hacer un serializador que sea rapido. Acá en mi lab
>>>> están haciendo una implementación parecida a Parcels (de VW) y está andando
>>>> bien. Pero hay que tener en cuenta un monton de problemas:
>>>>
>>>> - Ciclos en el subgrafo
>>>>
>>>> - CompiledMethod, ContextPart (y subclases), Process, Continuations, etc
>>>> etc son dificilies de serializar
>>>>
>>>> - endianess (big or blah)
>>>>
>>>> - que haces con nil, true, false, etc? y Symbol ? A la hora de
>>>> cargarlo en la misma image o en otra, no podes crear duplicados, y los
>>>> objetos tienen que apuntar a los ya existentes. Tambien tenes que hacer un
>>>> rehash de los sets cuando los traes nuevamente. etc......etc etc.
>>>>
>>>>
>>>> Bueno, eso nomas. Muchas veces las cosas parecen más faciles no?
>>>>
>>>> saludos
>>>>
>>>> Mariano
>>>>
>>>>
>>>> 2010/10/11 Angel Java Lopez <[email protected]>
>>>>
>>>>> Hola gente!
>>>>>
>>>>>
>>>>> Interesante la discusion del Thread "Blog", pero tambien algo se fue
>>>>> por las ramas... Cambio de titulo en este mensaje.
>>>>>
>>>>> Estuve agregando objetos distribuidos a mi pet project [1], quedo algo
>>>>> asi:
>>>>>
>>>>> http://pastie.org/1213856
>>>>>
>>>>> Tengan encuenta que no tengo libreria de clases de base, asi que tengo
>>>>> que comenzar desde nil subclass:... ';-)
>>>>>
>>>>> Puedo:
>>>>>
>>>>> - Levantar un servidor (tecnologia Remoting .NET), en nodo A.
>>>>> - Levantar un cliente remoto a ese servidor, en nodo B.
>>>>> - Definir una clase en nodo B.
>>>>> - Exportar su definicion de B a nodo A.
>>>>> - Ejecutar desde nodo B algo en nodo A.
>>>>> - Evaluar en nodo A y devolver el objeto serializado (contemplando
>>>>> grafos con ciclos, repeticion de objetos, etc..) a B.
>>>>>
>>>>> Me falta evaluar en nodo A y que el resultado quede en A, viajando a B
>>>>> una especie de proxy, de tal manera que invocando a ese objeto en B, se
>>>>> ejecute el mensaje en nodo A.
>>>>>
>>>>> Mi idea es que si B devuelve un objeto a A, ese resultado viaja
>>>>> completo. Sino, definiria algo como
>>>>>
>>>>> ^host asProxy: result.
>>>>>
>>>>> Tendria que escribir post, pero por ahora, tengo esto para mostrar.
>>>>>
>>>>> [1] http://code.google.com/p/ajtalk
>>>>>
>>>>> Nos leemos!
>>>>>
>>>>> Angel "Java" Lopez
>>>>> http://www.ajlopez.com
>>>>> http://twitter.com/ajlopez
>>>>>
>>>>>
>>>>>
>>>>> --
>>>>> To post to this group, send email to [email protected]
>>>>> To unsubscribe from this group, send email to
>>>>> [email protected]<clubsmalltalk%[email protected]>
>>>>>
>>>>> http://www.clubSmalltalk.org
>>>>>
>>>>
>>>> --
>>>> To post to this group, send email to [email protected]
>>>> To unsubscribe from this group, send email to
>>>> [email protected]<clubsmalltalk%[email protected]>
>>>>
>>>> http://www.clubSmalltalk.org
>>>>
>>>
>>> --
>>> To post to this group, send email to [email protected]
>>> To unsubscribe from this group, send email to
>>> [email protected]<clubsmalltalk%[email protected]>
>>>
>>> http://www.clubSmalltalk.org
>>>
>>
>>
> --
> To post to this group, send email to [email protected]
> To unsubscribe from this group, send email to
> [email protected]<clubsmalltalk%[email protected]>
>
> http://www.clubSmalltalk.org
>
--
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
http://www.clubSmalltalk.org