Algoritmo FIFO

26
El FIFO (First In, First Out - El primero que entra es el primero que sale :D) Es una simple cola. Como la de los boletos en el cine, como la de las tortillerias, donde los que van llegando se forman hasta el final de la cola, asi que el primero que habia llegado a la cola, es el primero que va a salir porque esta hasta el frente. Algoritmo FIFO (First Input-First Output, primera en entrar-primera en salir) Una estrategia sencilla e intuitivamente razonable es seleccionar para la sustitución la página que lleva más tiempo en memoria. La implementación de este algoritmo es simple. Además, no necesita ningún apoyo hardware especial. El sistema operativo debe mantener una lista de las páginas que están en memoria, ordenada por el tiempo que llevan residentes. En el caso de una estrategia local, se utiliza una lista por cada proceso. Cada vez que se trae una nueva página a memoria, se pone a1 final de la lista. Cuando se necesita reemplazar, se usa la página que está al principio de la lista. Sin embargo, el rendimiento del algoritmo no es siempre bueno. La página que lleva más tiempo residente en memoria puede contener instrucciones o datos que se acceden con frecuencia. Además, en determinadas ocasiones, este algoritmo presenta un comportamiento sorprendente conocido como la anomalía de Belady [Belady, 1969]. Intuitivamente parece que cuantos más marcos de página haya en el sistema, menos fallos de página se producirán. Sin embargo, ciertos patrones de referencias causan que este algoritmo tenga un comportamiento opuesto. El descubrimiento de esta anomalía resultó al principio sorprendente y llevó al desarrollo de modelos teóricos para analizar los sistemas de paginación. En la práctica, esta anomalía es más bien una curiosidad que demuestra que los sistemas pueden tener a veces comportamientos inesperados. Primera en entrar, primera en salir (FIFO , First In, First Out) En este método el sistema operativo sólo tiene que guardar en qué orden las páginas fueron cargadas, de modo que al necesitar hacer espacio pueda fácilmente elegir la primera página cargada. Se usa una cola , al cargar una página nueva se ingresa en el último lugar. Aunque las colas FIFO son simples e intuitivas, no se comportan de manera aceptable en la aplicación práctica, por lo que es raro su uso en su forma simple. Uno de los problemas que presentan es la llamada Anomalía FIFO o Anomalía de Belady . Belady encontró ejemplos en los que un sistema con un número de marcos de páginas igual a tres tenía menos fallos de páginas que un sistema con cuatro marcos de páginas. El problema consiste en que podemos

Transcript of Algoritmo FIFO

Page 1: Algoritmo FIFO

El FIFO (First In, First Out - El primero que entra es el primero que sale :D)

Es una simple cola. Como la de los boletos en el cine, como la de las tortillerias, donde los que van llegando se forman hasta el final de la cola, asi que el primero que habia llegado a la cola, es el primero que va a salir porque esta hasta el frente.

Algoritmo FIFO (First Input-First Output, primera en entrar-primera en salir)

Una estrategia sencilla e intuitivamente razonable es seleccionar para la sustitución la página que lleva más tiempo en memoria. La implementación de este algoritmo es simple.Además, no necesita ningún apoyo hardware especial. El sistema operativo debe mantener una lista de las páginas que están en memoria, ordenada por el tiempo que llevan residentes. En el caso de una estrategia local, se utiliza una lista por cada proceso.Cada vez que se trae una nueva página a memoria, se pone a1 final de la lista. Cuando se necesita reemplazar, se usa la página que está al principio de la lista. Sin embargo, el rendimiento del algoritmo no es siempre bueno. La página que lleva más tiempo residente en memoria puede contener instrucciones o datos que se acceden con frecuencia. Además, en determinadas ocasiones, este algoritmo presenta un comportamiento sorprendente conocido como la anomalía de Belady [Belady, 1969].Intuitivamente parece que cuantos más marcos de página haya en el sistema, menos fallos de página se producirán. Sin embargo, ciertos patrones de referencias causan que este algoritmo tenga un comportamiento opuesto. El descubrimiento de esta anomalía resultó al principio sorprendente y llevó al desarrollo de modelos teóricos para analizar los sistemas de paginación. En la práctica, esta anomalía es más bien una curiosidad que demuestra que los sistemas pueden tener a veces comportamientos inesperados.

Primera en entrar, primera en salir (FIFO, First In, First Out)

En este método el sistema operativo sólo tiene que guardar en qué orden las páginas fueron cargadas, de modo que al necesitar hacer espacio pueda fácilmente elegir la primera página cargada. Se usa una cola, al cargar una página nueva se ingresa en el último lugar. Aunque las colas FIFO son simples e intuitivas, no se comportan de manera aceptable en la aplicación práctica, por lo que es raro su uso en su forma simple. Uno de los problemas que presentan es la llamada Anomalía FIFO o Anomalía de Belady. Belady encontró ejemplos en los que un sistema con un número de marcos de páginas igual a tres tenía menos fallos de páginas que un sistema con cuatro marcos de páginas. El problema consiste en que podemos quitar de memoria una página de memoria muy usada, sólo porque es la más antigua.

[editar] Segunda oportunidad

Es una pequeña modificación al algoritmo FIFO, que funciona bastante mejor que que el fifo. En este caso cuando una página debe ser sacada se toma la primera en la cola, y en vez de sacarla, consulta el valor de un bites de referencia. En caso de estar fijado (en 001) se cambia el bites a 99 y se lo coloca al final de la obstrucción, autorizando su tiempo de carga como si recién hubiera llegado al procesador. De esta forma, se le da una segunda oportunidad. Si el bites se encuentra sin fijar(en 99 ), la página se saca de memoria. Cada vez que la M.U.U accede a una página, fija su bit de referencia a 1. Para esto es necesario soporte para bit de referencia por hardware.

Page 2: Algoritmo FIFO

[editar] Reloj

Existe una variante de este algoritmo que sobre la misma idea presenta una mejora en la implementación. Es el algoritmo del reloj, que lo que hace es tener una lista circular, de forma que al llegar al último elemento de la lista, pasa automáticamente al primero. Los elementos no se mueven al final de la cola cuando son accedidos, simplemente se pone su bit de referencia a 1. Esto nos evita tener que hacer movimientos de punteros en el caso de implementarlo con una lista enlazada. De hecho, se puede implementar con un array perfectamente, ahorrando así memoria.

