Konu php postid oluşturma. Pthreads Çevirisi ile PHP'de Çok Yönlü Programlama

Bazen aynı anda birkaç eylemi gerçekleştirmek gerekli hale gelir, örneğin, bir veritabanı tablosundaki değişiklikleri kontrol edin ve diğerinde değişiklikler yapın. Ayrıca, işlemlerden biri (örneğin, değişiklikleri kontrol etme) uzun sürüyorsa, sıralı yürütmenin kaynak dengelemesini sağlayamayacağı açıktır.

Bu tür sorunları çözmek için, programlama çoklu iş parçacığı kullanır - her işlem, tahsis edilmiş miktarda kaynakla ayrı bir iş parçacığına yerleştirilir ve içinde çalışır. Bu yaklaşımla, tüm görevler ayrı ayrı ve bağımsız olarak gerçekleştirilecektir.

PHP çoklu iş parçacığını desteklemese de, onu taklit etmek için aşağıda tartışılacak olan birkaç yöntem vardır.

1. Komut dosyasının birden çok kopyasını çalıştırın - işlem için bir kopya

//woman.php if (! isset ($ _ GET ["thread"])) (system ("wget ​​http: //localhost/woman.php? thread = make_me_happy"); sistem ("wget ​​http : // localhost / woman.php? thread = make_me_rich ");) elseif ($ _GET [" thread "] ==" make_me_happy ") (make_her_happy ();) elseif ($ _GET [" thread "] ==" make_me_rich ") (find_another_one ( );)

Bu betiği parametresiz çalıştırdığımızda, gerekli işlevlerin yürütülmesini başlatan işlem kimlikleriyle ("thread = make_me_happy" ve "thread = make_me_rich") kendisinin iki kopyasını otomatik olarak başlatır.

Böylece, istenen sonucu elde ederiz - iki işlem aynı anda gerçekleştirilir - ancak elbette bu çok iş parçacıklı değil, aynı anda görevleri gerçekleştirmek için sadece bir koltuk değneğidir.

2. Jedi Yolu - PCNTL Uzantısını Kullanma

PCNTL, süreçlerle tam olarak çalışmanıza izin veren bir uzantıdır. Yönetime ek olarak mesajlaşma, durum kontrolü ve önceliklendirmeyi destekler. PCNTL'yi kullanan önceki komut dosyası şöyle görünür:

$ pid = pcntl_fork(); if ($ pid == 0) (make_her_happy ();) elseif ($ pid> 0) ($ pid2 = pcntl_fork (); if ($ pid2 == 0) (find_another_one ();))

Oldukça kafa karıştırıcı görünüyor, satır satır gidelim.

İlk satırda, mevcut süreci "çatallıyoruz" (çatal - bir işlemi tüm değişkenlerin değerlerini tutmaktan kopyalamak), paralel olarak çalışan iki işleme (mevcut ve alt) bölüyoruz.

nerede olduğumuzu anlamak için şu an, bir alt veya üst işlemde, pcntl_fork alt öğe için 0 ve üst öğe için işlem kimliği döndürür. Bu nedenle, ikinci satırda $ pid'e bakarız, eğer sıfıra eşitse, o zaman alt süreçteyiz - işlevi gerçekleştiriyoruz, aksi takdirde ana süreçteyiz (satır 4), sonra yaratırız başka bir işlem ve görevi aynı şekilde gerçekleştirin.

Komut dosyası yürütme süreci:

Böylece, komut dosyası, kopyaları olan ve aynı değerlere sahip aynı değişkenleri içeren 2 alt süreç daha oluşturur. Ve pcntl_fork fonksiyonunun döndürdüğü tanımlayıcı yardımı ile şu anda hangi thread'de olduğumuza yönleniyor ve gerekli işlemleri yapıyoruz.

Geçenlerde pthreads denedim ve hoş bir sürpriz oldu - bu PHP'de birkaç gerçek iş parçacığıyla çalışma yeteneği ekleyen bir uzantı. Öykünme yok, sihir yok, sahte yok - her şey gerçek.



