Вы находитесь на странице: 1из 9

Cómo trabaja FoxPro internamente

   
Visual Foxpro en Español

Visual Foxpro Introducción Historia Instalación Visual FoxPro Advanced Otros temas Vfp Ayuda  

Vfp 9.0

Requisitos Cómo trabaja FoxPro internamente


Preguntas frecuentes 10/03/2020
Actualizaciones Vfp 9.0  
Documentación Vfp9 SP2
Autor: Christof Wollenhaupt, Foxpert
Instalar parches Vfp 9 SP2
Índice
Artículos Visual FoxPro temas

FoxRibbon Camf FoxPro desde adentro


El índice de la tabla de nombres (NTI)
Lenguajes de programación Variables, Matrices y Objetos
Administración de la memoria
Historia de la microinformática
Rushmore
Computadora Palabras Finales
Descarga
Emuladores
Referencias
Sistema Operativo
 
Software

  FoxPro desde adentro

Érase una vez, que el xBase no era un lenguaje de programación, era una herramienta para recuperar y para manipular automáticamente datos. Los usuarios de las
herramientas xBase no eran principalmente desarrolladores; eran expertos en una variedad enorme de diversas áreas que utilizaban FoxBase, dBase, y herramientas similares
para manejar sus datos. El xBase fue mejorado constantemente y finalmente desarrollado como un verdadero lenguaje de programación. FoxPro se convirtió en un entorno
profesional de desarrollo que alcanzó sus alturas con FoxPro 2.5/2.6. En 1995 el paradigma de la herramienta cambió otra vez. Un lenguaje de programación procedural se
convirtió en una herramienta orientada a objetos que continúa desarrollándose como un diseño basado en componentes.

Visual FoxPro no es sólo un entorno orientado a objetos como Delphi o Visual Basic.NET. Visual FoxPro todavía contiene sus raíces. Sólo intente hacer funcionar un programa
de Turbo PASCAL 3.0 en Delphi 7.0. ¿Qué tal sus programas de GW-BASIC en Visual Basic.NET? ¿Pero Foxbase? Hasta hoy puede hacer funcionar código sin cambios en Visual
FoxPro que ha escrito en los años ochenta. La salida por pantalla no luce tan agradable, pero todavía puede ejecutar código en VFP 8 casi 20 años después de que lo ha escrito.

Visual FoxPro es casi totalmente compatible hacia atrás. Pensando sobre esto, significa que mucho del código en FoxPro y FoxBase es todavía parte de Visual FoxPro. Esto
significa que la orientación a objetos se sienta encima de FoxPro, y no viceversa. Muchos comportamientos extraños de Visual FoxPro llegan a ser solamente explicables si
piensas cómo habrías hecho algo en FoxBase, sólo para darte cuenta de que Visual FoxPro no lo hace distinto.

Una advertencia por adelantado: Los siguientes artículos intentan describir cómo trabaja internamente Visual FoxPro. Los interiores reales de FoxPro son propiedad intelectual
de Microsoft y no se divulgan públicamente. Cada uno de los que realmente saben como trabaja FoxPro internamente esta impedido para hablar de esto firmando un Acuerdo
de No-Divulgación (NDA). He recogido la siguiente información de una variedad de fuentes públicas. Cierta información está en la biblioteca MSDN que Microsoft publica
trimestralmente (algunos items existen solamente en versiones más viejas de la biblioteca MSDN). Otra información viene del código de ejemplo que Microsoft envía. La
mayoría de las piezas, sin embargo, vienen de pruebas y de observaciones, no sólo de mí, sino de muchos, muchos desarrolladores en varios foros. Especialmente las
diferencias en el comportamiento de varias versiones permiten hacer conclusiones de la estructura interna de VFP. Algunas de las estructuras siguientes se han extendido en la
versión más reciente de FoxPro.

El índice de la tabla de nombres (NTI)

En Visual FoxPro podemos nombrar varios items. A esos items, Visual FoxPro les asigna algo llamado un nombre. Estos items son variables (no propiedades), nombres de
matrices, procedimientos, funciones, alias de tablas, nombres de campo y objetos (no clases). Cada uno de estos elementos tiene una etiqueta y un alcance. La visibilidad
(alcance) de una variable, por ejemplo, depende de su tipo, mientras que el alcance de un alias es la sesión de datos. Un nombre de campo debe ser único en una tabla y los
procedimientos son limitados en alcance a un archivo de programa.

https://visualfoxpro.webcindario.com/visual_foxpro/articulos/secretos_ocultos_vfp/como_trabaja_vfp_internamente.php[26/03/2020 0:36:56]
Cómo trabaja FoxPro internamente

Siempre que se crea una variable, se abre una tabla, y así sucesivamente, Visual FoxPro crea una nueva entrada en una lista interna, la Tabla de Nombres. La posición dentro
de esta lista es el Índice de la Tabla de Nombres - o NTI para abreviar. En esta lista, a cada nombre se el asigna un número único entre 1 y 65.000, porque se mantiene como
valor de 16-bits. Hay sólo una lista global. Esta es la razón por la cuál se pueden crear hasta 65.000 variables solamente. Puesto que los alias y los nombres de objetos (hasta
Visual FoxPro 6.0) también se incluyen en esta lista, el número real de variables es reducido por el número de objetos instanciados y áreas de trabajo asignadas.

El manejo de esta lista se ha optimizado en las distintas versiones de FoxPro. Cuando se libera un nombre cerrando una tabla o porque no se necesita más una variable, Visual
FoxPro no quita la entrada inmediatamente. Solamente marca la entrada como inválida, como se hace con los registros eliminados.