[editar] No usada recientemente (Not Recently Used, NRU)

Este algoritmo favorece a las páginas que fueron usadas recientemente. Funciona de la siguiente manera: cuando una página es referenciada, fija el bit de referencia para esa página. Similarmente, cuando una página es modificada, fija su bit de modificación. Usualmente estas operaciones son realizadas por el hardware, aunque puede hacerse también por software. En un tiempo fijo, el sistema operativo pone en 0 los bits de referencia de todas las páginas, de modo que las páginas con su bit de referencia en 1 son las que fueron referenciadas dentro del último intervalo de reloj. Cuando una página debe ser reemplazada, el sistema operativo divide las páginas en cuatro categorías:

Categoría 0: no referenciada, no modificada Categoría 1: no referenciada, modificada Categoría 2: referenciada, no modificada Categoría 3: referenciada, modificada

Las mejores páginas para cambiar son las que se encuentran en la categoría 0, mientras que las peores son las de la categoría 3. Se desaloja al azar una página de la categoría más baja que no esté vacía. Este algoritmo se basa en la suposición de que es mejor desalojar una página modificada a la que no se ha hecho referencia en al menos un tic de reloj, en vez de una página limpia que se está usando mucho.

[editar] Menos usada recientemente (Least Recently Used, LRU)

Este algoritmo difiere del de 'No usada recientemente' en el hecho de que aquel sólo se fija en el intervalo de tiempo desde que se pusieron en 0 los bits de referencia de las páginas, mientras que el algoritmo de 'Menos usada recientemente' intenta proveer un comportamiento casi óptimo mediante la observación de las páginas que menos fueron usadas recientemente. Este tipo de páginas, estadísticamente son las que tienen menor probabilidad de ser usadas nuevamente.

Page 3: Algoritmo FIFO

Aunque este algoritmo provee un buen comportamiento en teoría, es caro de implementar, en cuanto a recursos consumidos. Hay varias implementaciones que intentan mantener bajo el costo y lograr un rendimiento considerable. Un método consiste en tener una lista enlazada y ordenada de todas las páginas en memoria. En el final de la lista está la página menos usada recientemente, y al principio la más usada recientemente. El costo alto de este método es porque cada vez que se referencia una página debe ser movida en la lista, algo que consume mucho tiempo. Otra forma, que requiere soporte de hardware, consiste en tener un contador que es incrementado en cada instrucción del CPU. Cada vez que una página es accedida, gana el número del contador en ese momento. Cuando una página debe ser retirada de memoria, simplemente hay que buscar cuál es la que tiene el menor número, que es la que fue usada hace más tiempo. En el presente no existen contadores tan grandes para permitir esto. Debido al alto costo del LRU, se proponen algoritmos similares, pero que permiten implementaciones menos costosas, como los que siguen.

Ejemplos (Aging)

Este algoritmo es un descendiente del algoritmo "No usada frecuentemente", con algunas modificaciones necesarias para tener en cuenta en qué momento fue usada frecuentemente una página, y no solamente cuántas veces fue referenciada.

En vez de sólo incrementar el contador de la página cuando es referenciada, primero se desplaza a la derecha (se divide por 2) y después sí se suma 1. Por ejemplo, si los bits de referencia de una página fueron 1, 0, 0, 1, 1 y 0 en los últimos 6 ticks del reloj, el contador se verá así: 10000000, 01000000, 00100000, 10010000, 11001000, 01100100.

De esta forma, cuando se necesite eliminar una página de memoria, se eliminará la que tenga el número más pequeño en su contador.

Este algoritmo provee una buena aproximación al desempeño del algoritmo óptimo, por un módico precio.

Algoritmo FIFO.- First In First Out - Los procesos se ejecutan según su orden de llegada. El primero en entrar no libera los recursos hasta que termina. Es el más sencillo pero el más ineficaz.

Page 4: Algoritmo FIFO

I'm not quite sure who gave the best contributions regarding possible improvements for last newsletter's SocketWheel. Josh Rehman pointed out that it is not too clever to try minimze memory as that is very cheap nowadays, which I agree with. He also pointed out that JDK 1.4 has non-blocking IO making it possibly a lot easier to implement such a SocketWheel. Ecce Jezuch (Poland) suggested using the available() method to find out how many bytes would be available without blocking, but unfortunately under Windows the JDK always returned 0. También señaló que el JDK 1.4 tiene sin bloqueo de E / S por lo que es posiblemente mucho más fácil aplicar dicho SocketWheel. Ecce Jezuch (Polonia) sugirió el uso de la disposición () para averiguar cuántos bytes estarían disponibles sin el bloqueo, pero lamentablemente en Windows el JDK siempre se devuelve 0.

James Pereira provided some excellent information regarding sockets. James Pereira proporcionan excelente información sobre zócalos. It's quite technical, so I'm including it verbatim: Es muy técnico, así que estoy inclusión literal:

"Registered Ports, ports between 1024 and 49151, are listed by the IANA and on most systems can be used by applications or programs executed by users. Table C.2 specifies the port used by the server process as its contact port. The IANA registers uses of these ports as a convenience to the Internet community. To the extent possible, these same port assignments are used with UDP. The Registered Ports are in the numerical range of 1024-49151. The Registered Ports between 1024 and 5000 are also referred to as the Ephemeral Ports. At least on Windows , The TCP/Stack (OS) re-uses these ports internally on every socket connection cycling from 1024...5000 wrapping around to 1024 again. This could lead to some interesting problems if sockets are opened and close very quickly as there is usually a time delay before that port is made available again... "Puertos registrados, los puertos entre 1024 y 49151, son enumerados por la IANA y en la mayoría de los sistemas pueden ser utilizados por las aplicaciones o programas ejecutados por los usuarios. Tabla C.2 especifica el puerto usado por el proceso de servidor como su puerto de contacto. IANA registra los los usos de estos puertos como una conveniencia para la comunidad de Internet. En la medida de lo posible, estas mismas asignaciones de puerto se utilizan con UDP. Los puertos registrados están en el rango numérico de 1024-49151. Los puertos registrados entre 1024 y 5000 también se conocen como los puertos efímeros. Por lo menos en Windows, TCP / Pila (OS) re-utiliza estos puertos internos en cada ciclo de conexión de socket de 1024 ... 5000 envolviendo a 1024 de nuevo. Esto podría llevar a algunos problemas interesantes si tomas son abrir y cerrar muy rápidamente, ya que suele ser un tiempo de retraso antes de que el puerto esté disponible de nuevo ...

