Está en la página 1de 19

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.
[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.
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.
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 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
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
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.java
import 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.java
import 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
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
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 = 0
class FIFOArrayList FIFOArrayList clase
4552883 iterations 4552883 iteraciones
class FIFOLinkedList FIFOLinkedList clase
2551017 iterations 2551017 iteraciones
class SwappingOverFIFOQueue clase SwappingOverFIFOQueue
3594810 iterations 3594810 iteraciones

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

Entries = 100 Las entradas = 100


class FIFOArrayList FIFOArrayList clase
1800877 iterations 1800877 iteraciones
class FIFOLinkedList FIFOLinkedList clase
2509328 iterations 2509328 iteraciones
class SwappingOverFIFOQueue clase SwappingOverFIFOQueue
2158451 iterations 2158451 iteraciones

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

Entries = 10000 Entradas = 10000


class FIFOArrayList FIFOArrayList clase
49500 iterations 49.500 iteraciones
class FIFOLinkedList FIFOLinkedList clase
812933 iterations 812.933 iteraciones
class 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 = 100


class FIFOArrayList FIFOArrayList clase
1434122 iterations 1434122 iteraciones
class FIFOLinkedList FIFOLinkedList clase
1307108 iterations 1307108 iteraciones
class 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 = 100


class FIFOArrayList FIFOArrayList clase
497550 iterations 497.550 iteraciones
class FIFOLinkedList FIFOLinkedList clase
480599 iterations 480.599 iteraciones
class SwappingOverFIFOQueue clase SwappingOverFIFOQueue
392314 iterations 392.314 iteraciones
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"});
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
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.java
importación java.util.ArrayList;
public class FIFOArrayList se extiende ArrayList implementa FIFO {
pública Objeto de eliminar () {
volver eliminar (0);
  }
}
/ / FIFOLinkedList.java
importació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.java
importació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) {
        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.java
importació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;
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 = 0
FIFOArrayList clase
        4552883 iteraciones
FIFOLinkedList clase
        2551017 iteraciones
clase SwappingOverFIFOQueue
        3594810 iteraciones

Con 100 de las entradas me sale:

Las entradas = 100


FIFOArrayList clase
        1800877 iteraciones
FIFOLinkedList clase
        2509328 iteraciones
clase SwappingOverFIFOQueue
        2158451 iteraciones

Y con 10.000 entradas me sale:

Entradas = 10000
FIFOArrayList clase
        49.500 iteraciones
FIFOLinkedList clase
        812.933 iteraciones
clase 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 = 100


FIFOArrayList clase
        1434122 iteraciones
FIFOLinkedList clase
        1307108 iteraciones
clase 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 = 100


FIFOArrayList clase
        497.550 iteraciones
FIFOLinkedList clase
        480.599 iteraciones
clase SwappingOverFIFOQueue
        392.314 iteraciones

En ambos casos, los valores de la SwappingOverFIFOQueue eran peores que tanto para el
ArrayList y LinkedList el.
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.java
importació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" });
  }
}

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

También podría gustarte