Los items finalmente son quitados por un proceso llamado Garbage Collection (recolección de basura). Este término se refiere al proceso de quitar entradas inválidas de las
listas, liberar entradas desactualizadas de la caché, compactar la memoria moviendo bloques de memoria alrededor, comprobando el acceso a los ficheros temporales, y así
sucesivamente. Visual FoxPro ejecuta la recolección de basura en su bucle ocioso (idle loop). Se entra en este bucle siempre que Visual FoxPro está en una condición de espera
causada por READ, READ EVENTS, INKEY() o WAIT WINDOW. Esto sigue siendo cierto si se utiliza el comando con las opciones de no esperar (NOWAIT). Se puede utilizar este
truco para forzar a Visual FoxPro a limpiar la memoria usando un WAIT WINDOW "" NOWAIT.

No fue hasta Visual FoxPro 7.0 que SYS(1104) se hizo en la documentación aún cuando la función está disponible desde FoxPro 2.6, por lo menos. SYS(1104) dispara
manualmente una recolección de basura. No es lo mismo que el bucle ocioso, aunque, como en el bucle ocioso Visual FoxPro hace más que ejecutar la recolección de basura,
como adicionalmente procesar los mensajes de Windows. Durante la ejecución del programa, Visual FoxPro no está en un bucle ocioso y por lo tanto no realiza una recolección
de basura. Hasta Visual FoxPro 5.0 esto tenía el efecto de que más y más entradas en la tabla de nombres se marcaban como inválidas, pero no se liberaban.

Esto tenía consecuencias de gran envergadura en la performance, pero también en la estabilidad. Cada vez que una nueva entrada se agrega a la tabla de nombres, Visual
FoxPro tiene que buscar todas las entradas existentes para encontrar nombres conflictivos. Para las variables esto implica comprobar si existe una nueva variable con un
alcance más bajo, porque no se puede, por ejemplo, crear una variable PÚBLICA cuando existe una variable LOCAL con el mismo nombre. Para los alias esto implica verificar
que el nombre del alias no esté usado en la sesión actual de datos. Este proceso de búsqueda ha causado la degradación exponencial de la performance. Mientras que se
podría medir la creación del primer objeto en milisegundos o incluso nanosegundos, a Visual FoxPro le tomó varios minutos para crear el objeto 60,000.

Las aplicaciones que nunca alcanzaban un estado ocioso, como las rutinas de importación o los proveedores de servicio, se hacían más lentos cuanto más tiempo funcionaban.
Algunas funciones, también, exigían una nueva entrada en la tabla de nombres, como la función REQUERY al recargar una vista. La desaceleración no era el único problema.
Cuanto más se acercaba una aplicación al límite, más inestable se volvía. Si se era afortunado, Visual FoxPro indicaba un error de “demasiados nombres”, pero generalmente
simplemente se colgaba.

Visual FoxPro 6.0 mejoró perceptiblemente este comportamiento. Cuando el número de items en la tabla de nombres se acerca al 95% del límite, Visual FoxPro inicia
automáticamente una recolección de basura. En un programa que crea 65.000 objetos se nota como un descanso más largo al crear ese objeto.

Una mejora importante vino en Visual FoxPro 7.0. Todas las versiones anteriores contaban objetos. Cuando se crean dos etiquetas

LOCAL loLabel1, loLabel2


loLabel1 = CreateObject("Label")
loLabel2 = CreateObject("Label")

Visual FoxPro ajusta la propiedad NAME. La primera etiqueta se nombra “Label1”, para la segunda etiqueta Label2.Name resulta en “Label2”. Para hacer que esto suceda,
Visual FoxPro coloca cada objeto en la tabla de nombres. La consecuencia es que cada creación de objeto dura más que la anterior. Se puede saltear esto hasta cierto grado
asignando un nombre único como SYS(2015) en el evento Init. No obstante, este comportamiento limita el número de los objetos que pueden ser instanciados a 65.000. En
Visual FoxPro 3.0 a 6.0 no se pueden crear más de 65.000 objetos incluyendo todos los objetos que estén en formularios. Cuando se ha alcanzado ese límite, no se puede
incluso abrir al diseñador de formularios ya que también intenta crear objetos.

Visual FoxPro 7.0 y 8.0 no hacen ninguna búsqueda de nombre único cuando se crean objetos con CREATEOBJECT () o NEWOBJECT (), ni colocan objetos en la tabla de
nombres. Por lo tanto se pueden crear lejos más de 65.000 objetos… e incluso más rápidamente que en Visual FoxPro 6.0 también. La desventaja es que los nombres de
objetos no son mas únicos. Un pequeño precio a pagar.

Variables, Matrices y Objetos

Una de las consultas más frecuentes que hacen los desarrolladores que acaban de aprender que Visual FoxPro puede manejar solamente hasta 65.000 variables es si eso se

https://visualfoxpro.webcindario.com/visual_foxpro/articulos/secretos_ocultos_vfp/como_trabaja_vfp_internamente.php[26/03/2020 0:36:56]
Cómo trabaja FoxPro internamente