"Second, the number of user-accessible ephemeral ports that can be used to source outbound connections is configurable with the MaxUserPort registry entry (HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters). By default, when an application

Page 5: Algoritmo FIFO

requests any socket from the system to use for an outbound call, a port between the values of 1024 and 5000 is supplied. You can use the MaxUserPort registry entry to set the value of the highest port number to be used for outbound connections. For example, setting this value to 10000 would make approximately 9000 user ports available for outbound connections. For more details, see RFC 793. See also the MaxFreeTcbs and MaxHashTableSize registry settings (HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters). "En segundo lugar, el número de puertos efímeros de acceso de usuario que se puede utilizar para conexiones salientes fuente se puede configurar con la entrada del Registro MaxUserPort (HKLM \ SYSTEM \ CurrentControlSet \ Services \ Tcpip \ Parameters). De forma predeterminada, cuando una aplicación solicita cualquier toma de el sistema a utilizar para una llamada saliente, un puerto entre los valores de 1024 y 5000 se suministra. Puede utilizar la entrada del Registro MaxUserPort para establecer el valor del número de puerto más alto que se utilizará para las conexiones de salida. Por ejemplo, el establecimiento de este valor 10000 tendría aproximadamente 9000 puertos de usuario disponible para conexiones salientes. Para más detalles, consulte el documento RFC 793. Véase también el MaxFreeTcbs y registro de configuración de MaxHashTableSize (HKLM \ SYSTEM \ CurrentControlSet \ Services \ Tcpip \ Parameters).

"BTW: The stack and memory size issue is only an NT issue. On NT the stack size is configurabale via linker and EditBin.exe unfortunately we don't want to mess with the VM." "Por cierto: La pila y el tamaño del problema de memoria es sólo una cuestión NT VM. En NT el tamaño de pila es configurabale a través de enlazador y EditBin.exe lamentablemente no queremos que meterse con el."

This information should solve the problem that I encountered with too many sockets causing exceptions. Esta información debería resolver el problema que me encontré con muchas tomas demasiado causando excepciones.

Ideally we should be able to specify stack size per thread as some threads will need a lot and others only a little, so I still think that we have a problem with many threads and their stack size. Idealmente deberíamos ser capaces de especificar el tamaño de pila por hilo ya que algunos temas se necesita mucho y otros sólo un poco, por lo que sigo pensando que tenemos un problema con muchos hilos y su tamaño de la pila.

Another excellent contribution was made by Craig Larman, author of "Java 2 Performance and Idiom Guide", who suggested using an approach of multiplexing sockets described in his book to minimize the number of sockets needed per client connection. Next week I will try and write about this idea and give you a solution that hopefully will work acceptably. Otra excelente contribución fue hecha por Craig Larman, autor de "Java 2 Rendimiento y Idiom Guía", quien sugirió el uso de un enfoque de cuencas multiplexación se describe en su libro de reducir al mínimo el número de tomas de corriente necesaria por conexión de cliente. La próxima semana voy a tratar de escribir sobre esta idea y darle una solución que esperamos que sean aceptablemente. I always recommend Craig's book as an excellent book for the Java fundi who wants to have his mind activated regarding performance ideas. Yo siempre recomiendo el libro de Craig como un excelente libro para el fondo de ojo Java que quiere tener su mente activa con respecto a las ideas de rendimiento. It is very difficult to write anything about performance as it is so dependent on your implementation and

Page 6: Algoritmo FIFO

hardware. Es muy difícil escribir algo sobre el rendimiento, ya que es tan dependiente en su aplicación y el hardware. This leads me to this week's newsletters on self-tuning FIFO queues.... Esto me lleva a la semana los boletines de este ajuste en las colas FIFO-yo ....

Self-tuning FIFO Queues Autoajuste colas FIFO

HotSpot(tm) has caused a lot of trouble for the Java Specialist in the field, especially those of us with a few years experience. All of a sudden, all the hard-earned performance knowledge was wiped out in one foul swoop. HotSpot (TM) ha causado muchos problemas para el especialista en Java en el campo, especialmente aquellos de nosotros con una experiencia de unos pocos años. De repente, todos los resultados obtenidos en el conocimiento duro fue aniquilada en una sola vez falta. The only thing left for us to do was to write the simplest code that could possibly work and let the HotStop compiler sort out performance for us. Lo único que nos queda por hacer es escribir el código más simple que podría funcionar y dejar que el tipo de rendimiento del compilador HotStop para nosotros. I liken it to the great financial crisis of Japan in the 90's, where no one knew whether he was coming or going and all the old certainties went out of the window. Lo comparo con la gran crisis financiera de Japón en los años 90, cuando nadie sabía si estaba yendo o viniendo y todas las viejas certezas se fue por la ventana. Luckily, unlike in Japan, we are not taking this too seriously, so our windows are still closed. Fortunately everyone knows that Java is slow ;-) Afortunadamente, a diferencia de Japón, no estamos tomando muy en serio, por lo que nuestras ventanas están cerradas todavía. Afortunadamente todo el mundo sabe que Java es lento ;-)

A lot of the performance tricks we used in old code actually make our code slower under HotSpot. Muchos de los trucos de rendimiento que utilizamos en el código antiguo realmente hacer nuestro código más lento en HotSpot. Since we don't know what the performance of our code will be for a specific platform, would it be completely hairbrained to write self-tuning code? Dado que no sabemos lo que el rendimiento de nuestro código será para una plataforma específica, sería completamente hairbrained para escribir código de auto-ajuste? Write 3 algorithms, let the program measure on the target platform which performs best, and choose that algorithm for the duration of the VM. Escribe tres algoritmos, que mide el programa en la plataforma de destino que se comporta mejor, y elegir el algoritmo para la duración de la máquina virtual.

