2008-09-24 3 views
8

Hace una reducción de hash en Perl mientras elimina elementos.¿Se encoge un hash en Perl a medida que elimina elementos?

Más específicamente, tuve un programa en Perl que he heredado eso sería analizar un archivo enorme (1 GB) y la carga hasta un hash de hashes. Haría lo mismo para otro archivo y luego haría una comparación de diferentes elementos. El consumo de memoria fue enorme durante este proceso y, aunque agregué elementos de eliminación de hash en caso de que se utilizaran, el consumo de memoria no se vio afectado.

La secuencia de comandos fue extremadamente lenta y una memoria tan grande. Sé que no estaba bien diseñado, pero ¿alguna idea sobre el uso de la memoria hash?

Respuesta

7

En general, Perl no puede devolver la memoria al sistema operativo. Sin embargo, puede reutilizar la memoria internamente, lo que podría reducir la cantidad de memoria que necesita un programa.

Ver perlfaq3: How can I free an array or hash so my program shrinks?

Si la memoria utilizada por los hashes es excesiva (es decir> memoria física) que podría tie en un archivo en el disco. Esto reduciría en gran medida el uso de la memoria, pero tenga en cuenta que el acceso a una estructura en el disco es mucho más lento que el acceso a uno en la memoria. (Así es basura de disco.)

11

Es posible que desee comprobar hacia fuera algo así como DBM::Deep. Hace esas cosas vinculadas que Michael mencionó para que no tengas que pensar en eso. Todo está almacenado en el disco en lugar de en la memoria. Es poco menos que necesitar un servidor de base de datos más elegante.

Además, si desea realizar un seguimiento hacia abajo el cuello de botella, echa un vistazo a Devel::NYTProf, el nuevo picor en Perl perfiles que salió del New York Times, .

5

Si el hash es verdaderamente gigantesca, una mejor estrategia es utilizar probablemente un hash en el disco y deje el sistema operativo preocuparse de conseguir cosas dentro y fuera de la memoria. Me gusta especialmente Berkeley DB para almacenar grandes hashes en el disco, y el módulo Perl BerkeleyDB proporciona una interfaz con todas las funciones, incluida una API atada.

DBM::Deep también se puede utilizar como una gota en el reemplazo de hash, pero se basa en su propio formato. Esto puede ser molesto si su estructura necesita ser leída por otros sistemas (que no sean Perl).

4

Si las entradas en el segundo archivo son necesarias solo una vez (a medida que se leen), podría reducir el uso de memoria a la mitad.

Dependiendo de su algoritmo, que incluso podría ser capaz de simplemente mantener ambas filehandles abierta y un pequeño hash aún no utilizados-valores en la memoria. Un ejemplo sería una fusión o comparación de datos ordenados: solo necesita mantener la línea actual de cada archivo y compararla entre sí sobre la marcha, saltando hasta que cmp cambie.

Otro enfoque podría ser hacer varias pasadas, especialmente si tiene uno o más núcleos inactivos en su máquina. Abra los tubos de lectura y tenga subprocesos para alimentar los datos en fragmentos manejables preorganizados.

Para obtener algoritmos más genéricos, solo puede evitar pagar el tamaño de la memoria intercambiándolo por el costo de la velocidad del disco.

En la mayoría de los casos, la carga de todas las fuentes de datos en la memoria sólo se gana en tiempo de desarrollo - a continuación, que paga por ella en la huella y/o la velocidad cuando N se hace grande.

5

Acerca de la pregunta específica: No, la eliminación de las claves hash no reduce el consumo de memoria de su programa.

En cuanto al caso más general: la gran mayoría de los programas y los idiomas continuarán aferrándose a la memoria que han utilizado anteriormente, pero que no están utilizando actualmente. Esto se debe a que solicitar la asignación de memoria por parte del sistema operativo es una operación relativamente lenta, por lo que la conservan en caso de que se necesite más tarde.

Por lo tanto, si desea mejorar esta situación, necesitará reducir la cantidad máxima de memoria requerida por su programa, ya sea revisando sus algoritmos para no tener que acceder a la misma cantidad de datos a la vez, usando -dispositivo de almacenamiento (como el ya mencionado DBM :: Deep), o liberando espacio de variables innecesarias a Perl (déjelos fuera del alcance o configúrelos en undef) para que pueda ser reutilizado.

4

Solución alternativa: fork un proceso secundario que asigna toda esa memoria. Permita que pase algo de información agregada cuando haya terminado de hacer su trabajo; cuando muere el proceso bifurcado, su memoria irá con él. Un poco de dolor, pero funciona en algunos casos. Un ejemplo de un caso en el que esto ayuda sería si está procesando muchos archivos, cada archivo de uno en uno, solo unos pocos de los archivos son grandes, y se necesita mantener poco estado intermedio.

Cuestiones relacionadas