aplica a los elementos de matrices también. La respuesta es un NO definitivo. Una matriz cuenta como una sola variable, no importa cuántos elementos contenga. Porque el
número de elementos se limita a 65.000 también, se pueden crear 65.000 matrices con 65.000 elementos cada una, como máximo. Incluso en Visual FoxPro se pueden
almacenar masas de datos en memoria. Debido a razones de performance, ninguna aplicación se acerca a estos límites siquiera. La razón de todas estas limitaciones es la tabla
de nombres, de nuevo. Realmente, Visual FoxPro sólo sabe tratar con variables - simples variables, eso es todo. El soporte de matrices, y posteriormente objetos, ha sido
acomodado en este diseño.

¿Pero qué es una variable en Visual FoxPro? Las variables en FoxPro pueden almacenar valores de cualquier tipo de datos. Sin embargo, como Visual FoxPro está escrito en C
en sí mismo, las variables de FoxPro también tienen que ser almacenadas en formato C hasta cierto punto. Visual FoxPro almacena variables en estructuras de C. Aún cuando
la estructura siguiente proviene del kit de construcción de bibliotecas (SDK), está probablemente cerca de qué utiliza internamente Visual FoxPro, si no es incluso idéntico:

typedef struct {
    char ev_type;
    char ev_padding;
    short ev_width;
    unsigned ev_length;
    long ev_long;
    double ev_real;
    CCY ev_currency;
    MHandle ev_handle;
    unsigned long ev_object;
   } Value;

Además del tipo, hay una entrada para cada tipo de dato soportado. Visual FoxPro utiliza diversos campos dependiendo de qué tipo de datos deba ser almacenado. La
estructura explica porqué las cadenas pueden contener cualquier carácter (porque su longitud se almacena por separado) y cómo Visual FoxPro se ocupa del número de
posiciones decimales en valores de coma flotante para permitir diferencias entre 1.0 y 1.00. Las cadenas y los objetos reales no se almacenan directamente en esta estructura
porque su tamaño puede variar ampliamente. Para acceder a cadenas, Visual FoxPro utiliza algo llamado manejador de memoria que será explicado en un momento. Los
objetos se identifican usando un número de 32-bits no muy documentado. Puede ser que sorprenda que las matrices no están siquiera mencionadas.

Cada vez que un programa crea una nueva variable de memoria, Visual FoxPro asigna un bloque de la memoria con la estructura antedicha. Su dirección tiene que ser
almacenada en alguna parte, justo como el nombre, que no es parte de la estructura anterior. Almacenar esta información es el trabajo de la tabla de nombres. Cada entrada
en la tabla de nombres contiene además de nombre y alcance, los detalles del tipo de la entrada (variable, campo, alias, etc.) y su localización en memoria. La lista se limita a
65.000 entradas, por lo tanto, el límite máximo de variables.

Una matriz no se puede almacenar en una sola estructura, sin embargo. Cada elemento de matriz se almacena en una estructura como una sola variable. Ésta es la única
manera de poder almacenar los items de varios tipos de datos en una sola matriz. En la tabla de nombres Visual FoxPro crea una sola entrada para la matriz entera. El
siguiente ejemplo setea todos los elementos en la matriz a NULL:

LOCAL laArray[3]
laArray = .NULL.

Esta sola entrada es la que es usada para pasar una matriz por referencia. La matriz real, por otra parte, es una simple tabla de lista que contiene punteros a todos los
elementos individuales. La entrada de matrices en la tabla de nombres real contiene un puntero a esta lista. No hay obviamente manera de tener acceso directamente a un
elemento de la matriz como se puede tener acceso a una variable. Al pasar el índice de la tabla de nombres (NTI) que Visual FoxPro utiliza para identificar unívocamente una
entrada en la tabla de nombres a una función que devuelva un elemento de la tabla de nombres, esta función podría solamente devolver la entrada para la matriz entera. Otra
función recibe esta entrada y devuelve un elemento particular.

Los objetos se almacenan de manera similar. El valor en la estructura es la dirección de otra tabla de nombres. Para cada objeto Visual FoxPro parece crear una nueva tabla de
nombres. Probablemente ha sido elegido ese camino porque la tabla de nombres ya maneja nombre y alcance. Las propiedades en Visual FoxPro son realmente variables que
se mantienen en un lugar oculto. Más asombrosamente, esto es así para los métodos, que son también variables. Por esta razón no se puede crear una clase que tenga más de
65.000 métodos, propiedades, y eventos.

Este diseño tiene muchas ventajas ya que de otra manera las matrices y las propiedades comerían rápidamente el espacio disponible de la tabla de nombres. La desventaja
más obvia, sin embargo, es pasar parámetros por referencia usando el carácter @. En este caso, Visual FoxPro no pasa una copia del valor como lo hace normalmente, sino
simplemente el NTI, el índice de la tabla de nombres. A la función que llama se le pide amablemente que ponga el resultado en la variable número x. Una matriz, sin embargo,
tiene solamente un simple índice de la tabla de nombres. No hay posibilidad tampoco de especificar en qué elemento debe ser escrito el resultado. Por lo tanto, se puede pasar

https://visualfoxpro.webcindario.com/visual_foxpro/articulos/secretos_ocultos_vfp/como_trabaja_vfp_internamente.php[26/03/2020 0:36:56]
Cómo trabaja FoxPro internamente
solamente una matriz entera por referencia. En Visual FoxPro es imposible pasar un solo elemento de matriz por referencia. Se tiene que copiar el elemento en una variable,
pasar una referencia a esa variable y actualizar el valor en la matriz.

