Van egy PHP programom, ami viszonylag erőforrásigényes szövegfeldolgozást végez (10-12 órán át fut).
Bár három (szöveges) eredményfájlra van szükség, úgy döntöttem, hogy egyetlen kimenetet gyártok, amelyben soronként jelzem az első karakterrel, hogy melyik kimenetbe szánom az adott sort. Utána három greppel szortírozom a sorokat: grep "^a" ...; grep "^b"...
Ez utóbbi hármas grep valahogy egész biztosan feljavítható, ugyanis háromszor kell átnyálazni a fájlt, háromszor kell ránézni minden sorra, pedig elvileg elég lenne csak egyszer. Ha van ötletetek szép, időtakarékos megoldásra (pl. egy C/C++ program formájában), örömmel veszem. Akár még a PHP program szintjén is elfogadok tanácsot (pl. nyugodtan irányítsam háromfelé, nem lesz attól sokkal hosszabb a futás...)
Úgy is fogalmazhatnék, hogy egy általánosabb grep-re lenne szükségem, ami nem csak "igen-nem" jelleggel nézi valaminek a meglétét (és aszerint írja ki vagy sem), hanem lehetővé tenne többfelé terelést is az első karakter alapján.
- 1328 megtekintés
Hozzászólások
PHP script 12 órán át fut? Jó ég. Mindenképpen kell rá írni valami alternatívát egy natív nyelven és cron-ból futtatni, a PHP csak az eredményét dolgozza fel. miért nincs három külön fájl, ha amúgy is három kiemenetre szánod?
- A hozzászóláshoz be kell jelentkezni
Elsőre perllel vagy akár shell scripttel is lehetne próbálkozni. :)
- A hozzászóláshoz be kell jelentkezni
perl<3 +1
- A hozzászóláshoz be kell jelentkezni
Igazából a titkos fegyver a mysql LOAD DATA INFILE -ja szokott lenni, ha olyan a kiinduló anyag. Aztán sql-ből már elég tágak a lehetőségek. :)
- A hozzászóláshoz be kell jelentkezni
Hát, ez egy ilyen helyzet: egy bemeneti fájlnak minden sorából három sor keletkezik, három fájlba. :-)
- A hozzászóláshoz be kell jelentkezni
ennyiből nekem nem világos, hogy miért jobb markert tenni a kimenetbe, és az alapján utólag szétválogatni, miért nem jobb egyből több külön fájlba kiírni...
- A hozzászóláshoz be kell jelentkezni
Mekkora a szövegfájl, amit szét kell válogatni?
Mennyi a grep futási ideje a mostani módszereddel? Hány százalékos javulást vársz a mostani PHP+grep együttes futási idejéhez képest? Mennyi időt tudsz feláldozni az idődből ennek a gyorsulásnak az eléréséhez? Esetleg a PHP leváltásával sokkal nagyobb gyorsulás érhető el?
- A hozzászóláshoz be kell jelentkezni
Amiatt láttam jobbnak markereket használni, mert több szegmenst dolgozok fel, és a wget-eket indító shell szkriptben szeretem megadni a kimenet nevét; így gyorsabbnak és egyszerűbbnek tűnt a megoldás. Meg az örökös (többfelé történő) fájlnyitogatás is idő. De lehet, hogy ezt tényleg átgondolom, és inkább GET paraméterként adom meg a kimeneti fájl(ok) nevét.
A teljes (PHP+grep) futásidőnek kb. 20%-át teszi ki a grep; ennek a harmadolódásában bízom.
A PHP leváltásával persze lehetne gyorsítani, de annyira bonyolult (sok hónapon keresztül, sok ember ötleteinek bevonásával készült), hogy nem merném bevállalni az átírását. A fő PHP program kb. 600 soros, de vannak egyéb PHP alkatrészek is.
- A hozzászóláshoz be kell jelentkezni
Eloszor is ne wgettel csinald, hanem php-vel egyenesen, masreszt pedig ha egyszerre nyitsz 3 file handlert, akkor mindharom file meg van nyitva, es egymas utan irkal bele a szal, nem kell mindig ujranyitogatnia. Szerintem igy tudod a leggyorsabban megoldani (marmint ha PHP-nel maradunk persze).
- A hozzászóláshoz be kell jelentkezni
Először direktben PHP-vel csináltam, de meglepő módon nagy fájlok esetén sokkal-sokkal lassabb volt (persze ez lehet php.ini beállítási kérdés; de ezt tapasztaltam). De az egyből-háromfelé írkálást még ki fogom próbálni, köszi.
- A hozzászóláshoz be kell jelentkezni
Nem is értem. Ha már feldolgozod az adott sort, miért nem teszed be a megfelelő (kimeneti) file-ba?
- A hozzászóláshoz be kell jelentkezni
Minden feldolgozott bemeneti sornak 3 kimenete van.
- A hozzászóláshoz be kell jelentkezni
Ha mindenképpen "válogatni" akarsz, akkor egy awk-os megoldás, bár nem biztos, hogy gyorsabb:
#!/usr/bin/gawk -f
BEGIN { FS = "" }
($1 == "a") { print $0 >> "a.txt" }
($1 == "b") { print $0 >> "b.txt" }
($1 == "c") { print $0 >> "c.txt"
Természetesen, előtte törölni kell a fájlokat: a.txt, ...
- A hozzászóláshoz be kell jelentkezni
Köszi az első konstruktív ötletet! Ha if/else-eket teszek be (hogy ne fusson rá felesleges vizsgálatokra), azzal még 15%-ot gyorsul, de így is világbajnok sebességű megoldás! Hálás köszönet még egyszer!
- A hozzászóláshoz be kell jelentkezni
az első konstruktív ötletet
*facepalm* a megoldas az eredeti felvetesre jo, de azert gondolkodj el a fentieken es csinald meg rendesen...
- A hozzászóláshoz be kell jelentkezni
Rendben :-)
- A hozzászóláshoz be kell jelentkezni
De, ilyen feladatokra jó eséllyel az awk a leggyorsabbak között van, mert nincs "megterhelve" sok egyéb funkcióval.
Amit a fentin gyorsítani lehet, az a mezőkre tördelés kiküszöbölése, amit gnu awk-kal így lehet elérni:
awk -vFIELDWIDTHS='1 1' '{ print > $1 ".txt"}' log
Tkp. így is tördel mezőt - összesen kettőt, az első, és (azt már feleslegesen) a 2. karaktert teszi $1-be és $2-be.
Az üres FS (= minden karakter 1-1 mező) felálláshoz képest már a 4M-s példafájlomon is láttat különbséget a time:
$ time awk -vFIELDWIDTHS='1 1' '{print > $1 ".txt"}' log
real 0m0.094s
user 0m0.080s
sys 0m0.016s
$ time awk -FS='' '{ print > $1 ".txt"}' log
real 0m0.134s
user 0m0.100s
sys 0m0.028s
Pardon, az üres FS-nek parancssorban a -F='' felel meg, de úgy még lassabb:
$ time awk -F='' '{ print > $1 ".txt"}' log
real 0m0.320s
user 0m0.284s
sys 0m0.032s
Nnnna, ezt is túlragoztam.
- A hozzászóláshoz be kell jelentkezni
Príma, köszönöm!!
- A hozzászóláshoz be kell jelentkezni
A te két változatod gyorsabb mint az enyém. Egy kb. 263 MB-os fájlon kipróbáltam, és az enyém kb. 50%-kal volt lassabb. Viszont a te két változatod kevesebb mint 1 másodpercben tért el, így a nagy nyereség -- szerintem -- a feltételvizsgálat helyetti 'print > $1 ".txt"' megoldásnak köszönhető. Ez rendben is van. A 263 MB-os fájlon az eredmény nálam:
$ time awk -vFIELDWIDTHS='1 1' '{print > $1 ".txt"}' log
real 0m31.959s
user 0m26.260s
sys 0m1.590
Ami meglepő lett, az az, hogy ugyanezen a fájlon a 3 grep sokkal gyorsabb:
$ time grep '^a' log > a.txt; time grep '^b' log > b.txt; time grep '^c' log > c.txt
real 0m7.704s
user 0m4.400s
sys 0m0.920s
real 0m9.833s
user 0m1.910s
sys 0m0.720s
real 0m8.566s
user 0m2.090s
sys 0m0.880s
Rövid töprengés után arra jutottam, hogy az lehet az oka, hogy a szabad memória nagyobb mint a fájl, így cache-ből olvassa a grep (is), ezért lett gyorsabb. Mivel a mérés előtt is futtattam már a te megoldásodat is, ezért az is a cache-ből olvasott. A mérést fordított sorrendben elvégezve, gyakorlatilag ugyanezt az eredmény kaptam.
Mivel az indításkor a szabad memória kb. 500 MB volt, így készítettem egy 2,63 GB-os tesztfájlt, és megismételtem a tesztet:
$ time grep '^a' log > a.txt; time grep '^b' log > b.txt; time grep '^c' log > c.txt
real 1m41.283s
user 0m46.990s
sys 0m7.650s
real 1m16.525s
user 0m21.610s
sys 0m9.190s
real 1m25.122s
user 0m21.030s
sys 0m8.410s
$ time awk -vFIELDWIDTHS='1 1' '{print > $1 ".txt"}' log
real 5m8.724s
user 4m22.750s
sys 0m15.950s
$ time awk -F '' '{print > $1 ".txt"}' log
real 5m3.136s
user 4m19.250s
sys 0m14.440s
És a grep(ek) még mindig gyorsabb(ak). A két változatod között még mindig elhanyagolható a különbség.
- A hozzászóláshoz be kell jelentkezni