Newsgroup: it.comp.www.php
Titolo: Problemi di memoria (3)

Grazie al vostro aiuto ho risolto il mio precedente problema (col
passaggio da php4 a php5 il caricamento degli array multidimensionali d�
problemi di memoria) per quanto riguardava la lettura dei dati contenuti
in un file.
Adesso ho un ultimo problema da risolvere. Ed � molto importante, per me.
Ho necessit� assoluta di caricare in memoria un array ed il seguente
codice d� il nuovo problema di memoria:
<?php
//Carico nell'ARRAY $e[][][] le estrazioni
$fd=fopen("../archivio.txt","r");
while(!feof($fd))
	{
	$es = $es + 1;
	$riga = fgets($fd,120);
	$e[$es][0][1] = substr($riga,0,2);
	$e[$es][0][2] = substr($riga,2,2);
	$e[$es][0][3] = substr($riga,4,2);
	$e[$es][0][4] = substr($riga,6,2);
	$e[$es][0][5] = "00";
	$xxx = 6;
	for($a1 = 1; $a1 < 12; $a1 = $a1 + 1)
		{
		for($a2 = 1; $a2 < 6; $a2 = $a2 + 1)
			{
			$xxx = $xxx + 2;
			$e[$es][$a1][$a2] = substr($riga,$xxx,2) * 1;
			}
		}
	}
fclose($fd);
//FINE Carico nell'ARRAY $e[][][] le estrazioni
$prox=$es;
?>
Perdonatemi se pongo sempre la stessa domanda: se un archivio � di soli
493Kb... come fa ad occupare una memoria di 16Mb ???
Grazie per l'attenzione
Salvatore Paci
-- 
questo articolo e` stato inviato via web dal servizio gratuito 
http://www.newsland.it/news
 segnala gli abusi ad 
ab...@newsland.it

493Kb... come fa ad occupare una memoria di 16Mb ???
Beh... facilmente. 493 Kb sono i dati in forma testuale, ogni numero sono
due byte.
Ma se ogni numero e' un intero a 64 bit, e ogni array richiede un nodo ed
e' allocato singolarmente con gestione GC indipendente, ogni numero avra'
bisogno di 8+(16*3)+8+8 = 72 byte, occupando 36 volte piu' spazio di quel
che pensi.
Dunque non 493 Kb ma 17 megabyte -- e tu ne hai solo sedici.
Ma, se la versione precedente del PHP usava interi a 32 bit, ti sarebbero
serviti solo circa 9 Mb. Ecco perche' prima ti funzionava, e adesso no.
Potresti provare a collassare l'array in un array 2D, condensando i primi
cinque termini dell'asse k in cinque byte con Chr o pack/unpack.
Francamente, io riguarderei piuttosto l'algoritmo e/o userei un database.
Leonardo
-- 
Linten addie toorin addie,
Linten addie toorin ee,
Linten lowrin lowrin lowrin,
The barnyards of Delgaty

 Dunque non 493 Kb ma 17 megabyte -- e tu ne hai solo sedici.
----
Qui avviene qualcosa di strano (per me che lo ignoro).
In questo momento l'archivio contiene 4200 righe (di 120 caratteri
ciascuna)
ho modificato il codice in modo da caricare nell'array soltanto dalla riga
4000 fino alla 4200 eppure mi d� sempre lo stesso errore di memoria.
Facendo il calcolo (201 righe per 120 caratteri per 36) ottengo 868320 e
quindi meno di un Mb.
Eppure...
ciao


4000 fino alla 4200 eppure mi d� sempre lo stesso errore di memoria.
Fammi vedere un po' il codice modificato...?


 Lo deve fare? Cosi' a cazzotto mi sembrerebbe di no.
Allora... questa impostazione di archivio proviene da una vecchia 
applicazione in VB6.
L'array era est(1 to 5000, 5, 1 to 5)
il secondo elemento (5) dato che non � specificata da dove deve partire... 
parte da 0 e l� ci mettevo la data.
Esempio:
prima riga=
070920090102030405xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
est(1,0, 1) = 07 giorno
est(1,0, 2) = 09 mese
est(1,0, 3) = 20 secolo
est(1,0, 4) = 09 anno
est(1,0, 5) = lo impostavo a zero, tanto non lo utilizzavo. Ma almeno 
mantenevo i cinque elementi
est(1,1, 1) = 01 primo elemento ecc ecc
Ecco il codice modificato che legge 
www.salvatorepaci.it/archivio.txt
<?php
       function getarc($x1, $x2, $x3)
        {
                GLOBAL  $archfd;
                if (!isset($archfd))
                        if (!($archfd = fopen('../archivio.txt', 'r')))
                                die('Impossibile aprire archivio');
                $x1--; $x2--; $x3--;
                $linear = ($x1*11+$x2)*5+$x3;
                $rigax   = floor($linear / 55);
                $colonna= $linear % 55;
                fseek($archfd, $rigax * 120 + $colonna * 2 + 8, SEEK_SET);
                return floor(fread($archfd, 2));
        }
echo("<body background=\"sfondo.gif\">");
$fd = fopen("../archivio.txt", "r");
//calcolo il numero totale delle righe
while(!feof($fd))
 {
 $riga = fgets($fd,4096);
 $ultima++;
 }
fclose($fd);
?>
Con questo codice leggo tutti dati meno i primi 8 caratteri (la data)
Per la parte che stavo gestendo ieri... mi andava bene.
Per caricare TUTTO in memoria e lavorare su un solo array, invece, no.
Grazie per la pazienza :)
Salvatore 

 868320 e quindi meno di un Mb.
Per prima cosa devi moltiplicare per 4. I numeri, indipendentemente dal 
valore che ci metti, occupano 4 byte (un int) o 8 byte (un float). 
Raddoppia se sei su un sistema a 64 bit.
Inoltre ci sono due cose da considerare:
- PHP5 occupa piu` memoria di PHP4, perche` ha piu` funzionalita` di base.
- Un array in PHP non e` un array normale, ma una tabella hash. Ogni 
elemento non occupa solo il suo spazio, ma anche spazio per l'indice e per 
la lista delle collisioni. Inoltre non viene allocato byte per byte, ma 
chuck per chunk, per ottimizzare i malloc().
Quindi il tuo array da 1 MB, con le considerazioni di cui sopra (x4 per 
gli int, x3 per gli indici e le collisioni, x"qualcosa" per i chunk) 
occupa ALMENO 12 MB solo di array. Aggiungici la memoria per lo script, 
per i suoi dati e per i dati "internamente usati" da PHP e sfondi 
tranquillamente i 16 MB anche su 32bit.
Bye.