Igual se aplica a las propiedades de objetos. En teoría, no se puede pasar una propiedad por referencia porque es una parte integral del objeto. Pasar una propiedad por
referencia, por lo tanto, rompería la encapsulación. La respuesta verdadera, sin embargo, es que una propiedad no tiene una entrada dedicada en la tabla de nombres y
pasarla por referencia es por lo tanto imposible. Son afectadas especialmente por este diseño las propiedades matrices. Ni las matrices ni las propiedades se pueden pasar por
referencia. Por lo tanto no se tiene ninguna otra posibilidad que copiar la matriz en una variable local, pasarla en lugar de la otra, y copiar la matriz entera nuevamente usando
ACOPY() para ambas maneras. Combinado con los métodos access y assign este método tiene aún más desventajas que sólo reducir la velocidad de ejecución.
Afortunadamente, Visual FoxPro 8 agregó las colecciones que lucen como una matriz, pero pueden ser fácilmente pasados alrededor.

El acceso a las variables ha sido optimizado por Visual FoxPro. Ya al compilar un programa Visual FoxPro traduce nombres en valores enteros fáciles de manejar. Las líneas:

LOCAL lcName, lcZIP


? lcName

Se convierten en el pseudo código siguiente durante la compilación:

LOCAL #1, #2
? #1

En el archivo FXP resultante todas las variables se enumeran al final del archivo. Dentro del código compilado, se utilizan valores de 16 bits que indican la posición en la lista.

0x00000000 : FE F2 FF 20 02 01 00 00 00 B0 00 00 00 8F 00 00 þòÿ .....°...�..


0x00000010 : 00 21 00 00 00 00 00 00 00 00 00 00 00 00 00 00 .!..............
0x00000020 : 00 00 00 00 00 00 00 94 11 00 00 00 00 25 00 00 .......”.....%..
0x00000030 : 00 00 00 00 00 00 00 00 00 56 00 00 00 03 00 00 .........V......
0x00000040 : 00 50 00 00 00 C2 8B 56 2B 11 00 00 00 FC 18 00 .P...‹V+....ü..
0x00000050 : 0B 00 AE F7 00 00 07 F7 01 00 FE 0A 00 02 F8 03 ..®÷...÷..þ...ø.
0x00000060 : 01 F7 00 00 FE 03 00 55 02 00 06 00 4C 43 4E 41 .÷..þ..U....LCNA
0x00000070 : 4D 45 05 00 4C 43 5A 49 50 B1 00 A1 00 31 00 00 ME..LCZIP±.¡.1..
0x00000080 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 65 ...............e
0x00000090 : 3A 5C 74 65 6D 70 5C 00 76 61 72 2E 66 78 70 00 :\temp\.var.fxp.
0x000000A0 : 65 3A 5C 74 65 6D 70 5C 76 61 72 2E 70 72 67 00 e:\temp\var.prg.
0x000000B0 : 00 29 00 00 00 8F 00 00 00 00 00 00 00 09 00 00 .)...�..........
0x000000C0 : 00 00 00 00 00 00 00 00 00 .........

Es reconocible inmediatamente que el código real empieza en la posición 0x50 y finaliza en 0x64. Lo siguiente lista el significado de la parte en negritas del archivo:

0B 00 length of first line (11 bytes)


AE code for the LOCAL statement
F7 expression: a variable follows
00 00 variable #1 (lcName)
07 comma in list of parameters
F7 another variable follows
01 00 variable #2 (lcZIP)
FE end of expression

0A 00 length of second line (10 bytes)


02 F8 03 code for the ? statement
01 number of parameters: 1
F7 expression: a variable follows
00 00 Variable #1 (lcName)
FE end of expression

https://visualfoxpro.webcindario.com/visual_foxpro/articulos/secretos_ocultos_vfp/como_trabaja_vfp_internamente.php[26/03/2020 0:36:56]
Cómo trabaja FoxPro internamente
Al ejecutar tal programa, Visual FoxPro crea una lista que asigna cada variable en el código al índice de la tabla de nombres. Internamente, FoxPro llama una función que
recibe el índice como parámetro y devuelve una estructura completada conteniendo el valor. Como se puede ver la longitud del nombre de la variable no es relevante. No se
utiliza en el código real del programa, sólo está enumerada una vez al final. Los nombres de variables más largos (y a menudo más legibles) por lo tanto no tienen ningún
efecto significativo en la velocidad de ejecución.

Una vez más la situación es diferente al observar las matrices. Las funciones internas para determinar el NTI pueden todavía ser utilizadas, pero Visual FoxPro no sabe hasta
entonces que esta variable es una matriz. En el paso siguiente los parámetros índice se evalúan y se pasan a otra función que copie la estructura del valor para cargar un
elemento de la matriz. Acceder a un elemento de una matriz, por lo tanto, es siempre más lento que acceder a una variable. Para complicar más las cosas, Visual FoxPro
soporta corchetes y paréntesis para las matrices así como para funciones. No hay distinción clara entre los dos de antemano. Como las matrices tienen precedencia, Visual
FoxPro tiene que comprobar para saber si hay una matriz del mismo nombre en cada llamada de función.

Es más difícil para los accesos a los objetos. Una vez más los nombres de propiedad se convierten a números usando el mismo algoritmo. Sin embargo, object1.name es casi
igual que object2.name. Si Visual FoxPro encuentra código como este:

LOCAL loLabel
loLabel = CREATEOBJECT("Label")
? loLabel.Caption