Böyle bir görev düşünüyorum. Hızlı bir şekilde tamamlanması gereken bir görev havuzu var. PHP'nin bu sorunu çözmek için başka araçları var, burada bahsedilmiyor, makale pthreads hakkında.



pthreads nedir

Bu kadar! Neredeyse her şey. Aslında, meraklı okuyucuyu üzebilecek bir şey var. Bunların hiçbiri, varsayılan seçeneklerle derlenmiş standart PHP'de çalışmaz. Çoklu okumanın keyfini çıkarmak için PHP'nizde ZTS'nin (Zend Thread Safety) etkinleştirilmiş olması gerekir.

PHP kurulumu

Ardından, ZTS ile PHP. Çalışma zamanı ile ZTS'siz PHP arasındaki büyük farkı (37.65'e karşı 265.05 saniye) boşverin, PHP ayarını ortak bir paydaya getirmeye çalışmadım. ZTS'siz durumda, örneğin XDebug'u etkinleştirdim.


Gördüğünüz gibi, 2 iş parçacığı kullanıldığında, program yürütme hızı, doğrusal kod durumundan yaklaşık 1,5 kat daha yüksektir. 4 iplik kullanırken - 3 kez.


İşlemci 8 çekirdekli olmasına rağmen, 4'ten fazla iş parçacığı kullanıldığında program yürütme süresinin neredeyse değişmediğine dikkat edebilirsiniz. Görünüşe göre bu, işlemcimin fiziksel çekirdeklerinin 4 olmasından kaynaklanıyor. Anlaşılır olması için diyagram şeklinde bir plaka çizdim.


Özet

PHP, pthreads uzantısını kullanarak çoklu iş parçacığını oldukça zarif bir şekilde işleyebilir. Bu, somut bir performans artışı sağlar.

