2011-01-16 12 views
9

estoy escribiendo montones y montones de datos que no se leerá otra vez por semana - como mi programa se ejecuta la cantidad de memoria disponible en la máquina (se muestra con 'libre' o 'superior') cae muy rápido, la cantidad de memoria que usa mi aplicación no aumenta, ni tampoco la cantidad de memoria utilizada por otros procesos.que sin búfer de E/S en Linux

Esto me lleva a creer que la memoria está siendo consumida por la memoria caché del sistema de archivos - ya que no tengo la intención de leer estos datos durante mucho tiempo espero pasar por alto los búferes del sistema, de manera que mis datos se escriben directamente en disco. No tengo sueños de mejorar el rendimiento o ser un súper ninja, mi esperanza es dar una pista al sistema de archivos de que no volveré para este recuerdo en el corto plazo, así que no dediques tiempo de optimización para esos casos.

En Windows me he enfrentado a problemas similares y solucioné el problema usando FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH - la memoria de las máquinas no fue consumida por mi aplicación y la máquina era más usable en general. Espero duplicar las mejoras que he visto pero en Linux. En Windows existe la restricción de escribir en trozos del sector, estoy contento con esta restricción por la cantidad de ganancia que he medido.

hay una manera similar a hacer esto en Linux?

Respuesta

6

El equivalente más cercano a las banderas de Windows que usted menciona que puedo pensar es abrir su archivo con los open(2) banderas O_DIRECT | O_SYNC:

O_DIRECT (Since Linux 2.4.10) 
      Try to minimize cache effects of the I/O to and from this file. In 
      general this will degrade performance, but it is useful in special 
      situations, such as when applications do their own caching. File I/O 
      is done directly to/from user space buffers. The O_DIRECT flag on its 
      own makes at an effort to transfer data synchronously, but does not 
      give the guarantees of the O_SYNC that data and necessary metadata are 
      transferred. To guarantee synchronous I/O the O_SYNC must be used in 
      addition to O_DIRECT. See NOTES below for further discussion. 

      A semantically similar (but deprecated) interface for block devices is 
      described in raw(8). 

Por supuesto, tratando de hacer la investigación sobre este indicador para confirmar que es lo que quiere Encontré this interesting piece diciendo que la E/S sin búfer es una mala idea, Linus lo describió como "daño cerebral". De acuerdo con eso, debes usar el madvise() para decirle al núcleo cómo almacenar las páginas en caché. YMMV.

2

como mi programa se ejecuta la cantidad de memoria disponible en la máquina cae muy rápidamente

¿Por qué es esto un problema? La memoria libre es memoria que no está sirviendo ningún propósito útil. Cuando se utiliza para almacenar en caché los datos, al menos existe la posibilidad de que sea útil.

Si uno de sus programas pide más memoria, cachés archivo será el primero que hay que ir. Linux sabe que puede volver a leer los datos del disco siempre que lo desee, de modo que solo obtendrá la memoria y le dará un nuevo uso.

Es cierto que Linux por defecto espera unos 30 segundos (esto es lo que el valor que solía ser de todos modos) antes de lavar escribe en el disco. Puede acelerar esto con una llamada al fsync(). Pero una vez que los datos se han escrito en el disco, hay prácticamente cero costo para mantener un caché de los datos en la memoria.

Viendo como se escribe en el archivo y no lee de ella, Linux probablemente supongo que estos datos es la mejor para tirar, con preferencia a otros datos en caché. Así que no pierda el esfuerzo tratando de optimizar a menos que haya confirmado que se trata de un problema de rendimiento.

+1

que es sólo un problema debido a que el efecto es el caché se está utilizando para algo que nunca se usará. El caché está tomado de otros que podrían usar y estoy viendo un aumento de E/S. – stuck

6

Puede utilizar O_DIRECT, pero en ese caso es necesario hacer el bloque IO mismo; debe escribir en múltiplos del tamaño del bloque FS y en los límites del bloque (es posible que no sea obligatorio, pero si no lo hace, su rendimiento succionará x1000 porque cada escritura desalineada necesitará una lectura primero).

Otra manera mucho menos impactante de detener sus bloques usando la memoria caché del SO sin usar O_DIRECT, es usar posix_fadvise (fd, offset, len, POSIX_FADV_DONTNEED). En los kernels de Linux 2.6 que lo admiten, esto descarta inmediatamente (limpia) los bloques del caché. Por supuesto, necesitas usar fdatasync() o algo así primero, de lo contrario los bloques pueden estar sucios y, por lo tanto, no se borrarán de la memoria caché.

Probablemente es una mala idea de fdatasync() y posix_fadvise (... POSIX_FADV_DONTNEED) después de cada escritura, pero en su lugar espere hasta que haya hecho una cantidad razonable (50M, 100M tal vez).

Así que en breve

  • después de cada (parte significativa) de escrituras,
  • fdatasync
  • llamada seguido de posix_fadvise (... POSIX_FADV_DONTNEED)
  • Esto eliminará los datos en un disco e inmediatamente eliminarlos desde el caché del sistema operativo, dejando espacio para cosas más importantes.

algunos usuarios han encontrado que las cosas como archivos de registro de rápido crecimiento pueden soplar fácilmente cosas "más útil" fuera de la caché de disco, lo que reduce caché golpea mucho en una caja que tiene que tener una gran cantidad de caché de lectura , pero también escribe registros rápidamente. Esta es la principal motivación para esta característica.

Sin embargo, como cualquier optimización

a) usted no va a necesitar por lo

b) No haga que (todavía)

Cuestiones relacionadas