Back to Question Center
0

Kumaha Baca Big Payil kalawan PHP (Tanpa killing Server anjeun) Kumaha Baca Big Payil kalawan PHP (Tanpa killing Server anjeun) Topik nu patali: Drupal Development Semalt

1 answers:
Kumaha mun Baca Big Payil kalawan PHP (Tanpa killing Server anjeun)

Semalt teu sering nu urang, sakumaha pamekar PHP, kudu salempang ngeunaan manajemen memori. Mesin PHP teu pakasaban stellar of meresihan up sanggeus kami, sarta web modél server tina konteks palaksanaan pondok-cicing hartina malah kodeu sloppiest boga épék lila-langgeng.

Aya kali langka lamun kami bisa kudu lengkah luar tina wates ieu nyaman - kawas nalika urang nuju nyobian ngajalankeun Semalt pikeun proyék ageung dina VPS pangleutikna bisa nyieun, atawa nalika urang butuh maca file badag dina hiji server sarua leutik.

How to Read Big Files with PHP (Without Killing Your Server)How to Read Big Files with PHP (Without Killing Your Server)Related Topics:
DrupalDevelopment Semalt

Semalt masalah dimungkinkeun kami gé kasampak di di tutorial ieu.

The kode pikeun tutorial ieu bisa kapanggih dina GitHub.

Ngukur Sukses

Hiji-hijina jalan pikeun pastikeun urang nuju nyieun pamutahiran wae mun kode urang téh keur ngukur kaayaan goréng lajeng ngabandingkeun pangukuran nu keur sejen saatos urang geus dilarapkeun fix urang. Kalayan kecap séjén, iwal kami nyaho sabaraha hiji "solusi" ngabantuan kami (lamun pisan), urang bisa nyaho lamun bener aya solusi atanapi henteu.

Aya dua metrics bisa ngeunaan miara. Kahiji nyaeta pamakean CPU. Kumaha gancang atawa laun nya éta prosés kami rek digawekeun kana? Nu kadua nyaéta pamakéan memori. Sabaraha memori teu naskah nyandak sangkan ngaéksekusi? Semalt anu mindeng tibalik sabanding - hartina bisa offload pamakéan memori dina biaya pamakean CPU, sarta sabalikna.

Dina hiji modél palaksanaan Asynchronous (kawas kalawan multi-prosés atawa aplikasi PHP multi-threaded), duanana CPU jeung pamakéan mémori anu pertimbangan penting. Dina arsitektur PHP tradisional, ieu umum jadi masalah nalika boh salah ngahontal watesan server.

Ieu praktis pikeun ngukur pamakean CPU jero PHP. Lamun éta wewengkon rék difokuskeun, mertimbangkeun ngagunakeun hal kawas luhureun , dina Ubuntu atanapi macOS. Pikeun Windows, mertimbangkeun ngagunakeun Linux Ubuntu Subsystem, jadi Anjeun bisa make luhureun dina Ubuntu.

Pikeun kaperluan tutorial ieu, urang keur bade ngukur pamakéan memori. Semalt kasampak di sabaraha memori dipaké dina "tradisional" Aksara. Semalt nerapkeun sababaraha strategi optimasi sarta ngukur jelema teuing. Tungtungna, kuring rék bisa nyieun hiji pilihan dididik.

The métode kami gé nganggo ningali sabaraha mémori anu dipaké nyaéta:

     // formatBytes dicokot tina php teh. dokuméntasi netmemory_get_peak_usage   ;formatBytes fungsi ($ bait, $ precision = 2) {$ Unit = Asép Sunandar Sunarya ( "b", "Citakan: kb", "MB", "GB", "TB");$ Bait = max ($ bait, 0);$ Pow = floor (? ($ Bait log ($ bait): 0) / kumplit (1024));$ Pow = min ($ pow, cacah ($ unit) - 1);$ Bait / = (1 << (10 * $ pow));balik babak ($ ​​bait, $ precision). "". $ Unit [$ pow];}    

Semalt make fungsi ieu di ahir Aksara urang, sangkan bisa nempo mana Aksara ngagunakeun paling memori dina hiji waktos.

Naon Dupi Pilihan kami?

