error "no hay suficiente memoria para realizar esta operacion"

478 views
Skip to first unread message

carlosmupe

unread,
May 25, 2017, 3:56:27 PM5/25/17
to Comunidad de Visual Foxpro en Español
Hola estimados, tengo un archivo de texto con 15 millones de registros, cada linea la ingreso a un arreglo ya que el archivo viene delimitado por tabs

LOCAL ARRAY ArrayElementos(1)

=FSEEK(nfile, 0, 0)
=FGETS(nfile,8192)
DO WHILE !FEOF(nfile)
   laLinea=FGETS(nfile,8192)
   ALINES(ArrayElementos,laLinea,CHR(9))
   IF !EMPTY(laLinea)
       ** realizo operaciones
   endif
enddo

el problema es que en algún minuto fox me arroja el error que no hay suficiente memoria para continuar la operación, hay alguna forma de evitar este mensaje? 


saludos y gracias

ZeRoberto

unread,
May 25, 2017, 4:49:16 PM5/25/17
to publicesvfoxpro
En vez de pasarlo a un arreglo porque no lo pones en un dbf?

Saludos

carlosmupe

unread,
May 25, 2017, 5:18:59 PM5/25/17
to Comunidad de Visual Foxpro en Español
hola estimado gracias por la respuesta, el problema de ello es que supera los 2 gb en una tabla dbf.

saludos y gracias 

ZeRoberto

unread,
May 25, 2017, 6:27:58 PM5/25/17
to publicesvfoxpro
Oh es 15 millones, y que datos guardas ahi, y si lo separas por meses y años por archivos?

Saludos

Carlos Miguel FARIAS

unread,
May 26, 2017, 7:00:09 AM5/26/17
to Grupo Fox
Aunque un arreglo de vfp puede manejar 2 gb de elementos, eso se da en vfp 9 y no anteriores, además tienes que tener memoria RAM suficiente para manejar ese volumen de datos (15 millones por 20 bytes ya supera lo que puede direccionar el Windows).
Tal como te sugirieron, vas a tener que pasar los datos a un SGBD externo ya que las dbf no lo soportan. Sugiero Firebird, por lo simple de instalar, SQLite, aguantaría el volumen de datos pero la inserción sería en extremo muy lenta.
También puedes usar postgresql, que es libre en todas las versiones, y esa cantidad de registros cae en su rango de tablas casi medianas.
Saludos: Miguel, La Pampa (RA)
Larga Vida y Prosperidad
Que la Fuerza los acompañe

El 25 de mayo de 2017, 19:27, ZeRoberto <zero...@gmail.com> escribió:
Oh es 15 millones, y que datos guardas ahi, y si lo separas por meses y años por archivos?

Saludos

Fidel Charny

unread,
May 26, 2017, 8:01:06 AM5/26/17
to Comunidad de Visual Foxpro en Español
Para el caso, el array que genera Alines() es sobre una cadena cuyo máximo tamaño es de 8192 caracteres, por lo que no debería ser el problema.
Con 15 millones de registros habrá que ver qué tamaño tiene el archivo que se abre en bajo nivel (Maximum file size accessible via low level file functions 2 gigabytes ) y si es menor a 2 Gb ver cuales son las operaciones que realiza con el array obtenido. Dicho sea de paso, la comparación de Empty(laLinea) debería ser anterior a Alines().
También es necesario saber si los registros del archivo abierto en bajo nivel están separados por CHR(13) para justificar el uso de FGETS().
Me parece que quedaría mejor escrito algo así:
PROCEDURE Leer
LPARAMETERS tcFileName
TRY
    LOCAL i
,;
        lcLinea
,;
        lnHandle
,;
        lnLines
,;
        loex AS
Exception

    LOCAL ARRAY laLines
(1)    
   
    lnHandle
= FOPEN(m.tcFileName,0)
    IF lnHandle
# -1
       
*=FSEEK(m.lnHandle,0,0)            && se necesita si antes se movió el puntero
        lcLinea
=FGETS(m.lnHandle,8192)    && salta encabezado
        DO WHILE
!FEOF(m.lnHandle)
            lcLinea
= FGETS(m.lnHandle,8192)
            IF
!EMPTY(m.lcLinea)
                lnLines
= ALINES(laLines,m.lcLinea,1+2,CHR(9))
                FOR i
= 1 TO m.lnLines
                   
* Operaciones con laLines[i]
                NEXT
            ENDIF
        ENDDO
    ENDIF
   
CATCH TO loex
    loex
.UserValue = PROGRAM()
   
* ShowError(loex) && muestra el error

FINALLY
    IF m
.lnHandle # -1
        FCLOSE
(m.lnHandle)
    ENDIF

ENDTRY



El viernes, 26 de mayo de 2017, 8:00:09 (UTC-3), Miguel escribió:
Aunque un arreglo de vfp puede manejar 2 gb de elementos, eso se da en vfp 9 y no anteriores, además tienes que tener memoria RAM suficiente para manejar ese volumen de datos (15 millones por 20 bytes ya supera lo que puede direccionar el Windows).
Tal como te sugirieron, vas a tener que pasar los datos a un SGBD externo ya que las dbf no lo soportan. Sugiero Firebird, por lo simple de instalar, SQLite, aguantaría el volumen de datos pero la inserción sería en extremo muy lenta.
También puedes usar postgresql, que es libre en todas las versiones, y esa cantidad de registros cae en su rango de tablas casi medianas.
Saludos: Miguel, La Pampa (RA)
Larga Vida y Prosperidad
Que la Fuerza los acompañe
El 25 de mayo de 2017, 19:27, ZeRoberto <zero...@gmail.com> escribió:
Oh es 15 millones, y que datos guardas ahi, y si lo separas por meses y años por archivos?