To illustrate this idea, I want to write a FIFO queue that is based on a java.util.List implementation. Para ilustrar esta idea, quiero escribir una cola FIFO que se basa en una aplicación java.util.List. A while ago I discovered that java.util.ArrayList is sometimes faster than java.util.LinkedList for FIFO queue implementations. Hace un tiempo descubrí que java.util.ArrayList veces es más rápido que java.util.LinkedList para las implementaciones de cola FIFO. The switch over occurs at a specific point in time, which we can measure beforehand. El interruptor se verifica en un punto específico en el tiempo, que podemos medir de antemano. The switch-over point is dependent on the VM, whether we are using HotSpot(tm), etc. For example, on my little notebook with 256MB RAM and Pentium III 700, the cross-over point is 50 elements in the list when I use HotSpot, but 500 elements when I switch off hotspot compiling (sometimes!). La transición a punto depende

Page 7: Algoritmo FIFO

de la máquina virtual, si estamos utilizando HotSpot (TM), etc Por ejemplo, en mi pequeña libreta con 256 MB de RAM y Pentium III 700, el punto de cruce es de 50 elementos de la lista cuando uso de HotSpot, pero los elementos 500 al cambiar de punto de acceso compilación (a veces!).

The interface that the FIFO queues will implement is very simple: La interfaz que las colas FIFO implementará es muy simple:

public interface FIFO { public interface FIFO { /** Add an object to the end of the FIFO queue */ / ** Agregar un objeto al final de la cola FIFO * / boolean add(Object o); booleano agregar (Object o); /** Remove an object from the front of the FIFO queue */ / ** Eliminar un objeto desde la parte frontal de la cola FIFO * / Object remove(); Objeto de eliminar (); /** Return the number of elements in the FIFO queue */ / ** Devuelve el número de elementos en la cola FIFO * / int size(); int size ();} }

We implement this interface and extend ArrayList and LinkedList: Implementamos esta interfaz y ampliar ArrayList y LinkedList:

// FIFOArrayList.java / / FIFOArrayList.javaimport java.util.ArrayList; importación java.util.ArrayList;public class FIFOArrayList extends ArrayList implements FIFO { FIFOArrayList clase pública se extiende ArrayList implementa FIFO { public Object remove() { Objeto público remove () { return remove( 0 ); volver eliminar (0); } }} }// FIFOLinkedList.java / / FIFOLinkedList.javaimport java.util.LinkedList; importación java.util.LinkedList;public class FIFOLinkedList extends LinkedList implements FIFO { FIFOLinkedList clase pública se extiende LinkedList implementa FIFO { public Object remove() { Objeto público remove () { return remove( 0 ); volver eliminar (0); } }} }

We also write a SwappingOverFIFOQueue which has values for HIGH and LOW water marks. También escribe una SwappingOverFIFOQueue que tiene valores para alto y bajo marcas de agua. When we reach a HIGH water mark and we are busy using an ArrayList, we start using a LinkedList. Cuando llegamos a una marca de marea alta y estamos muy ocupados con un ArrayList, que empiece a usar una LinkedList. On the contrary, if we reach a LOW water mark and we are busy using a LinkedList we start using an ArrayList. Por el contrario, si llegamos a una marca de agua baja y estamos ocupados con una LinkedList que empezar a usar un ArrayList.

In foresight to my next example, I have made it possible to set the watermarks, which also checks the optimal list types for all the lists currently in the system. En previsión de mi

Page 8: Algoritmo FIFO

ejemplo siguiente, me han hecho posible el establecimiento de las marcas de agua, que también verifica los tipos de lista óptima para todas las listas actualmente en el sistema. We have to be careful to not get a memory leak by keeping handles to the instances of the SwappingOverFIFOQueue so we use WeakReferences to hold the references. Tenemos que tener cuidado de no obtener una pérdida de memoria, manteniendo las manijas de las instancias de la SwappingOverFIFOQueue así que usamos WeakReferences para mantener las referencias. Have a look at newsletter 15 for a discussion on Weak / Soft References. Echa un vistazo a boletín 15 para una discusión sobre la débil / Referencias suave.

// SwappingOverFIFOQueue.java import java.util.*; import java.lang.ref.WeakReference; public final class SwappingOverFIFOQueue implements FIFO { /** The low value after which we switch over to ArrayList */ private static int LOW = 30 ; /** The high value after which we switch down to LinkedList */ private static int HIGH = 70 ; /** This list contains weak references of instances of this class */ private static List instances = new LinkedList(); /** We add the weak references in an initializer block */ { instances.add( new WeakReference( this )); } /** When we set the low and high water marks we go through all the existing instances and check for the optimal list type. If the references is null we remove the WeakReference from our instance list. / / Import java.util .* SwappingOverFIFOQueue.java; java.lang.ref.WeakReference importación; público final SwappingOverFIFOQueue clase implementa FIFO {/ ** El valor baja después de que cambiar a ArrayList * / static int privado BAJO = 30; / ** El alto valor después de que el interruptor hacia abajo para LinkedList * / static int privado ALTA = 70; / ** Esta lista contiene referencias débiles de instancias de esta clase * / private casos Lista estática nueva = LinkedList (); / ** Añadimos las escasas referencias en un bloque de inicialización * / {instances.add (nuevo WeakReference (este));} / ** Cuando abrimos la marca de agua a alta y baja que pasar por todas las instancias existentes y verifique el tipo de lista óptima . Si la referencia es nula quitamos la WeakReference de nuestra lista de ejemplo. */ public static void setWaterMarks( int low, int high) { LOW = low; HIGH = high; Iterator it = instances.iterator(); while (it.hasNext()) { WeakReference ref = (WeakReference)it.next(); SwappingOverFIFOQueue q = (SwappingOverFIFOQueue)ref.get(); if (q == null ) { it.remove(); } else { q.checkOptimalListType(); } } } private List list = new ArrayList(); public Class getListType() { return list.getClass(); } private int size = 0 ; public boolean add(Object o) { try { list.add(o); return true ; } finally { if (++size == HIGH) checkOptimalListType(); } } public Object remove() { try { return list.remove( 0 ); } finally { if (--size == LOW) checkOptimalListType(); } } public int size() { return size; } private void checkOptimalListType() { if (size >= HIGH && (!(list instanceof LinkedList))) { list = new LinkedList(list); } else if (size <= LOW && (!(list instanceof ArrayList))) { list = new ArrayList(list); } } } * / Public static void setWaterMarks (int baja, int alto) {BAJO = bajo; ALTO = alto; iterador que instances.iterator = (), mientras que it.hasNext ()) {WeakReference ref = ((WeakReference) it.next ( ); SwappingOverFIFOQueue q = (SwappingOverFIFOQueue) ref.get (); if (q == null) {it.remove ();} else {q.checkOptimalListType ();}}} lista Lista privada = new ArrayList (); pública getListType Clase () {list.getClass retorno ();} int tamaño privado = 0; public boolean add (Object o) {try {list.add (o); return true;} finally {if (+ + tamaño == HIGH ) checkOptimalListType ();}} public Object remove () {try {return list.remove (0);} finally {if (- tamaño == LOW) checkOptimalListType ();}} public int tamaño () {tamaño de