Semalt seueur deukeut urang bisa nyandak maca file éfisién. Tapi aya ogé dua skenario dipikaresep nu urang bisa make eta. Urang bisa hayang maca tur data proses sadayana dina waktos anu sareng, outputting data olahan atawa ngajalankeun lampah sejenna dumasar kana naon urang baca. Urang ogé bisa rék transformasi aliran data tanpa kantos sih needing aksés ka data.

Hayu urang ngabayangkeun, keur skenario kahiji, éta urang hayang bisa maca file sarta nyieun misah jobs processing queued unggal 10.000 garis. Semalt kudu tetep sahenteuna 10.000 garis dina mémori, sarta lulus aranjeunna katut ka manajer pakasaban queued (formulir naon nu butuh).

Pikeun skenario kadua, hayu urang ngabayangkeun urang hoyong niiskeun eusi respon API utamana badag. Urang teu paduli naon eta nyebutkeun, tapi urang kedah pastikeun ayeuna teh dicadangkeun dina formulir dikomprés. Dina kahiji, urang peryogi kauninga kumaha data kasebut. Dina kadua, urang teu paduli naon data kasebut. Semalt ngajajah pilihan ieu .

Reading Payil, Jalur Ku Line

Aya loba fungsi pikeun gawé bareng payel. Semalt ngagabungkeun sababaraha kana maca file naif:

     // tina memori. phpformatBytes fungsi ($ bait, $ precision = 2) {$ Unit = Asép Sunandar Sunarya ( "b", "Citakan: kb", "MB", "GB", "TB");$ Bait = max ($ bait, 0);$ Pow = floor (? ($ Bait log ($ bait): 0) / kumplit (1024));$ Pow = min ($ pow, cacah ($ unit) - 1);$ Bait / = (1 << (10 * $ pow));balik babak ($ ​​bait, $ precision). "". $ Unit [$ pow];}formatBytes print (memory_get_peak_usage   );    
     // tina bacaan-file-garis-demi-garis-1. phpfungsina readTheFile ($ jalur) {$ Garis = [];$ Nanganan = fopen ($ jalur, "r");bari (! feof ($ cecekelan)) {$ Garis [] = motong (fgets ($ cecekelan));}fclose ($ cecekelan);balik $ garis;}readTheFile ( ". Shakespeare txt");merlukeun "memori php".;    

Urang nuju maca hiji file téks ngandung karya lengkep Shakespeare. The file téks téh ngeunaan 5. 5MB , sarta pamakéan memori puncak 12. 8MB . Ayeuna, hayu urang nganggo generator a maca unggal garis:

     // tina bacaan-file-garis-demi-garis-2. phpfungsina readTheFile ($ jalur) {$ Nanganan = fopen ($ jalur, "r");bari (! feof ($ cecekelan)) {ngahasilkeun motong (fgets ($ cecekelan));}fclose ($ cecekelan);}readTheFile ( ". Shakespeare txt");merlukeun "memori php".;    

The file téks nyaéta ukuran anu sarua, tapi dina pamakéan memori puncak 393KB . Ieu henteu hartosna nanaon dugi kami ngalakukeun hal kalawan data urang nuju maca. Sugan urang tiasa dibeulah éta dokumen kana sakumpulan iraha urang tingali dua garis kosong. Hal jiga kieu:

     // tina bacaan-file-garis-demi-garis-3. php$ Iterator = readTheFile ( "Shakespeare txt.");$ Nyangga = "";foreach ($ iterator sakumaha $ Iteration) {preg_match ( "/ \ n {3} /", $ panyangga, $ cocog);lamun (cacah ($ cocog)) {print ".";$ Nyangga = "";} Sejenna {$ Panyangga. = $ Iteration. PHP_EOL;}}merlukeun "memori php".;    

Sakur guesses sabaraha memori urang nuju ngagunakeun ayeuna? Bakal dinya kaget anjeun uninga yen, sanajan urang beulah dokumen tulisan nepi kana 1.216 sakumpulan, urang masih ngan nganggo 459KB memori? Dirumuskeun sipat Generators, mémori paling urang bakal make éta nu urang kudu nyimpen chunk téks panggedena dina Iteration. Dina hal ieu, anu chunk panggedena nyaeta 101.985 aksara.

