Zdravím, mám problém. Psal jsem skript, který zpracovával soubor, ve kterém bylo cca 300.000 řádků (četl jsem soubor po řádku a s každým řádkem prováděl to samé) a ejhle, zjistil jsem, že spotřeba paměti strašně moc roste. Různě jsem experimentoval a nakonec jsem stvořil takovýhle primitivní kód:
index.php:
<?php
require("./fce.php");
$a = 10;
for($i = 0; $i <= 20; $i++)
{
test($a);
echo "Pamet:".memory_get_usage()."<br>";
flush();
}
?>
a soubor fce.php:
<?php
function test($a)
{
for($j = 0; $j <= 8; $j++) $w[] = $a;
}
?>
Jde mi o to, že když v té funkci test() jde $j od 0 do 7 (a méně), vypisuje memory_get_usage() stale stejne cislo (coz je asi logocké, není důvod, aby skript zabíral více paměti), ovšem při $j od 0 do 8 a více se využívání paměti stále zvětšuje...
Tušíte někdo proč, prosím?
Nechápu ... :\
Jediné, co mě napadá, tak po každém "kole" provést unset(), případně clearstatcache().
Potom už se dá fungovat i s X-megabajtovými proměnnými.
no v podstate jde o to, ze kdyz je v te fci test() "for($j = 0; $j <= 7; $j++)", vypisuje to:
Pamet:42824
Pamet:42904
Pamet:42904
Pamet:42904
Pamet:42904
Pamet:42904
Pamet:42904
Pamet:42904
...
...
Zatimco pokud tam je vyse uvedene, vypisuje to:
Pamet:42972
Pamet:43084
Pamet:43148
Pamet:43180
Pamet:43212
Pamet:43244
Pamet:43276
Pamet:43308
Pamet:43340
...
...
A unset nema zadnej vliv....
a clearstatcache() taky ne...ach jo... :-/
Moment, ... čeho chceš vlastně dosáhnout?
no timhle konkretnim kodem samozrejme niceho....ale jde mi o to, aby kdyz zpracovavam skriptem nejaky dlouhy soubor (napr.), nedoslo k tomu, ze zacne vyuzivat tolik pameti, az se polozi...
zkratka me zajima, proc skript vyzaduje stale vice pameti...ackoli dela stale to same, funkce vzdy vytvori lokalni pole se stejnym poctem prvku, ktere maji stejnou hodnotu, ale vyuziva stale vice pameti....
když jsem si s tím hrál tak od 16 už hodnoty nerostly, první byla větší a ostatní stejně velké: 19456,19424,19424,...
když se počet opakování zadá jako proměnná tak se výše popisovaný efekt ztratí - hodnoty rostou
http://ds.mysteria.cz/memtest/index.php?f=200
(maximální hodnota f=200)
<?php
require("./fce.php");
$a = 10;
for($i = 0; $i <= 20; $i++)
{
test($a,$f);
echo "Pamet: $f x : ".memory_get_usage()."<br>";
flush();
}
?>
<?php
function test($a,$f)
{
for($j = 0; $j <=$f; $j++) $w[] = $a;
}
?>
nemas definovany rozsah. Takze, dokud meni str a boolean a na integer, tak potrebuje pamet na vic. Dal uz pamet nepotrebuje, vyuziva funkcea volne misto z minula
peta: a co se změní když se v cyklu zadám 8 místo 7?
ds: Ze by z 64bitu na 128bitu?
On vůbec neni úplně dobrej nápad zpracovávat v PHP velký soubory no... aspoň takovou já mám zkušenost. Musíš celý ten soubor zpracovat najednou? Nemůže ten skript zpracovat třeba 100 řádek, pokud se produkuje nějaký výsledek, tak ho uložit, a reloadovat se? (takhle já jsem obcházel ten time limit 30 sekund :-)
ds (ds.mysteria.cz)
preklep, a=na
- jde o to, ze na zacatku mas string ""
- pak nejaka funkce zmeni string na boolean 0/1
- pri ++ pak zjisti, ze boolean je nedostacujici a meni na vyssi typ. Otazka je, co to je. Jestli prida jen bit, viz Tomik, nebo udela -127..128
- pak nasleduje 0..255 (byte)
- integer (-32000..32000+-)
a nebo to teda dela po bitech. Ale o tom zas tolik nevim, neboli mne to. Zas tak setrit pameti nepotrebuji.
Zkus na zacatku definovat, ze $i=99; pred cyklem, co to udela? Jestli bude v tom rozdil. Pak to vrat do puvodniho stavu a zkus odpocitavat opacne $i-- .
<HTML>Otazkou je, jak velky je tvuj 300 000 radku dlouhy soubor (nevim co v nem mas a jestli je na radku jedna veta nebo 1000 znaku) a jake operace jsi s nim delal</HTML>
peta: jenom drobnost, k tem typum
boolean: nabyva hodnot FALSE nebo TRUE (muze byt definovano ruzne, treba 0 a 1, nebo treba FALSE=1, TRUE=not FALSE, ale to je jedno), v pameti zabira 1 byte
-127..128, to je v C definici signed char, zabira v pameti 1 bajt (1 bit znamenko+7bitu hodnota)
0..255, v C je to unsigned char, nebo treba uint_8, zabira take 1 bajt pameti
-32768..+32767 (signed int) zabira 2 bajty (1 bit znamenko, 15bitu hodnota)
0..65535 (unsigned int) zabira take 2 bajty (16bitu hodnota)
dalsi je long int, zabira 4 bajty
pak dalsi typ pojmenovany ruzne zabira 8 bajtu
(a to jsou jenom celociselne typy, realna cisla maji take ruzne typy, v pameti je to vetsinou mezi 6 a 12? bajty, zalezi na rozsahu)
po jednotlivych bitech se to rozhodne nedela, uvedomte si jak je organizovana pamet PC, ta je po bajtech, ne po bitech. takze i kdyz si ulozis 1 bit, sezere ti celej 1 bajt (i kdyz 7 zbyvajicich bitu nebude pouzito)
<HTML>Mike: jenom drobnost k tem typum... vidim ze o tom neco vis jen jsi zapomel uvest zavislost velikosti na platforme ... int s 2b platilo kdysi nyni to na winXP vypada nasledovne:
cout << sizeof(short int) << '\n';
cout << sizeof(int) << '\n';
cout << sizeof(unsigned int) << '\n';
cout << sizeof(unsigned long int) << '\n';
cout << sizeof(double) << '\n';
cout << sizeof(long double) << '\n';
Vystup:
2
4
4
4
8
12</HTML>
Mike (specialfx.xf.cz)
"
boolean: v pameti zabira 1 byte
1 byte = 8 bitu, jsi si tim jist, ze prave 1 byte? :)
"
<HTML>Ja si tim jisty jsem, typ boolean zabira (a co vim tak vzdycky zabiral) 1byte i kdyz se s nim pracuje jako s 1 bitovym</HTML>
Spise se zeptejte jakym zpusobem se pracuje s pameti, pak se ptejte kolik co zabira.
V pameti se nepracuje s 1bitovym prostorem, ale minimalne se 4bitovym rozsahem. U pocitacu pak minimalne s 8bity. Takze pokud chcete pracovat s 1bitem, tak si musite ukosnout prave celych 8 bitu pameti (00000001 = 0x01). Datove typy pak jen urcuji rozsah pametoveho prostoru. Typ char je nejnizsi 8bitovy, coz je 256 ruznych kombinaci, a zabira 1 byte. Typ boolean v Ccku neexistuje, ale v pascalu jo. Jenze to neni vlastne nic jineho nez typ char, ktery nabyva jen dvou hodnot (z 8bitu si vsima jen jednoho bitu).
To co ukazal Richard, tak zalezi na pouzitem procesoru. U 8bitovem procesoru zabira typ int 16bitu (2B). U 16bitovem procesoru uz 32bitu (4B).