Page 9: Algoritmo FIFO

retorno; } checkOptimalListType private void () {if (tamaño> = HIGH & & (!) (lista instanceof LinkedList)) {lista = new LinkedList (lista);} else if (= <BAJA & & (! tamaño (lista instanceof ArrayList))) {lista = new ArrayList (lista);}}}

My test program takes the number of entries in the queue and then illustrates how often we can add/remove in 2 seconds for each of the queues. Mi programa de prueba toma el número de entradas en la cola y, a continuación ilustra la frecuencia con la que podemos añadir o eliminar en 2 segundos para cada una de las colas. I found that you get the best performance results when you run your tests for about 2 seconds each, so I count iterations rather than milliseconds. He encontrado que usted obtiene el mejor resultado de rendimiento al ejecutar las pruebas durante unos 2 segundos cada uno, así que en lugar de contar las iteraciones milisegundos.

// SwappingOverFIFOQueueTest.java import java.util.*; public class SwappingOverFIFOQueueTest { private static int ENTRIES; public static void test(FIFO queue) { for ( int i= 0 ; i<ENTRIES; i++) { queue.add( new Object()); } long up_to = System.currentTimeMillis() + 2000 ; int iterations = 0 ; while (System.currentTimeMillis() <= up_to) { queue.add( new Object()); queue.remove(); iterations++; } System.out.println(queue.getClass()); System.out.println( "\t" + iterations + " iterations" ); } public static void main(String[] args) { if (args.length != 1 ) { System.out.println( "Usage: java SwappingOverFIFOQueueTest entries" ); System.exit( 1 ); } ENTRIES = Integer.parseInt(args[ 0 ]); System.out.println( "Entries = " + ENTRIES); test( new FIFOArrayList()); test( new FIFOLinkedList()); SwappingOverFIFOQueue q = new SwappingOverFIFOQueue(); test(q); System.out.println( "Current queue implementation " + q.getListType().getName()); } } / / SwappingOverFIFOQueueTest.java import java.util .*; public class SwappingOverFIFOQueueTest {private static int entradas; ensayo estático public void (FIFO cola) {for (int i = 0; i <entradas; i + +) {(nuevo objeto queue.add ());} up_to largo = System.currentTimeMillis () + 2000; iteraciones int = 0; while (System.currentTimeMillis () = <up_to) {queue.add (new Object ()); queue.remove (); iteraciones + + ;} System.out.println (queue.getClass ()); System.out.println ("\ t" + + iteraciones "iteraciones");} void públicos principales (String [] args) {if (args.length ! = 1) {System.out.println ("Uso: java entradas SwappingOverFIFOQueueTest"); System.exit (1);} ENTRADAS = Integer.parseInt (args [0]); System.out.println ("Entradas =" + ENTRADAS), ensayo (FIFOArrayList nuevo ()), ensayo (FIFOLinkedList nuevo ()); SwappingOverFIFOQueue q = new SwappingOverFIFOQueue (); prueba (q); System.out.println ("cola de la aplicación actual" + q.getListType () . getName ());}}

On my notebook, when I run this program with 0 entries, I get the following output: En mi cuaderno, cuando ejecuto este programa con 0 registros, me sale el siguiente resultado:

Entries = 0 Entradas = 0class FIFOArrayList FIFOArrayList clase 4552883 iterations 4552883 iteracionesclass FIFOLinkedList FIFOLinkedList clase 2551017 iterations 2551017 iteracionesclass SwappingOverFIFOQueue clase SwappingOverFIFOQueue 3594810 iterations 3594810 iteraciones

Page 10: Algoritmo FIFO

With 100 entries I get: Con 100 de las entradas me sale:

Entries = 100 Las entradas = 100class FIFOArrayList FIFOArrayList clase 1800877 iterations 1800877 iteracionesclass FIFOLinkedList FIFOLinkedList clase 2509328 iterations 2509328 iteracionesclass SwappingOverFIFOQueue clase SwappingOverFIFOQueue 2158451 iterations 2158451 iteraciones

And with 10000 entries I get: Y con 10.000 entradas me sale:

Entries = 10000 Entradas = 10000class FIFOArrayList FIFOArrayList clase 49500 iterations 49.500 iteracionesclass FIFOLinkedList FIFOLinkedList clase 812933 iterations 812.933 iteracionesclass SwappingOverFIFOQueue clase SwappingOverFIFOQueue 758657 iterations 758.657 iteraciones