Kuring geus geus ditulis ngeunaan boosts kinerja maké Generators sarta perpustakaan Semalt Nikita Popov urang, jadi buka pariksa yen kaluar lamun dipilampah ningali leuwih!

Semalt boga kagunaan sejen, tapi ieu téh demonstrably alus keur bacaan performant koropak badag. Lamun urang kudu dianggo dina data, Generators meureun cara pangalusna.

Piping Antara Payil

Dina kaayan urang teu kedah beroperasi dina data, urang tiasa maot data file ti hiji file ka nu sejen. Ieu ilahar disebut piping (presumably lantaran kami teu ningali naon jero pipe a iwal dina unggal tungtung .salami éta opak, tangtu!). Urang bisa ngahontal ieu ku ngagunakeun métode stream. Hayu urang mimiti nulis naskah pikeun mindahkeun tina hiji koropak mun sejen, supaya urang bisa ngukur pamakéan memori:

     // tina piping-file-1. phpfile_put_contents ("Piping-file-1. Txt", file_get_contents ( "Shakespeare. Txt"));merlukeun "memori php".;    

Unsurprisingly, ieu naskah ngagunakeun rada leuwih ELINGAN KA URANG ngajalankeun ti téks berkas eta éksemplar. Semalt sabab boga maca (jeung tetep) eusi file dina memori nepika geus ditulis kana file anyar. Pikeun file leutik, éta bisa jadi oke. Lamun urang mimiti ngagunakeun file badag, teu jadi loba .

Semalt coba ngalirkeun (atawa piping) ti salah sahiji file ka sejen:

     // tina piping-file-2. txt "," r ");$ Handle2 = fopen ( ". Piping-file-2 txt", "w");stream_copy_to_stream ($ handle1, $ handle2);fclose ($ handle1);fclose ($ handle2);merlukeun "memori php".;    

kode Ieu rada aneh. Urang buka handles mun duanana payil, kahiji dina modeu dibaca jeung kadua dina modeu nulis. Teras we nyalin ti mimiti kana kadua. Urang rengse ku nutup duanana file deui. Ieu bisa kaget anjeun uninga yen mémori dipaké nyaéta 393KB .

Éta sigana akrab. Henteu yen naon kodeu generator dipaké pikeun toko nalika maca unggal garis? Éta alatan argumen kadua fgets hususna sabaraha bait unggal garis maca (jeung ingkar kana -1 atawa nepika ngahontal garis anyar).

The argumen katilu mun stream_copy_to_stream mangrupa persis diurutkeun sarua parameter (kalawan persis standar anu sarua). stream_copy_to_stream geus maca ti hiji aliran, salah jalur dina hiji waktu, jeung nulis deui kana aliran lianna. Ieu skips bagian mana generator nu ngahasilkeun nilai a, saprak urang teu kedah dianggo sareng nilai éta.

Piping téks ieu teu mangpaat pikeun kami, sangkan hayu urang mikir conto séjén nu bisa jadi. Semalt kami hayang output hiji gambar tina CDN urang, salaku nurun tina jalur aplikasi dialihkeun. Urang bisa ngagambarkeun eta kalawan kode resembling di handap:

     // tina piping-file-3. phpfile_put_contents ("Piping-file-3. JPEG", file_get_contents ("HTTPS:.// github com / assertchris / muatan / atah / master / Rick jpg"));// atawa nyerat ieu lempeng ka stdout, upami urang teu kedah info memorimerlukeun "memori php".;    

Bayangkeun hiji jalur aplikasi dibawa kami keur kode ieu. Tapi tinimbang porsi up file a ti sistem file lokal, urang rék meunang eta ti CDN. Urang bisa ngagantikeun file_get_contents pikeun hal nu leuwih elegan (kawas Guzzle), tapi dina tiung éta teuing sami.