No es difícil resolver la referencia a loLabel en la tercera línea. La función para obtener un valor para la NTI devuelve una estructura que representa el objeto entero. El paso
siguiente es considerablemente más complejo. Los objetos mantienen su propia tabla de nombres. La lista disponible para convertir nombres en el NTI es inútil. Por lo tanto,
Visual FoxPro tiene que localizar el nombre en el código (CAPTION, en este ejemplo) en la tabla de nombres privada y cargar la estructura allí. Esto requiere la resolución del
nombre real en vez de usar el valor de índice y los resultados no se pueden poner en la caché como para los valores simples. Por lo tanto, acceder a una propiedad de objeto
es incluso más lento que acceder a una variable o un elemento de matriz.

Eso explica porqué WITH…ENDWITH puede aumentar la performance tan notablemente. Simplemente mantiene la estructura de valores en memoria y hace innecesario
resolver la primera parte. Esto también explica porqué tiene mucho más sentido guardar referencias profundas en una variable local. Esa variable se puede resolver mucho
más rápidamente que una propiedad.

Administración de la memoria

Ni un bit menos complejo es el manejo de la memoria en Visual FoxPro. Ha habido dos versiones de FoxPro 2.x, una versión de 16 bits y otra de 32 bits que utilizaban un
extensor del DOS. El extensor del DOS incluso cambió entre 2.0 y 2.6. Para las aplicaciones DOS hay varios tipos de memoria, que son todos manejados por diversos
administradores de memoria. Están XMS y EMS como modelos concurrentes de memoria. Está HIMEM el cuál extendía la memoria convencional y DPMI, el interfaz de modo
protegido do DOS, que todavía es soportado por Windows. Todos estos tipos de memoria han sido soportados por varias versiones de FoxPro; todavía hay código que
permanece en Visual FoxPro, no obstante, no activo. Por ejemplo, la mayor parte de las funciones indocumentadas de la memoria entre SYS(1001) y SYS(1016) todavía
trabajan.

Windows agregó modelos de memoria más modernos dependiendo de la versión de Windows. Incluso en la versión actual de 32-bits de Windows hay varias clases de tipos de
memoria disponibles. Los tipos más conocidos son la memoria física y la de intercambio (swap). La memoria puede ser dividida aún más granularmente, como en montones
locales y globales, memoria virtual, memoria mapeada y muchos tipos más.

Encima de la memoria física y de varios modelos de memoria implementados por el sistema operativo, Visual FoxPro tiene su propia manejo de la memoria. Visual FoxPro
distingue cinco tipos de memoria: pila, memoria intermediaria fuera de la pantalla, grupo de manejadores y ficheros temporales. El apilado se utiliza para los procesos
temporales y no es relevante para los desarrolladores de Visual FoxPro. Generalmente, se nota el apilado en condiciones de error tales como “insufficient stack space” o
“Mismatched PUSHJMP/POPJMP call”. Solamente los desarrolladores de C/C++ que escriben un FLL tienen que tratar con las pilas.

El grupo de manejadores (handle pool) es la administración real de la memoria de Visual FoxPro. Para hacer frente a todos los distintos módulos de memoria, FoxPro
implementa un modelo inteligente que prohíbe el acceso directo a la memoria. Debido a este modelo, FoxPro puede ser portado hacia hacia otras plataformas que utilizan
modelos de memoria enteramente distintos, tales como Windows, Unix o el Mac.

Hay muchos datos para mantener en memoria. Esto incluye variables, menúes, ventanas, cadenas, pero también objetos, definiciones de clases, formularios, y mucho más.
Cada vez que Visual FoxPro exige memoria, el administrador de memoria es llamado con el tamaño del bloque de memoria deseado. En vez de devolver una dirección, sin
embargo, está devolviendo una manejador de memoria. Se puede imaginar esto como una clase de clave primaria. Siempre que un programa desee tener acceso a esta
memoria debe bloquearla antes, como se bloquea un registro. Después de eso se puede determinar la dirección usando una función interna. Una vez accedida la memoria el
código tiene que desbloquear el manejador, como desbloquear un registro.

https://visualfoxpro.webcindario.com/visual_foxpro/articulos/secretos_ocultos_vfp/como_trabaja_vfp_internamente.php[26/03/2020 0:36:56]
Cómo trabaja FoxPro internamente

El propósito de estos bloqueos es diferente al de los registros, sin embargo. El acceso paralelo a la memoria es lo que debe ser prevenido, moviendo el bloque alrededor.
Cuando los bloques de la memoria son constantemente asignados, la memoria libre se fragmenta con el tiempo. Lo mismo se aplica a los discos duros cuando se crean y
eliminan archivos. Después de funcionar un largo tiempo esto podría conducir a la situación de que hay bastante memoria disponible, pero no hay ningún bloque que sea lo
bastante grande como para almacenar los datos solicitados. Esto sería fatal para un sistema de base de datos que debe funcionar desatendido por días o semanas, ya que esa
situación colgaría el sistema.

Para evitar que esto suceda, la recolección de basura debe mover bloques de memoria alrededor. Internamente, Visual FoxPro realiza cierta clase de defragmentación mientras
que está ocioso. Pero la defragmentación no es la única razón para implementar este modelo. Además, la memoria no está siempre fácilmente disponible. Por ejemplo, en DOS
la memoria axtendida debe ser mapeada a la memoria convencional antes que la versión extendida de FoxPro pueda accederla. Cuando un manejador de FoxPro es bloqueado,
las funciones de administración de FoxPro pueden tener el cuidado de asegurarse de que este bloque de memoria está fácilmente disponible para el programa que llama.
Cuando está desbloqueado, FoxPro puede mover el bloque de nuevo a su posición original.