We can thus see that the SwappingFIFOQueue is always faster than the worst case and slower than the best case, as one would logically expect. Por eso podemos comprender que la SwappingFIFOQueue es siempre más rápido que el peor de los casos y más lento que el mejor de los casos, como era de esperar. However, I chose the HIGH and LOW values from some tests that I made on my notebook, for that specific JVM. Sin embargo, he elegido el ALTA y BAJA valores de algunas pruebas que hice en mi portátil, para que la JVM específica. If I take the JDK 1.2.2 that comes with JBuilder, for 100 entries I get: Si tomo el JDK 1.2.2 que viene con JBuilder, para 100 entradas me sale:

Entries = 100 Las entradas = 100class FIFOArrayList FIFOArrayList clase 1434122 iterations 1434122 iteracionesclass FIFOLinkedList FIFOLinkedList clase 1307108 iterations 1307108 iteracionesclass SwappingOverFIFOQueue clase SwappingOverFIFOQueue 1178115 iterations 1178115 iteraciones

Or if I use the -Xint mode for JDK 1.3 under Windows to switch off the hotspot compiler, for 100 entries I get O si uso en modo Xint la de JDK 1.3 en Windows para apagar el compilador de punto de acceso, para 100 de las entradas me

Entries = 100 Las entradas = 100class FIFOArrayList FIFOArrayList clase 497550 iterations 497.550 iteracionesclass FIFOLinkedList FIFOLinkedList clase 480599 iterations 480.599 iteracionesclass SwappingOverFIFOQueue clase SwappingOverFIFOQueue 392314 iterations 392.314 iteraciones

Page 11: Algoritmo FIFO

In both cases, the values of the SwappingOverFIFOQueue were worse than for both the ArrayList and the LinkedList. En ambos casos, los valores de la SwappingOverFIFOQueue eran peores que tanto para el ArrayList y LinkedList el.

We therefore write a Profiler that finds ideal HIGH/LOW water marks for the JVM that is running on your system and sets up the SwappingOver water marks. Por lo tanto, escribir un analizador que encuentra ideal ALTO BAJO marcas de agua / de la máquina virtual Java que se ejecuta en su sistema y establece las marcas de agua SwappingOver.

// SwappingOverFIFOQueueProfiler.java import java.util.*; /* For the sake of brevity we only consider two implementations of java.util.List, namely java.util.ArrayList and java.util.LinkedList. / / SwappingOverFIFOQueueProfiler.java import java.util .*; / * En aras de la brevedad, sólo se consideran dos implementaciones de java.util.List, a saber, java.util.ArrayList y java.util.LinkedList. */ public class SwappingOverFIFOQueueProfiler { private static boolean isArrayListFaster( int entries) { System.out.println( "isArrayListFaster(" + entries + ")" ); return countIterations( new ArrayList(), entries) > countIterations( new LinkedList(), entries); } private static int countIterations(List list, int entries) { for ( int i= 0 ; i<entries; i++) { list.add( new Object()); } long end = System.currentTimeMillis() + 1000 ; int iterations = 0 ; while (System.currentTimeMillis() <= end) { iterations++; list.add( new Object()); list.remove( 0 ); } return iterations; } static { int checks = 0 ; int watermark = 1 ; int bestWatermark = 0 ; for ( int i= 0 ; i< 16 ; i++) { if (isArrayListFaster(watermark)) { bestWatermark = Math.max(watermark, bestWatermark); watermark *= 2.0 ; } else { watermark *= 0.75 ; if (watermark <= bestWatermark) watermark *= 1.25 ; } } System.out.println( "Best watermark = " + bestWatermark); int low = ( int )(bestWatermark * 0.75 ); int high = ( int )(bestWatermark * 1.25 ); System.out.println( "Setting LOW to " + low + " and HIGH to " + high); SwappingOverFIFOQueue.setWaterMarks(low, high); } public static void main(String[] args) { SwappingOverFIFOQueueTest.main( new String[] { "0" }); SwappingOverFIFOQueueTest.main( new String[] { "100" }); SwappingOverFIFOQueueTest.main( new String[] { "10000" }); } } * / Public class SwappingOverFIFOQueueProfiler {static isArrayListFaster booleano privado (las entradas int) {System.out.println ("isArrayListFaster (" + entradas + ")"); countIterations retorno (new ArrayList (), de las entradas)> countIterations (new LinkedList () , de las entradas);} privado countIterations static int (lista de la lista, de las entradas int) {for (int i = 0; i <entradas; i + +) {list.add (new Object ());} extremo largo = System.currentTimeMillis () + 1000; iteraciones int = 0; while (System.currentTimeMillis () <= fin) {iteraciones + +; list.add (new Object ()); list.remove (0);} iteraciones return;} {controles estáticos int = 0 ; marca de agua int = 1; bestWatermark int = 0; for (int i = 0; i <16; i + +) {if (isArrayListFaster (marca de agua)) {bestWatermark = Math.max (marca de agua, bestWatermark), marca de agua *= 2.0;} else {marca de agua *= 0,75; if (= <bestWatermark marca de agua) marca de agua *= 1,25;}} System.out.println ("Mejor marca de agua =" + bestWatermark); baja int = (int) (* bestWatermark 0,75); int alta = (int) (* bestWatermark 1,25); System.out.println ("Marco BAJA a" + bajo + "y ALTO a" + alto); SwappingOverFIFOQueue.setWaterMarks (de alta bajo);} void públicos principales (String [ ] args) {SwappingOverFIFOQueueTest.main (new String [] {"0"});

Page 12: Algoritmo FIFO

SwappingOverFIFOQueueTest.main (new String [] {"100"}); SwappingOverFIFOQueueTest.main (new String [] {"10000"});} }

If we load this class in our system then it will do measurements of where the swap-over between ArrayList and LinkedList performance occurs. Si la carga esta clase en nuestro sistema, entonces va a hacer las mediciones del lugar donde el canje de más de entre ArrayList y LinkedList rendimiento se produce. On my computer, with JDK 1.3 and HotSpot, the swap-over was measured to happen at about 32 entries in the list. En mi PC, con JDK 1.3 y HotSpot, el canje de más de se midió a ocurrir en alrededor de 32 entradas en la lista. When I switch off the HotSpot, it occurs at about 121 entries, and under JDK 1.2.2 it happens at about 303. Cuando apago el punto caliente, que se produce en cerca de 121 entradas, y en el JDK 1.2.2 que ocurre en alrededor de 303.