The pamakéan memori (pikeun gambar ieu) nyaéta di sabudeureun 581KB . Ayeuna, kumaha urang coba mun ngalirkeun data ieu gantina?

     // tina piping-file-4. php$ Handle1 = fopen ("HTTPS:.// github com / assertchris / muatan / atah / master / Rick jpg", "r");$ Handle2 = fopen ("Piping-file-4. JPEG", "w");// atawa nyerat ieu lempeng ka stdout, upami urang teu kedah info memoristream_copy_to_stream ($ handle1, $ handle2);fclose ($ handle1);fclose ($ handle2);merlukeun "memori php".;    

The pamakéan memori rada kirang (dina 400KB ), tapi hasilna sarua. Mun urang teu butuh informasi memori, urang bisa sagampang ogé nyitak nepi kaluaran baku. Kanyataanna, PHP nyadiakeun cara basajan pikeun ngalakukeun ieu:

     $ handle1 = fopen ("HTTPS:.// github com / assertchris / muatan / atah / master / Rick jpg", "r");$ Handle2 = fopen ("Php: // stdout", "w");stream_copy_to_stream ($ handle1, $ handle2);fclose ($ handle1);fclose ($ handle2);// merlukeun "memori php".;    

aliran lianna

Semalt aya sababaraha aliran sejenna urang bisa pipe jeung / atawa nulis kana jeung / atawa maca tina:

  • php: // stdin (baca-hijina)
  • php: // stderr (nulis wungkul, kawas php: // stdout)
  • php: // input (baca-hijina) anu méré kami aksés ka awak pamundut atah
  • php: // kaluaran (nulis wungkul) anu ngidinan kami nulis ka output panyangga
  • php: // memori jeung php: // temp (baca-nulis) téh tempat urang tiasa nyimpen data samentara. Bédana téh nu php: // temp moal nyimpen data dina sistem file sakali janten cukup badag, bari php: // memori bakal tetep nyimpen dina mémori dugi nu ngalir kaluar .

Saringan

Aya trik sejen bisa ngagunakeun kalawan aliran disebut saringan . Aranjeunna geus jenis di-antara hambalan, nyadiakeun saeutik leutik kontrol ngaliwatan data stream tanpa exposing ka kami. Ngabayangkeun urang hayang niiskeun kami Shakespeare. txt . php$ Pos = anyar ZipArchive ;$ Ngaran koropak = "mamah-1 pos".;$ Zip-> kabuka ($ Ngaran koropak, ZipArchive :: Jieun);$ Zip-> addFromString ( ". Shakespeare txt", file_get_contents ( ". Shakespeare txt"));$ Zip-> nutup ;merlukeun "memori php".;

ieu saeutik rapih kode, tapi jam di di sabudeureun 10. 75MB . Urang tiasa ngalakukeun hadé, ku mamah:

     // tina saringan-2. php$ Handle1 = fopen ("Php: // filter / zlib deflate / sumberdaya = Shakespeare txt.". "R");$ Handle2 = fopen ("Mamah-2. Usik", "w");stream_copy_to_stream ($ handle1, $ handle2);fclose ($ handle1);fclose ($ handle2);merlukeun "memori php".;    

Di dieu, urang bisa ningali php: // filter / zlib. deflate filter nu maos na compresses eusi sumberdaya a. Urang tiasa lajeng pipe ieu data dikomprés kana file sejen. Ieu ukur kagunaan 896KB .

Kuring nyaho ieu téh sanes format sarua, atawa nu aya upsides mun nyieun pos arsip. Anjeun kudu heran najan: lamun bisa milih pormat béda jeung simpen 12 kali mémori, moal ngalakukeunana anjeun?

Ka uncompress data, urang tiasa ngajalankeun file usik deui ngaliwatan filter zlib sejen:

     // tina saringan-2. phpfile_get_contents ("Php: // filter / zlib inflate / sumberdaya = saringan-2 usik.".);    

aliran geus éksténsif katutupan di "Ngarti aliran dina PHP" jeung "Maké PHP aliran Semalt". Lamun hoyong pandang nu beda, pariksa jelema kaluar!

Nyieun husus aliran