Saludos

carlosmupe

unread,
May 26, 2017, 9:26:49 AM5/26/17
to Comunidad de Visual Foxpro en Español
Estimados gracias por las respuestas, efectivamente en operaciones inyecto la información a una base de datos mysql, tambien reviso la integridad de datos codigos existentes, etc.., el problema es al momento de cargar el arreglo con las lineas del archivo donde me arroja el error, el archivo es de texto, separado por tabuladores y saltos de carro en cada linea, es por ello que utilizo el fgets, no se si reemplazar la funcion "ALINES", con variables por cada elemento y usando substr, corrija el problema.

me da la sensación que el arreglo mantiene en memoria los registros de las lineas anteriores por eso es que colapsa, intente realizar un release a la variable y volver a declarar pero tampoco me funciono, habra alguna forma de limpiar de memoria el arreglo despues de un par de ciclos quizás eso resuelva el problema.

saludos

Fidel Charny

unread,
May 26, 2017, 11:20:14 AM5/26/17
to Comunidad de Visual Foxpro en Español
La función Alines() crea o redimensiona el Array de acuerdo a su determinación. No hay por qué preocuparse por eso.
No dice qué tamaño tiene el archivo de texto, algo que puede ser fundamental por la cantidad de registros.
Si el tamaño del archivo es menor a 2 GB. entonces el problema tiene que estar en el procesamiento de cada línea.
Puedes intentar liberar la memoria, aunque no puedo asegurar que solucione tu problema.
*****************************************************************************************
* PROCEDURE....:     ReduceMemory()
* Author......:  Bernard Bout
* Date........:  05/12/2007 3:03:15 PM
* Returns.....:
* Parameters..:
* Notes.......:  reduces memory usage for vfp
*****************************************************************************************
PROCEDURE
ReduceMemory()

Declare Integer SetProcessWorkingSetSize In kernel32 As SetProcessWorkingSetSize  ;
   
Integer hProcess , ;
   
Integer dwMinimumWorkingSetSize , ;
   
Integer dwMaximumWorkingSetSize
Declare Integer GetCurrentProcess In kernel32 As GetCurrentProcess
nProc
= GetCurrentProcess()
bb
= SetProcessWorkingSetSize(nProc,-1,-1)
ENDPROC

carlosmupe

unread,
May 26, 2017, 11:25:04 AM5/26/17
to Comunidad de Visual Foxpro en Español
gracias estimado, realizare algunas pruebas y comentare.

saludos

Víctor Hugo Espínola Domínguez

unread,
May 26, 2017, 12:20:44 PM5/26/17
to publice...@googlegroups.com
Según mi cálculo su archivo tiene 120 GB!

Creo que podría intentar dividiendo en 60 o más partes para luego procesar cada parte, otra opción es usar un lenguaje más moderno que pueda leer archivos grandes.

Saludos,
Víctor.
Lambaré - Paraguay.

ZeRoberto

unread,
May 26, 2017, 1:10:58 PM5/26/17
to publicesvfoxpro
Pero no entiendo para que los cargas en un array? puedes ir leyendo la linea e ir insertando en el MySQL

carlosmupe

unread,
May 26, 2017, 3:54:54 PM5/26/17
to Comunidad de Visual Foxpro en Español
estimado la carga en el arreglo era por comodidad ya que el archivo trae varios campos 15 aprox. por linea separadas por el caracter TAB. al llevarlo al array me genera 15 elementos los cuales accedo facilmente array[1]=nombre, array[2]=apellido, etc..
es por ello que lo uso, también podría recorrer la linea y almacenar en 15 variables cada campo, usando AT y substr. no he probado si esto me soluciona el error me imagino que si.


saludos y gracias.

ZeRoberto

unread,
May 26, 2017, 5:57:20 PM5/26/17
to publicesvfoxpro
Ah yo pensaba que cargabas un bloque de datos ahí y después hacías el insert

Rodolfo Ortiz González

unread,
May 29, 2017, 10:51:29 AM5/29/17
to publice...@googlegroups.com
Hola Carlos.

Has un prg con lo siguiente:

REDUCEMEMORY()

FUNCTION ReduceMemory()
  DECLARE INTEGER SetProcessWorkingSetSize ;
    IN kernel32 AS SetProcessWorkingSetSize ;
    INTEGER hProcess , ;
    INTEGER dwMinimumWorkingSetSize , ;
    INTEGER dwMaximumWorkingSetSize
  DECLARE INTEGER GetCurrentProcess ;
    IN kernel32 AS GetCurrentProcess
  nProc = GetCurrentProcess()
  bb = SetProcessWorkingSetSize(nProc,-1,-1)
ENDFUNC

Y tienes 2 chances.

1- Metelo después de finalizar tu if de cuando haces las operaciones.

 IF !EMPTY(laLinea)
       ** realizo operaciones
   endif
  DO REDUCEMEMORIA


2- Ejecútalo después de "X" tiempo.

Y nos cuentas que tal, saludos!



El 26 de mayo de 2017, 16:57, ZeRoberto <zero...@gmail.com> escribió:
Ah yo pensaba que cargabas un bloque de datos ahí y después hacías el insert
Reply all
Reply to author
Forward
0 new messages