Etiketler: Etiket Ekle

  • Programlama,
  • paralel programlama
  • Geçenlerde pthreads denedim ve hoş bir sürpriz oldu - bu PHP'de birkaç gerçek iş parçacığıyla çalışma yeteneği ekleyen bir uzantı. Öykünme yok, sihir yok, sahte yok - her şey gerçek.



    Böyle bir görev düşünüyorum. Hızlı bir şekilde tamamlanması gereken bir görev havuzu var. PHP'nin bu sorunu çözmek için başka araçları var, burada bahsedilmiyor, makale pthreads hakkında.



    pthreads nedir

    Bu kadar! Neredeyse her şey. Aslında, meraklı okuyucuyu üzebilecek bir şey var. Bunların hiçbiri, varsayılan seçeneklerle derlenmiş standart PHP'de çalışmaz. Çoklu okumanın keyfini çıkarmak için PHP'nizde ZTS'nin (Zend Thread Safety) etkinleştirilmiş olması gerekir.

    PHP kurulumu

    Ardından, ZTS ile PHP. Çalışma zamanı ile ZTS'siz PHP arasındaki büyük farkı (37.65'e karşı 265.05 saniye) boşverin, PHP ayarını ortak bir paydaya getirmeye çalışmadım. ZTS'siz durumda, örneğin XDebug'u etkinleştirdim.


    Gördüğünüz gibi, 2 iş parçacığı kullanıldığında, program yürütme hızı, doğrusal kod durumundan yaklaşık 1,5 kat daha yüksektir. 4 iplik kullanırken - 3 kez.


    İşlemci 8 çekirdekli olmasına rağmen, 4'ten fazla iş parçacığı kullanıldığında program yürütme süresinin neredeyse değişmediğine dikkat edebilirsiniz. Görünüşe göre bu, işlemcimin fiziksel çekirdeklerinin 4 olmasından kaynaklanıyor. Anlaşılır olması için diyagram şeklinde bir plaka çizdim.


    Özet

    PHP, pthreads uzantısını kullanarak çoklu iş parçacığını oldukça zarif bir şekilde işleyebilir. Bu, somut bir performans artışı sağlar.

    Etiketler:

    • php
    • pthreads
    Etiket ekle

    PHP geliştiricileri nadiren eşzamanlılık kullanıyor gibi görünüyor. Senkronize kodun basitliğinden bahsetmeyeceğim, tek iş parçacıklı programlama elbette daha basit ve daha nettir, ancak bazen küçük bir paralellik kullanımı somut bir performans artışı getirebilir.

    Bu yazıda, pthreads uzantısını kullanarak PHP'de çoklu iş parçacığının nasıl elde edilebileceğine bir göz atacağız. Bu, ZTS (Zend Thread Safety) PHP 7.x'in yüklenmesini gerektirir. yüklü uzantı pthreads v3. (Bu yazının yazıldığı sırada, PHP 7.1'de, kullanıcıların pthreads deposundaki ana daldan yükleme yapmaları gerekecek - üçüncü taraf uzantısına bakın.)

    Küçük bir açıklama: pthreads v2, PHP 5.x için tasarlanmıştır ve artık desteklenmemektedir, pthreads v3, PHP 7.x içindir ve aktif olarak geliştirilmektedir.

    Böyle bir arasözden sonra, hemen işe başlayalım!

    Tek seferlik görevleri işleme

    Bazen tek seferlik görevleri çok iş parçacıklı bir şekilde işlemek istersiniz (örneğin, G / Ç'ye bağlı belirli bir görevi gerçekleştirmek). Bu gibi durumlarda, yeni bir iş parçacığı oluşturmak ve ayrı bir iş parçacığında bazı işlemlere başlamak için Thread sınıfını kullanabilirsiniz.

    Örneğin:

    $ görev = yeni sınıf İş parçacığını genişletir (özel $ yanıtı; genel işlev çalıştırma () ($ içerik = file_get_contents ("http://google.com")); preg_match ("~ (.+)~ ", $ içerik, $ eşleşmeleri); $ bu-> yanıt = $ eşleşmeler;)); $ görev-> başlat () && $ görev-> katıl (); var_dump ($ görev-> yanıt); // dize (6) "Google"

    Burada run yöntemi, yeni iş parçacığının içinde yapılacak olan işlemimizdir. Thread :: start çağrıldığında, yeni bir thread oluşturulur ve run metodu çağrılır. Daha sonra, ortaya çıkan iş parçacığı yürütmesini tamamlayana kadar engelleyecek olan Thread :: join'i çağırarak ortaya çıkan iş parçacığını ana iş parçacığına geri ekleriz. Bu, sonucu çıkarmaya çalışmadan önce görevin tamamlanmasını sağlar (bu, $ görev-> yanıtında saklanır).

    Akış mantığıyla ilişkili ek sorumluluklarla (çalışma yöntemini tanımlama sorumluluğu dahil) sınıfı kirletmek istenmeyebilir. Bu tür sınıfları Threaded sınıfından miras alarak ayırt edebiliriz. Sonra başka bir iş parçacığının içinde çalıştırılabilirler:

    Sınıf Görevi, Threaded'i genişletir (genel $ yanıtı; genel işlev someWork () ($ içerik = file_get_contents ("http://google.com"); preg_match ("~ (. +) ~", $ İçerik, $ eşleşmeleri); $ bu-> yanıt = $ eşleşmeleri;)) $ görev = yeni Görev; $ thread = yeni sınıf ($ görev) Thread'i genişletir (özel $ görev; genel işlev __construct (Dişli $ görev) ($ bu-> görev = $ görev;) genel işlev çalıştırma () ($ bu-> görev-> bazıWork ( );)); $ thread-> start () && $ thread-> birleştirme (); var_dump ($ görev-> yanıt);

    Ayrı bir iş parçacığında çalıştırılması gereken herhangi bir sınıf, NS Threaded sınıfından miras alır. Bunun nedeni, farklı iş parçacıkları üzerinde işleme gerçekleştirmek için gerekli yeteneklerin yanı sıra örtük güvenlik ve kullanışlı arabirimler (kaynak senkronizasyonu gibi) sağlamasıdır.

    pthreads uzantısı tarafından sağlanan sınıf hiyerarşisine bir göz atalım:

    Dişli (Traversable, Collectable uygular) Thread Worker Uçucu Havuz

    Thread ve Threaded sınıflarının temellerini zaten ele aldık ve öğrendik, şimdi diğer üçüne (Worker, Volatile ve Pool) bir göz atalım.

    Akışları yeniden kullanma

    Paralelleştirilmesi gereken her görev için yeni bir iş parçacığı başlatmak pahalıdır. Bunun nedeni, PHP içinde çoklu kullanım elde etmek için "ortak olmayan" mimarinin pthreads içinde uygulanması gerektiğidir. Bu, mevcut PHP yorumlayıcı örneğinin tüm yürütme bağlamının (her sınıf, arayüz, özellik ve işlev dahil) oluşturulan her iş parçacığı için kopyalanması gerektiği anlamına gelir. Bunun performans üzerinde gözle görülür bir etkisi olduğundan, akış mümkün olduğunda her zaman yeniden kullanılmalıdır. Akışlar iki şekilde yeniden kullanılabilir: Workers veya Pools kullanarak.

    Worker sınıfı, başka bir iş parçacığı içinde eşzamanlı olarak bir dizi görevi gerçekleştirmek için kullanılır. Bu, yeni bir Worker örneği oluşturarak (yeni bir iş parçacığı oluşturur) ve ardından görevleri bu ayrı iş parçacığının yığınına iterek (İşçi :: yığını kullanarak) yapılır.

    İşte küçük bir örnek:

    Class Task, Threaded'i genişletir (özel $ değeri; public function __construct (int $ i) ($ this-> value = $ i;) public function run () (usleep (250000); echo "Görev: ($ this-> value) \ n ";)) $ işçi = yeni Çalışan (); $ işçi-> başlat (); for ($ i = 0; $ i stack (yeni Görev ($ i));) while ($ işçi-> toplama ()); $ işçi-> kapatma ();

    Yukarıdaki örnekte, Worker :: yığın yöntemi aracılığıyla yeni bir $work nesnesi için yığına 15 görev gönderilir ve ardından gönderildikleri sırayla işlenir. İşçi :: toplama yöntemi, yukarıda gösterildiği gibi, görevleri yürütmeyi bitirir bitirmez temizlemek için kullanılır. Bunu while döngüsü içinde kullanarak, yığındaki tüm görevler tamamlanana ve temizlenene kadar ana iş parçacığını engelleriz - Worker :: kapatma çağırmadan önce. Çalışanın programdan önce sonlandırılması (yani, hala tamamlanması gereken görevler varken), tüm görevler yürütülmesini tamamlayana kadar ana iş parçacığını engellemeye devam eder, yalnızca görevler çöp toplayıcı tarafından temizlenmez (bu, bellek gerektirir). sızıntılar).

    Worker sınıfı, son eklenen görevi kaldırmak için Worker :: unstack ve yürütme yığınındaki görevlerin sayısını almak için Worker :: getStacked dahil olmak üzere görev yığınıyla ilgili birkaç başka yöntem sağlar. Çalışanın yığını yalnızca tamamlanması gereken görevleri içerir. Yığından bir görev tamamlandığında, kaldırılır ve çöp toplama için ayrı bir (dahili) yığına yerleştirilir (İşçi :: toplama yöntemini kullanarak).

    Bir iş parçacığını birçok görev için yeniden kullanmanın başka bir yolu da bir iş parçacığı havuzu kullanmaktır (Havuz sınıfı aracılığıyla). İş parçacığı havuzu, görevlerin yürütülmesini sağlamak için bir grup Çalışan kullanır eşzamanlı havuz oluşturulduğunda eşzamanlılık faktörünün (birlikte çalıştığı havuz iş parçacıklarının sayısı) ayarlandığı .

    Yukarıdaki örneği bir işçi havuzu kullanacak şekilde uyarlayalım:

    Class Task, Threaded'i genişletir (özel $ değeri; public function __construct (int $ i) ($ this-> value = $ i;) public function run () (usleep (250000); echo "Görev: ($ this-> value) \ n ";)) $ havuz = yeni Havuz (4); for ($ i = 0; $ i gönderiyorum (yeni Görev ($ i));) while ($ havuz-> topla ()); $ havuz-> kapatma ();

    Bir işçinin aksine bir havuz kullanırken dikkate değer birkaç fark vardır. İlk olarak, havuzun manuel olarak başlatılmasına gerek yoktur; kullanılabilir oldukları anda görevleri gerçekleştirmeye başlar. İkincisi, biz göndermek havuza görevler, değil onları yığının üzerine koymak... Ayrıca, Pool sınıfı Threaded'den miras almaz ve bu nedenle (Worker'ın aksine) diğer threadlere geçirilemez.

    İşçiler ve havuzlar için iyi bir uygulama olarak, görevlerini her zaman bitirir bitirmez temizlemeli ve ardından bunları manuel olarak sonlandırmalısınız. Thread sınıfı kullanılarak oluşturulan diziler de üst dizine eklenmelidir.

    pthreads ve (olmayan) değişkenlik

    Son değineceğimiz sınıf, pthreads v3'e yeni bir ekleme olan Volatile. Değişmezlik kavramı, pthread'lerde önemli bir kavram haline geldi, çünkü onsuz performans önemli ölçüde düşüyor. Bu nedenle, varsayılan olarak, kendileri Threaded nesneler olan Threaded sınıflarının özellikleri artık değiştirilemez ve bu nedenle ilk atamalarından sonra üzerine yazılamaz. Bu tür özellikler için açık değişkenlik şu anda tercih edilmektedir ve yine de yeni Uçucu sınıfla elde edilebilir.

    Yeni değişmezlik kısıtlamalarını gösteren bir örneğe bakalım:

    Class Task, Threaded // bir Threaded sınıfını genişletir (genel fonksiyon __construct () ($ this-> data = new Threaded (); // $ this-> data, Threaded sınıfının bir Threaded özelliği olduğu için üzerine yazılamaz)) $ görev = yeni sınıf (yeni Görev ()) Thread'i genişletir (// Threaded genel işlevi genişlettiği için bir Threaded sınıfı __construct ($ tm) ($ this-> threadedMember = $ tm; var_dump ($ this-> threadedMember->) data); // object (Threaded) # 3 (0) () $ this-> threadedMember = new StdClass (); // özellik, Threaded sınıfının bir Threaded üyesi olduğu için geçersiz));

    Uçucu sınıfların dişli özellikleri ise değişkendir:

    Sınıf Görevi Uçucu'yu genişletir (genel işlev __construct () ($ this-> data = new Threaded (); $ this-> data = new StdClass (); // geçici bir sınıfta olduğumuz için geçerlidir)) $ görev = yeni class (new Task()) Thread'i genişletir (public function __construct ($ vm) ($ this-> volatileMember = $ vm; var_dump ($ this-> volatileMember-> data); // object (stdClass) # 4 (0) () // Volatile, Threaded'i genişlettiği için hala geçersiz, bu nedenle özellik hala Threaded sınıfının Threaded bir üyesidir $ this-> volatileMember = new StdClass ();));

    Volatile sınıfının, Threaded özelliklerini (ayrıca unset()) değiştirme yeteneği sağlamak için üst Threaded sınıfı tarafından dayatılan değişmezliği geçersiz kıldığını görebiliriz.

    Değişebilirlik ve Uçucu sınıf - diziler konusunu kapsayacak bir tartışma konusu daha var. pthreads'de diziler, Threaded sınıfındaki bir özelliğe atandığında otomatik olarak Volatile nesnelerine dönüştürülür. Bunun nedeni, birden çok PHP bağlamından bir diziyi değiştirmenin güvenli olmamasıdır.

    Birkaç şeyi daha iyi anlamak için örneğe tekrar bakalım:

    $ dizi =; $ görev = yeni sınıf ($ dizi) Konuyu genişletir (özel $ veri; genel işlev __construct (dizi $ dizi) ($ bu-> veri = $ dizi;) genel işlev çalıştırma () ($ bu-> veri = 4; $ bu-> veri = 5; print_r ($ bu-> veri);)); $ görev-> başlat () && $ görev-> katıl (); / * Çıktı: Uçucu Nesne (=> 1 => 2 => 3 => 4 => 5) * /

    Volatile nesnelerine dizilermiş gibi davranılabileceğini görebiliriz, çünkü bunlar (yukarıda gösterildiği gibi) alt küme operatörü () gibi dizi işlemlerini destekler. Ancak, Uçucu sınıflar desteklemiyor temel fonksiyonlar array_pop ve array_shift gibi dizilerle. Bunun yerine, Threaded sınıfı bize yerleşik yöntemlerle benzer işlemler sağlar.

    Gösteri olarak:

    $ data = yeni sınıf, Uçucu'yu genişletir (genel $ a = 1; genel $ b = 2; genel $ c = 3;); var_dump ($ veri); var_dump ($ data-> pop()); var_dump ($ data-> shift()); var_dump ($ veri); / * Çıktı: nesne ( [e-posta korumalı]) # 1 (3) (["a"] => int (1) ["b"] => int (2) ["c"] => int (3)) int (3) int (1) nesne ( [e-posta korumalı]) # 1 (1) (["b"] => int (2)) * /

    Desteklenen diğer işlemler arasında Dişli :: yığın ve Dişli :: birleştirme bulunur.

    senkronizasyon

    Bu makalenin son bölümünde, pthreads'de senkronizasyona bir göz atacağız. Senkronizasyon, paylaşılan kaynaklara erişimi kontrol etmenizi sağlayan bir tekniktir.

    Örneğin, basit bir sayaç uygulayalım:

    $ counter = yeni sınıf Thread'i genişletir (public $ i = 0; public function run () (for ($ i = 0; $ i i;))); $ sayaç-> başlat (); for ($ ben = 0; $ ben ben;) $ counter-> join (); var_dump ($ sayaç-> i); // 10 ile 20 arasında bir sayı yazdıracak

    Senkronizasyon kullanılmadan çıktı deterministik değildir. Birden çok iş parçacığı, kontrollü erişim olmadan aynı değişkene yazar, bu da güncellemelerin kaybolacağı anlamına gelir.

    Bunu düzeltelim, böylece senkronizasyon ekleyerek doğru çıktıyı 20 elde edelim:

    $ sayaç = yeni sınıf İş parçacığını genişletir (genel $ i = 0; genel işlev çalıştır () ($ this-> senkronize (işlev () (($ i = 0; $ i i;)));)); $ sayaç-> başlat (); $ sayaç-> senkronize (fonksiyon ($ sayaç) (($ i = 0; $ i i;) için), $ sayaç); $ sayaç-> katıl (); var_dump ($ sayaç-> i); // int (20)

    Senkronize kod blokları, Threaded :: wait ve Threaded :: notify (veya Threaded :: notifyAll) yöntemlerini kullanarak da birbirleriyle etkileşime girebilir.

    İşte iki senkronize while döngüsündeki sıralı artış:

    $ sayaç = yeni sınıf İş parçacığını genişletir (genel $ koşul = 1; genel işlev çalıştır () ($ this-> senkronize (işlev () (for ($ i = 0; $ i notify (); if ($ this-> koşul) === 1) ($ bu-> koşul = 2; $ bu-> bekle ();))));)); $ sayaç-> başlat (); $ counter-> synchronized (fonksiyon ($ counter) (if ($ counter-> koşul! == 2) ($ counter-> wait (); // önce diğerinin başlamasını bekleyin) for ($ i = 10; $ i bildir (); if ($ sayaç-> koşul === 2) ($ sayaç-> koşul = 1; $ sayaç-> bekle ();))), $ sayaç); $ sayaç-> katıl (); / * Çıktı: int (0) int (10) int (1) int (11) int (2) int (12) int (3) int (13) int (4) int (14) int (5) int ( 15) int (6) int (16) int (7) int (17) int (8) int (18) int (9) int (19) * /

    Threaded :: wait çağrısının etrafına yerleştirilmiş ek koşulları fark edebilirsiniz. Bu koşullar, bir bildirim aldığında ve belirtilen koşul doğru olduğunda senkronize edilmiş geri aramanın devam etmesine izin verdiği için kritiktir. Bu önemlidir çünkü bildirimler Threaded :: notify'ın çağrıldığı yerler dışındaki yerlerden gelebilir. Bu nedenle, Threaded :: wait yöntemine yapılan çağrılar koşullara dahil edilmemişse, sahte uyandırma bu, kodun öngörülemeyen davranışına yol açacaktır.

    Çözüm

    pthreads paketindeki beş sınıfı (Threaded, Thread, Worker, Volatile ve Pool) ve her bir sınıfın nasıl kullanıldığını ele aldık. Ayrıca pthreads'deki yeni değişmezlik kavramına da bir göz attık, kısa inceleme desteklenen senkronizasyon yetenekleri. Bu temel bilgiler yerine getirildikten sonra, artık gerçek dünya durumlarında pthreads kullanmaya başlayabiliriz! Bu bir sonraki yazımızın konusu olacak.

    Bir sonraki gönderinin çevirisiyle ilgileniyorsanız, bana bildirin: sosyal medyada yorum yapın. ağlar, artı ve gönderiyi meslektaşlarınız ve arkadaşlarınızla paylaşın.



    Geçenlerde pthreads denedim ve hoş bir sürpriz oldu - bu PHP'de birkaç gerçek iş parçacığıyla çalışma yeteneği ekleyen bir uzantı. Öykünme yok, sihir yok, sahte yok - her şey gerçek.



    Böyle bir görev düşünüyorum. Hızlı bir şekilde tamamlanması gereken bir görev havuzu var. PHP'nin bu sorunu çözmek için başka araçları var, burada bahsedilmiyor, makale pthreads hakkında.



    pthreads nedir

    Bu kadar! Neredeyse her şey. Aslında, meraklı okuyucuyu üzebilecek bir şey var. Bunların hiçbiri, varsayılan seçeneklerle derlenmiş standart PHP'de çalışmaz. Çoklu okumanın keyfini çıkarmak için PHP'nizde ZTS'nin (Zend Thread Safety) etkinleştirilmiş olması gerekir.

    PHP kurulumu

    Ardından, ZTS ile PHP. Çalışma zamanı ile ZTS'siz PHP arasındaki büyük farkı (37.65'e karşı 265.05 saniye) boşverin, PHP ayarını ortak bir paydaya getirmeye çalışmadım. ZTS'siz durumda, örneğin XDebug'u etkinleştirdim.


    Gördüğünüz gibi, 2 iş parçacığı kullanıldığında, program yürütme hızı, doğrusal kod durumundan yaklaşık 1,5 kat daha yüksektir. 4 iplik kullanırken - 3 kez.


    İşlemci 8 çekirdekli olmasına rağmen, 4'ten fazla iş parçacığı kullanıldığında program yürütme süresinin neredeyse değişmediğine dikkat edebilirsiniz. Görünüşe göre bu, işlemcimin fiziksel çekirdeklerinin 4 olmasından kaynaklanıyor. Anlaşılır olması için diyagram şeklinde bir plaka çizdim.


    Özet

    PHP, pthreads uzantısını kullanarak çoklu iş parçacığını oldukça zarif bir şekilde işleyebilir. Bu, somut bir performans artışı sağlar.