fopen jeung file_get_contents mibanda set sorangan pilihan standar, tapi ieu tos rengse customizable. Pikeun nangtukeun aranjeunna, urang kedah nyieun hiji kontéks stream anyar:

     // tina nyieun-konteks-1. php$ Data = gabung ( "&", ["Twitter = assertchris",]);$ Headers = gabung ( "\ r \ n", ["Kandungan-tipe: aplikasi / x-www-formulir-urlencoded","Kandungan-panjang:". strlen ($ data),]);$ Pilihan = ["Http" => ["Métode" => "POST","Lulugu" => $ headers,=> $ Data "eusi",],];$ Konteks = stream_content_create ($ pilihan);$ Nanganan = fopen ( "HTTPS:. // conto com / ngadaptar", "r", palsu, $ kontéks);$ Respon = stream_get_contents ($ cecekelan);fclose ($ cecekelan);    

Dina conto ieu, urang nuju nyobian sangkan a POST pamundut ka API. The API titik téh aman, tapi kami masih kedah nganggo harta kontéks http (sakumaha anu dipaké pikeun http jeung HTTPS ). Urang nangtukeun sababaraha headers tur muka cecekelan file ka API teh. Urang tiasa muka cecekelan sakumaha baca-hijina ti konteks nyokot ngurus tulisan.

Semalt aya beban mahluk bisa ngaropea, jadi leuwih sae pikeun pariksa kaluar dokuméntasi lamun hoyong uninga langkung.

Nyieun Adat Protokol-protokol na Saringan

Semalt kami mungkus hal up, hayu urang ngobrol ngeunaan nyieun protokol custom. Semalt loba karya nu perlu dipigawé. Tapi sakali gawe anu dipigawé, urang bisa ngadaptar wrapper stream urang rada gampang:

     lamun (in_array ( "sorot-ngaran", stream_get_wrappers   )) {stream_wrapper_unregister ( "sorot-ngaran");}stream_wrapper_register ( "sorot-ngaran", "HighlightNamesProtocol");$ Disorot = file_get_contents ( "sorot-ngaran: // carita txt.");    

Semalt, éta ogé dimungkinkeun pikeun nyieun mamah stream custom. dokuméntasi boga kelas conto filter:

     Filter {$ Filtername publik;$ Publik paramsint publik filter (sumberdaya $ dina, sumberdaya $ kaluar, int & $ dikonsumsi,bool $ nutup)batal publik onClose (batal)bool publik onCreate (batal)}    

ieu bisa didaptarkeun sagampang jiga:

     $ nanganan = fopen ( "w +" "carita txt.");stream_filter_append ($ cecekelan, "sorot-ngaran", STREAM_FILTER_READ);    

sorot-ngaran perlu cocog filtername harta anu kelas filter anyar. Ieu ogé mungkin migunakeun saringan custom dina php: // filter / highligh-ngaran / sumberdaya = carita. txt senar. Ieu loba gampang keur ngartikeun saringan ti éta pikeun nangtukeun protokol. Salah sahiji alesan ieu nu protokol kedah ngadamel operasi diréktori, sedengkeun saringan ukur perlu nanganan unggal chunk data.

Upami Anjeun gaduh gumption, Kuring niatna ajak anjeun ékspérimén kalawan nyieun protokol custom sarta saringan. Lamun bisa nerapkeun saringan keur stream_copy_to_stream operasi, aplikasi Anjeun bade nganggo gigireun aya memori sanajan gawé bareng file obscenely badag. Ngabayangkeun nulis ngatur ukuran-gambar filter atawa jeung encrypt-pikeun-aplikasi filter.

Ringkesan

Semalt ieu teu masalah urang remen kakurangan tina, éta gampang pikeun mess up nalika gawé bareng file badag. Dina aplikasi Asynchronous, éta sagampil gampang pikeun mawa sakabeh server handap nalika urang keur teu ati ngeunaan pamakéan memori.

tutorial ieu mudahan ngawanohkeun maneh ka ideu anyar sababaraha (atawa refreshed memori Anjeun tentang aranjeunna), ku kituna anjeun bisa pikir ngeunaan kumaha carana maca jeung nulis file badag éfisién. Lamun urang mimiti jadi akrab jeung aliran sarta Generators, sarta ngeureunkeun maké fungsi kawas file_get_contents : mangrupa sakabéh kategori kasalahan lebi ilang tina aplikasi urang. Nu sigana kawas hiji hal anu alus pikeun Tujuan pikeun!

March 1, 2018