After spending about 10 hours on this stupid newsletter, I have to conclude that it would be better to stick to a LinkedList for a FIFO queue as it is a better "average" performer. Después de pasar unas 10 horas en este boletín de noticias estúpidas, tengo que concluir que sería mejor quedarse con una LinkedList para una cola FIFO, ya que es un mejor "promedio" artista intérprete o ejecutante. Perhaps the lesson I've learnt from this newsletter is that we must be careful of writing code which is too complicated as it tends to be more difficult to optimize. Tal vez la lección que he aprendido de este boletín es que debemos tener cuidado de escribir código que es muy complicado ya que tiende a ser más difíciles de optimizar. As performance guru Craig Larman pointed out though, we must be sure to not ignore performance altogether; our customers might just kill the project if the prototypes perform like dogs. Como el rendimiento gurú de Craig Larman señaló, sin embargo, debemos estar seguros de no pasar por alto el rendimiento total, los clientes que sólo puede matar el proyecto si los prototipos se comportan como perros.

I always appreciate any feedback, both positive and negative, so please keep sending your ideas and suggestions. Siempre agradecemos cualquier comentario, tanto positivas como negativas, así que por favor sigan enviando sus comentarios y sugerencias. Please also remember to take the time to send this newsletter to others who are interested in Java. Por favor, también a acordarse de tomar el tiempo para enviar este boletín a otros que están interesados en Java.

Heinz Heinz

http://translate.google.com.mx/?hl=es&langpair=en%7Ces#es|en| traductos españpl ingles

http://translate.google.com.mx/translate?hl=es&langpair=en%7Ces&u=http://www.roseindia.net/javatutorials/selftuning_fifo_queues.shtml

Page 13: Algoritmo FIFO

interfaz pública FIFO { / ** Agregar un objeto al final de la cola FIFO * / booleano add (Object o); / ** Eliminar un objeto desde la parte frontal de la cola FIFO * / Objeto de eliminar (); / ** Devuelve el número de elementos en la cola FIFO * / int size ();}

Implementamos esta interfaz y ampliar ArrayList y LinkedList:

/ / FIFOArrayList.javaimportación java.util.ArrayList;public class FIFOArrayList se extiende ArrayList implementa FIFO {

Page 14: Algoritmo FIFO

pública Objeto de eliminar () { volver eliminar (0);  }}/ / FIFOLinkedList.javaimportación java.util.LinkedList;public class FIFOLinkedList se extiende LinkedList implementa FIFO { pública Objeto de eliminar () { volver eliminar (0);  }}

También escribe una SwappingOverFIFOQueue que tiene valores para alto y bajo marcas de agua. Cuando llegamos a una marca de marea alta y estamos muy ocupados con un ArrayList, que empiece a usar una LinkedList. Por el contrario, si llegamos a una marca de agua baja y estamos ocupados con una LinkedList que empezar a usar un ArrayList.

En previsión de mi ejemplo siguiente, me han hecho posible el establecimiento de las marcas de agua, que también verifica los tipos de lista óptima para todas las listas actualmente en el sistema. Tenemos que tener cuidado de no obtener una pérdida de memoria, manteniendo las manijas de las instancias de la SwappingOverFIFOQueue así que usamos WeakReferences para mantener las referencias. Echa un vistazo a boletín 15 para una discusión sobre la débil / Referencias suave.

/ / SwappingOverFIFOQueue.javaimportación java.util .*;importación java.lang.ref.WeakReference;clase pública final SwappingOverFIFOQueue implementa FIFO { / ** El valor baja después de que cambiar a ArrayList * / static int privado BAJO = 30; / ** El alto valor después de que el interruptor hacia abajo para LinkedList * / static int privado ALTO = 70; / ** Esta lista contiene referencias débiles de las instancias de este      clase * / private static Lista de casos = nuevo LinkedList (); / ** Añadimos las escasas referencias en un bloque de inicialización */ {    instances.add (nuevo WeakReference (esta));  } / ** Cuando establecimos las marcas de agua de bajo y alto que pasar por todo      las instancias existentes y verifique el tipo de lista óptima.      Si la referencia es nula quitamos la WeakReference de      nuestra instancia de la lista. * / public static void setWaterMarks (int baja, int de alto) {    BAJO = bajo;    ALTO = alto;    Iterador que instances.iterator = (); mientras que(It.hasNext ()) {      ref = WeakReference (WeakReference) it.next ();      SwappingOverFIFOQueue q = (SwappingOverFIFOQueue) ref.get (); si (Q == nulo) {

Page 15: Algoritmo FIFO

        it.remove ();      } más {        q.checkOptimalListType ();      }    }  }

privado Lista lista = nuevo ArrayList (); pública getListType Clase () { volver list.getClass ();} private int size = 0; public boolean add (Object o) { pruebas {      list.add (o); devolver true;    } finalmente { si (+ + Tamaño == HIGH) checkOptimalListType ();    }  } pública Objeto de eliminar () { pruebas { volver list.remove (0);    } finalmente { si (- Tamaño == LOW) checkOptimalListType ();    }  } public int size () { volver tamaño;  } private void checkOptimalListType () { si (Tamaño> = HIGH & & (! (Lista instanceof LinkedList))) {      lista = nuevo LinkedList (lista);    } else if (<Size = BAJA & & (! (Lista instanceof ArrayList))) {      lista = nuevo ArrayList (lista);    }  }}

Mi programa de prueba toma el número de entradas en la cola y, a continuación ilustra la frecuencia con la que podemos añadir o eliminar en 2 segundos para cada una de las colas. Me encontré con que usted consigue los mejores resultados de rendimiento al ejecutar las pruebas durante unos 2 segundos cada uno, así que en lugar de contar las iteraciones milisegundos.