Parte del grupo de manejadores es visible a nosotros los desarrolladores con el comando LIST MEMORY, pero no todos los manejadores. Internamente Visual FoxPro hace uso
intensivo de manejadores también. Todas las ventanas de edición, por ejemplo, son manejadores también. Por lo tanto podemos utilizar ACTIVATE WINDOW no sólo para
activar nuestras propias ventanas, sino todas las ventanas proporcionadas por FoxPro incluyendo las barras de herramientas. En Visual FoxPro el grupo de manejadores es
limitado solamente por la memoria física y virtual disponible.

La función SYS(1001) devuelve el tamaño máximo del grupo de manejadores. La función indocumentada SYS(1011) devuelve el número de manejadores asignados. Esta
función debe devolver el mismo valor antes y después de una llamada de función. Cualquier otro valor indica un escape de memoria. SYS(1016) devuelve el tamaño de la parte
asignada del grupo de manejadores. SYS(1104) inicia manualmente una recolección de basura. Esta función está documentada oficialmente desde Visual FoxPro 7.0. Todas
estas funciones devuelven varios valores cuando son ejecutadas en la ventana de comandos, porque la ventana de comandos entra permanentemente en el bucle ocioso y por
lo tanto ejecuta una recolección de basura. Algunas funciones se filtran en los manejadores usados internamente, otras no hacen eso. No obstante, estas funciones son buenos
indicadores para el uso de la memoria.

Básicamente, todo lo que no es temporal se almacena en el grupo de manejadores en alguna parte. Esto incluye transacciones y los cambios sin comprometer en un buffer
intermedio que deben ser escritos nuevamente con TABLEUPDATE().

El grupo de páginas (page pool) es el área de la memoria que es controlada por SYS(3050). Visual FoxPro guarda en ella mapas de bits creados por Rushmore y la utiliza para
guardar en caché las tablas y los índices. Esta parte de la memoria es principalmente responsable de la impresionante velocidad de Visual FoxPro. Todo lo que se lee en disco
es cacheado aquí para una reutilización posterior. Se puede controlar el tamaño máximo de esta área de memoria por separado para el primer plano (foreground) y para el
proceso de fondo (background). Eso significa que dependiendo de si el usuario está trabajando con su aplicación, o no, usted puede decirle a Visual FoxPro que utilice menos o
más memoria. Esa memoria no es asignada inmediatamente, sino que se asigna según lo necesitado. Se puede especificar un valor enorme sin tener que temer que esta
cantidad de memoria se vaya inmediatamente.

SYS(3050) intenta asignar memoria en Windows que no se intercambie al disco. Sin embargo, no hay garantía. Los qué podría sucederle es que Visual FoxPro haya asignado la
memoria para propósitos de caché que existe solamente en el disco duro local como memoria virtual. Obviamente, esto tiene un impacto absoluto en la performance.
Reduciendo el valor de SYS(3050) inmediatamente libera toda la memoria superflua. Como el valor mínimo es 256 KB (no MB), se puede utilizar el código siguiente para liberar
memoria más allá de 256 KB:

lcMemory = Sys(3050,1)
Sys(3050,1,1)
Sys(3050,1,Val(lcMemory))

Aún cuando es verdad que se tiene control completo sobre el grupo de páginas, ésta es solamente la mitad de la verdad en cuanto al consumo de memoria concierne. Si Visual
FoxPro es de la opinión que necesita más memoria, por ejemplo, para almacenar un mapa de bits de la optimización, entonces no vacila en crear ficheros temporales si el
grupo de páginas no es suficientemente grande. FoxPro continúa funcionando, aunque el valor de SYS(3050) sea demasiado bajo, eventualmente con la misma velocidad,
quizá más lento, o aún más rápidamente. Esto depende de qué clase de memoria se asigne a Visual FoxPro y qué dispositivo sea más rápido. ¿Es el que está usado por
Windows para la memoria virtual o el que es utilizado por Visual FoxPro para almacenar ficheros temporales? Como Windows, también puede almacenar en caché el acceso a
los archivos TMP, puede ser que note repentinamente que su aplicación funciona más rápidamente.

Qué directorio se utiliza para los ficheros temporales depende de los ajustes del registro, el TMPFILES=… que elija (no TEMPFILES!) y varios ajustes en Windows. Bajo
circunstancias normales puedes utilizar SYS(2023) para descubrir el directorio temporal. A veces, sin embargo, Visual FoxPro puede silenciosamente cambiar a un directorio
distinto. Esto puede ser causado por un número de factores. En todo caso, se debería observar la salida del seteo SYS(2023) actual ya que puede ser que difiera del directorio
temporal normal usado por Windows. El peor caso es que Visual FoxPro utilice el directorio raíz del usuario o el directorio del programa, ambos a menudo que están en el
servidor. Realmente para estar seguro donde van los ficheros temporales, se podría crear un cursor y determinar su posición con la función de DBF(). Aún cuando un cursor se

https://visualfoxpro.webcindario.com/visual_foxpro/articulos/secretos_ocultos_vfp/como_trabaja_vfp_internamente.php[26/03/2020 0:36:56]
Cómo trabaja FoxPro internamente
crea generalmente en el mismo directorio donde apunta SYS(2023), este no siempre es el caso.

