99
edits
(Getting involved as a programmer: traducido) |
(Nasal Internals for hackers: Intern'ing symbols: traducido) |
||
Line 182: | Line 182: | ||
Si estás interesado en aportar como un desarrollador del núcleo, por favor lee [[Howto:Start core development|Comenzar como desarrollador del núcleo]]. | Si estás interesado en aportar como un desarrollador del núcleo, por favor lee [[Howto:Start core development|Comenzar como desarrollador del núcleo]]. | ||
== Nasal | == Internals de Nasal para hackers: internando símbolos == | ||
'' | ''Aportado por Philosopher'' | ||
Como algunos de ustedes, experimentados hackers de Nasal/C podrán recordar, o incluso aquellos familiarizados con los detalles de los lenguajes de script, los namespaces son sólo tablas de hashing con llaves que representan símbolos - correcto? Ok bien, practicamente, pero cada uno de esos símbolos son únicos en una forma distinta a todos los otros strings que hay ahí afuera: ellos son internos. (El interning es un proceso que toma strings y un diccionario y retorna una cadena coincidente, añadiendo uno si es necesario). Eso significa que las cadenas iguales son sustituidas tal que tienen el mismo puntero, por ejemplo, un string representa todas las instancias de "io", almacenado en un pool/hash de todos los símbolos usados.) Aunque estas cadenas internadas aparecen en tiempo de ejecución en las keys de los namespaces, ellas se crean durante la generación del código (codegen), donde los símbolos (TOK_SYMBOL) que son convertidos a cadenas Nasal, son internadas para obtener la cadena correcta (usando el globals->symbols hash), y son almacenadas en el bloque de constantes de naCode. Desde allí, los symbol-strings son usados para establecer y obtener varios lvalues (ambos simbolos locales/globales y miembros de objeto) en una forma optimizada (esa es la idea principal del ejercicio). Mirando el hash.c, hay varias funciones especializadas que hacen uso de potenciales optimizaciones: | |||
* naiHash_sym ( | * naiHash_sym (busca un símbolo internado) | ||
* naiHash_newsym ( | * naiHash_newsym (añade un símbolo en el primer slot vacío del hashcode) | ||
( | (Hay otro que se parece, naiHash_tryset, pero este no maneja símbolos internados: este usa el método findkey(), el cual a su vez usa el método equals() que comprueba una llave de igualdad más general en vez de simplemente la igualdad de punteros.) | ||
Lo primero, naiHash_sym, es bastante claro y el supremo ejemplo de la optimización: este corre los slots del hashcode, comprobando sólo la igualdad de punteros (nótese que el hashcode de los símbolos internados son calculados durante la internación, por lo que es otro paso que no es necesario realizar en tiempo de ejecución). naiHash_newsym es otra buena optimización pero un poco problemática, debido a que asume que la llave ya no existe. Básicamente se utiliza para añadir otro argumento como una llave local, pero no le importa si ya existe, sólo ve un slot ocupado y continúa. Considera el siguiente ejemplo que ilustra la llamada con un argumento en un hash que ya tiene la llave del argumento en él: | |||
<syntaxhighlight lang="nasal"> | <syntaxhighlight lang="nasal"> | ||
Line 203: | Line 203: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Esto mostraría: | |||
<pre> | <pre> | ||
arg | arg | ||
Line 210: | Line 210: | ||
</pre> | </pre> | ||
Esto muestra que la llave está siendo establecida dos veces (lo cual viola la condición de las tablas de hashing): una vez como argumento y otra vez para crear una llave existente en el espacio de nombres. El primer set es el que está siendo recogido (por ejemplo, el arg en {arg:nil} versus el arg... que iguala []). Y este comportamiento persiste incluso a través del redimensionado: hashset() (el cual es usado para reiniciar un hash después de la redistribución) sólo sigue añadiendo llaves en slots vacíos, tal que el número de llaves no cambia (incluso si hay varias de la mismas llaves). | |||
Por esta razón, sugeriría modificar el naiHash_newsym para comprobar la igualdad de punteros de las llaves antes de continuar; de esa forma los símbolos no son "pisados" como acá. (Por favor considera que si "arg" existe en el hash como un no-internado, entonces éste será pisado de todos modos; tener que buscar símbolos no internados principalmente violaría el punto de la optimización en este paso, y a la larga realmente no importa.) Yo sostendría que encontrar una llave existente (¡unas simples comparaciones de punteros!) generalmente sería más eficiente, porque el hash nunca necesitaría ser redimensionado si encuentra uno existente, mientras que la vieja versión añadiría de todas formas. (Creo que una vez conté más de cien símbolos "arg" in the namespace __js0 desde el continuo lanzamiento de vínculos, lo cual obviamente no es bueno.) | |||
Continúa leyendo en [http://forum.flightgear.org/viewtopic.php?f=30&t=21308&p=193935#p193935]. | |||
== FlightGear addons and mods == | == FlightGear addons and mods == |
edits