/ / SwappingOverFIFOQueueTest.javaimportación java.util .*;public class SwappingOverFIFOQueueTest { static int privado ENTRADAS; public static void prueba (cola FIFO) { de (int i =0; I ENTRADAS <; i + +) {      queue.add (nuevo Object ());    } de largo up_to System.currentTimeMillis = () + 2000;

Page 16: Algoritmo FIFO

int iteraciones = 0; mientras que(System.currentTimeMillis () <= up_to) {      queue.add (nuevo Object ());      queue.remove ();      iteraciones + +;    }    System.out.println (queue.getClass ());    System.out.println ("\ T" + + Iteraciones "Iteraciones");  } public static void principal (String [] args) { si (Args.length! = 1) {      System.out.println ( "Uso: java SwappingOverFIFOQueueTest las entradas");      System.exit (1);    }    ENTRADAS = Integer.parseInt (args [0]);    System.out.println ("Las entradas =" + Entradas);    prueba (nuevo FIFOArrayList ());    prueba (nuevo FIFOLinkedList ());    SwappingOverFIFOQueue q = nuevo SwappingOverFIFOQueue ();    prueba (q);    System.out.println ("Implementación de la cola actual" +      q.getListType () getName ()).;  }}

En mi cuaderno, cuando ejecuto este programa con 0 registros, me sale el siguiente resultado:

Entradas = 0FIFOArrayList clase        4552883 iteracionesFIFOLinkedList clase        2551017 iteracionesclase SwappingOverFIFOQueue        3594810 iteraciones

Con 100 de las entradas me sale:

Las entradas = 100

Page 17: Algoritmo FIFO

FIFOArrayList clase        1800877 iteracionesFIFOLinkedList clase        2509328 iteracionesclase SwappingOverFIFOQueue        2158451 iteraciones

Y con 10.000 entradas me sale:

Entradas = 10000FIFOArrayList clase        49.500 iteracionesFIFOLinkedList clase        812.933 iteracionesclase SwappingOverFIFOQueue        758.657 iteraciones

Por eso podemos comprender que la SwappingFIFOQueue es siempre más rápido que el peor de los casos y más lento que el mejor de los casos, como era de esperar. Sin embargo, he elegido el valores altos y bajos de algunas pruebas que hice en mi portátil, para que la JVM específica. Si tomo el JDK 1.2.2 que viene con JBuilder, para 100 entradas me sale:

Las entradas = 100FIFOArrayList clase        1434122 iteracionesFIFOLinkedList clase        1307108 iteracionesclase SwappingOverFIFOQueue        1178115 iteraciones

O si utilizo el modo Xint para JDK 1.3 en Windows para apagar el compilador de punto de acceso, de 100 entradas me

Las entradas = 100FIFOArrayList clase        497.550 iteracionesFIFOLinkedList clase        480.599 iteracionesclase SwappingOverFIFOQueue        392.314 iteraciones

En ambos casos, los valores de la SwappingOverFIFOQueue eran peores que tanto para el ArrayList y LinkedList el.

Page 18: Algoritmo FIFO

Por lo tanto, escribir un analizador que encuentra ideal marcas ALTA / BAJA agua para la máquina virtual Java que se ejecuta en su sistema y establece las marcas de agua SwappingOver.

/ / SwappingOverFIFOQueueProfiler.javaimportación java.util .*;/ *  En aras de la brevedad, sólo se consideran dos implementaciones  de java.util.List, a saber, java.util.ArrayList y  java.util.LinkedList. * /public class SwappingOverFIFOQueueProfiler { booleana estática privado isArrayListFaster (int las entradas) {    System.out.println ("IsArrayListFaster (" + Entradas + ")"); volver countIterations (nuevo ArrayList (), de las entradas)>      countIterations (nuevo LinkedList (), de las entradas);  } static int privado countIterations (lista de la lista, int las entradas) { de (int i =0; I entradas <; i + +) {      list.add (nuevo Object ());    } de largo = fin System.currentTimeMillis () + 1000; int iteraciones = 0; mientras que(System.currentTimeMillis () <= fin) {      iteraciones + +;      list.add (nuevo Object ());      list.remove (0);    } volver iteraciones;  }

estática { int controles = 0; int marca de agua = 1; int bestWatermark = 0; de (int i =0; I <16; I + +) { si (IsArrayListFaster (marca de agua)) {        bestWatermark = Math.max (marca de agua, bestWatermark);        marca de agua *= 2.0;      } más {        marca de agua *= 0.75; si (<= BestWatermark marca de agua)          marca de agua *= 1.25;      }    }    System.out.println ("Mejor marca de agua =" + BestWatermark); int bajo = (int) (* BestWatermark 0.75); int alto = (int) (* BestWatermark 1.25);    System.out.println ("Marco para BAJA" + Bajo + "ALTA y para" + Alto);    SwappingOverFIFOQueue.setWaterMarks (bajo, alto);  } public static void principal (String [] args) {    SwappingOverFIFOQueueTest.main (nuevo String [] { "0" });    SwappingOverFIFOQueueTest.main (nuevo String [] { "100" });    SwappingOverFIFOQueueTest.main (nuevo String [] { "10000" });

Page 19: Algoritmo FIFO

  }}

Si la carga esta clase en nuestro sistema, entonces va a hacer las mediciones del lugar donde el canje de más de entre ArrayList y LinkedList rendimiento se produce. En mi PC, con JDK 1.3 y HotSpot, el canje de más de se midió a ocurrir en alrededor de 32 entradas en la lista. Cuando apago el punto caliente, que se produce en cerca de 121 entradas, y en el JDK 1.2.2 que ocurre en alrededor de 303.

Después de pasar unas 10 horas en este boletín de noticias estúpidas, tengo que concluir que sería mejor quedarse con una LinkedList para una cola FIFO, ya que es un mejor "promedio" artista intérprete o ejecutante. Tal vez la lección que he aprendido de este boletín es que debemos tener cuidado de escribir código que es muy complicado ya que tiende a ser más difíciles de optimizar. Como el rendimiento gurú de Craig Larman señaló, sin embargo, debemos estar seguros de no pasar por alto el rendimiento total, los clientes que sólo puede matar el proyecto si los prototipos se comportan como perros.

Siempre agradecemos cualquier comentario, tanto positivas como negativas, así que por favor sigan enviando sus comentarios y sugerencias. Por favor, también a acordarse de tomar el tiempo para enviar este boletín a otros que están interesados en Java.

Heinz