Rushmore
Rushmore es más que una tecnología, es un mito. Esto no debe pararnos, sin embargo, de figurarnos que hay detrás de ese mito. Especialmente con este asunto es importante
distinguir los hechos de la ficción. En la última década la regla era crear un índice por DELETED(), justo lo contrario es verdad en esta década. Ninguna de ambas, sin embargo,
son realmente la verdad.

La razón del funcionamiento de Visual FoxPro tiene dos fundamentos. Un fundamento es Rushmore, el otro fundamento es el uso verdaderamente agresivo de la caché. La
diferencia del funcionamiento de otras bases de datos con algoritmos de búsqueda centrados en mapas de bits (pues Rushmore es uno) no es causada sobre todo por
Rushmore, sino debido a su estrategia de caché y a un acceso de red optimizado.

Rushmore es un algoritmo orientado a mapas de bits. Visual FoxPro crea una lista para cada condición que se pueda optimizar con Rushmore. Esta lista determina si un
registro satisface los criterios de búsqueda o no. Visual FoxPro utiliza un solo bit para cada registro, pues hay solamente dos estados posibles para cada registro. Ocho registros
caben en un byte. Si se tiene una tabla de 8-millones-de-registros, cada condición de la búsqueda toma 1 MB de la memoria.

Cada bit comienza siendo 0 - no seteado - y el registro correspondiente está por lo tanto en el conjunto de resultados. Una vez que los mapas de bits hayan sido determinados
para todas las condiciones, esos mapas de bits se combinan bit-a-bit. Si se utiliza la condición siguiente en una consulta:

NAME = "Smith" AND InvoiceDate < DATE()-60

Esta consulta resulta en la creación de dos mapas de bits independientes que contienen todos los registros para “Smith” y todos los registros con una fecha de factura menor a
60 días. En cada mapa no importa si la otra condición no se satisface. Después de eso ambos mapas de bits son combinadas bit-a-bit con AND. El resultado es un mapa de bits
que tiene solamente un bit seteado para aquellos registros que satisfagan ambas condiciones. No es difícil imaginarse que el uso de la memoria para acumular estos mapas de
bits puede rápidamente crecer y retrasar una consulta. Si tienes solamente una sola condición, puedes utilizar el viejo estilo del dBase:

SET ORDER TO RequiredIndex


SEEK Value
SCAN WHILE Field=Values
   * do something
ENDSCAN

En muchos casos esto es incluso más rápido que una consulta optimizada con Rushmore porque Visual FoxPro no tiene que crear un mapa de bits. Por otra parte, esta técnica
no utiliza la caché de la misma forma que Rushmore, haciendo consultas repetidas a los mismos datos más rápidas en Rushmore. Rushmore trabaja como el bucle SCAN
anterior seteando el bit dentro del bucle.

¿Cómo se crea realmente este mapa de bits? El factor más importante es que el índice en Visual FoxPro está almacenado como b-tree, un árbol equilibrado. Cada nodo es un
bloque de 512 bytes que puede contener hasta 100 punteros para subordinar nodos. Los nodos cerca de la raíz referencian a los valores clave, sólo los nodos de la hoja
referencian a registros. Como cada nodo no referencia solamente a otros dos bloques, como se podría haber supuesto, la jerarquía en el archivo del índice puede seguir siendo
generalmente muy plana. Además, todos los nodos se ligan horizontalmente.

Cuando Visual FoxPro busca un valor, navega a través del árbol verticalmente de arriba hacia abajo hasta que encuentra el registro. Entonces continúa leyendo
horizontalmente mientras el valor de la búsqueda coincida con el que está en el índice. Esta estrategia de lectura abajo y de lado reduce el número de los nodos del índice que
tiene que leer, pero incrementa el número de nodos al actualizar el índice. Mientras que lee horizontalmente, Visual FoxPro setea el bit correspondiente para cada registro
encontrado. Esto es posible porque la entrada de índice contiene el número de registro así como el valor clave. Los datos se almacenan comprimidos sin embargo. Así es cómo
el operador igual trabaja.

Otras operaciones trabajan de manera similar. Por ejemplo, si se desean encontrar los registros que no son iguales, Visual FoxPro comienza con un mapa de bits en el cuál se
setean todos los registros. Entonces realiza la misma búsqueda que cuando busca los registros iguales, salvo que limpia bits cuando encuentra un registro. Al buscar por menor
o mayor que, simplemente se mantiene leyendo la lista hacia la derecha o hacia la izquierda hasta que FoxPro alcanza el final del archivo.

https://visualfoxpro.webcindario.com/visual_foxpro/articulos/secretos_ocultos_vfp/como_trabaja_vfp_internamente.php[26/03/2020 0:36:56]
Cómo trabaja FoxPro internamente
Con Rushmore Visual FoxPro puede determinar qué registros no están en el conjunto de resultados, no los registros que están en el conjunto de resultados. Ése es el porqué la
fase de Rushmore es seguida por la fase post-exploración. Cada registro que ha sido determinado por Rushmore se lee totalmente desde disco. Sin una expresión optimizada
éstos son todos los registros en todas las tablas. Cada uno de estos registros entonces se comprueba para las expresiones inoptimizables restantes. Además, todas las
expresiones optimizables se evalúan de nuevo, ya que algún otro pudo haber cambiado el registro mientras que Visual FoxPro creaba el mapa. Por lo tanto el conjunto de
resultados podría no contener todos los registros que coinciden actualmente con los criterios de búsqueda, pero nunca se obtienen registros que no coinciden con los criterios
de búsqueda.

Hay una excepción a esta regla, sin embargo. Al contar registros, Visual FoxPro intenta evitar la fase post-exploración. Cuando se ha construido el mapa de bits y no se deja
ninguna expresión inoptimizable, Visual FoxPro comienza a contar los bits seteados. Por lo tanto COUNT FOR y SELECT CNT(*) FROM son extremadamente rápidos si una
consulta se optimiza completamente. Una optimización parcial no es suficiente. Tampoco ayuda utilizar ningún otro método de cuenta como SELECT SUM(1) FROM…

Cuando se crea el mapa de bits Visual FoxPro tiene que leer todos los bloques de índice que coinciden con los criterios de búsqueda. Las accesos repetidos hacen que Visual
FoxPro recupere estos bloques de la caché. Sin embargo, se desecha la caché si una estación de trabajo cambia un campo puesto en un índice o agrega un nuevo registro.
Visual FoxPro puede determinar sólamente que otra estación de trabajo ha cambiado el índice, pero no qué ha cambiado exactamente. Por lo tanto la caché entera se desecha.
Se puede explotar esto para medir la performance. Usando una segunda instancia de FoxPro que reemplace un campo del índice en el primer registro en un bucle.

Hace algún tiempo la gente comenzó a darse cuenta de que un índice por DELETED() no es siempre la solución óptima. Parece que hay una clase de contra-movimiento que
condena totalmente el índice, que tampoco es una buena idea. Cuándo Rushmore es una buena idea es realmente muy fácil de determinar. Si se leen más bytes en el archivo
del índice que los registros que se quitan durante la post-exploración, Rushmore disminuye la performance. Se tienen que comparar los bytes que se transfieren realmente.

Por lo tanto se necesita tener presente que la caché tiene un impacto con Rushmore y que los índices CDX están almacenados comprimidos. Los comienzos iguales de una
palabra se almacenan solamente una vez. La cantidad real de datos se puede determinar con el monitor del sistema en Windows. Aún los resultados más exactos son posibles
con un monitor de red como NETMON.EXE que viene con Windows 2000 server, o Ethereal que está disponible gratuitamente en http://www.ethereal.com . Tal monitor de red
revela qué parte de un archivo se lee realmente. Combinado con la estructura de los archivos del archivo de ayuda se pueden determinar muchos detalles.

Si una aplicación cambia montones de datos estos invalidan con más frecuencia la caché. Por lo tanto, tal aplicación se beneficia menos de Rushmore que, por ejemplo, una
aplicación de catálogo de CD's que ha puesto todos los datos en la caché después de un corto tiempo de usarla.

Si su aplicación tiene muchos registros eliminados también se beneficia de Rushmore. Si su aplicación visita un registro múltiples veces porque, por ejemplo, el algoritmo
requiere la navegación por los registros siguientes y anteriores, Rushmore es superior pues puede reutilizar los mapas de bits mientras que el código del viejo estilo del xBase
tiene que releer todos los registros repetidamente.

Si se desea determinar el número de hits antes de que realmente se ejecute la consulta dando a sus usuarios la chance de evitar consultas duraderas, su consulta debe ser
completamente optimizable. Esto le da una ventaja verdadera de velocidad ya que crear un mapa de bits toma significativamente menos tiempo que leer la tabla entera, y el
mapa de bits puede incluso ser reutilizado si el usuario decide ejecutar la consulta.

Otro factor importante es la distribución de valores en el campo indexado. Hay una diferencia enorme si se busca un valor único como una clave primaria o un campo de estado
que pueda tomar solamente diez valores distintos. Un ejemplo extremo es el índice por DELETED() para el cual todos los campos tienen generalmente el mismo valor. En
general se deben evitar tales índices a menos que los necesite para propósitos de contar.

Palabras Finales

Este documento puede dar solamente una breve introducción sobre el funcionamiento de Visual FoxPro. Muchas cosas sólo las he mencionado brevemente. Algunas cosas
incluso no pudieron tener sentido cuando usted las leyó la primera vez. Se mantiene la pregunta: ¿Se necesitan conocer todas estas cosas? Ciertamente, no. Pero saber
algunas de estas cosas le puede ayudar a evaluar riesgos de forma más precisa. Podría explicar porqué ocurren ciertos errores que parecen ser al azar. Y es sólo y
simplemente interesante saber qué está ocurriendo por dentro.

Descarga

Cómo trabaja FoxPro internamente

https://visualfoxpro.webcindario.com/visual_foxpro/articulos/secretos_ocultos_vfp/como_trabaja_vfp_internamente.php[26/03/2020 0:36:56]
Cómo trabaja FoxPro internamente
 

Referencias

Artículo original: FoxPro Inside Out http://www.foxpert.com/docs/howfoxproworks.en.htm

Autor: Christof Wollenhaupt, Foxpert

Traducido por: Fernando D. Bozzo (fdbozzo@gmail.com)

Visual Foxpro Aconsejamos utilizar Mozilla Firefox y una resolución de 1920 x 1080.

  Para aumentar la pantalla Ctrl + - Para disminuir la pantalla Ctrl -


25 de Diciembre de 2018
 
© 2018 - César A. Mallo Fernández F11 Maximiza ventana, y pulsando de nuevo, volvemos al estado anterior.

Contacto: foxribbonlib@gmail.com En este sitio web todas las marcas registradas son propiedad de sus respectivos dueños.

https://visualfoxpro.webcindario.com/visual_foxpro/articulos/secretos_ocultos_vfp/como_trabaja_vfp_internamente.php[26/03/2020 0:36:56]

Вам также может понравиться