Alternatif untuk get_posts () karena crash cache multithreading

8

Saya menggunakan pthreads untuk membuat beberapa utas. Masing-masing utas pada satu titik mencoba menggunakan get_posts()sebagai berikut:

$args = array(
    'post_type' => 'post',
    'post_status' => 'any'
);

$posts_list = get_posts($args);

Namun saya berakhir dengan crash berikut:

HP Fatal error:  Call to a member function get() on a non-object in C:\dev\wordpress\wp-includes\cache.php on line 123

PLEASE NOTE ketika saya melakukan get_posts()panggilan yang sama di bagian kode yang tidak berulir, saya tidak mengalami crash.

Sekarang, pertanyaan saya, bagaimana cara menelepon get_posts()dari dalam thread pthread ? Dan jika saya tidak bisa melakukan itu, apa alternatifnya?

Terima kasih.


Memperbarui

Berikut ini contoh kode

class My_Thread extends Thread {

    public function run() {

        /* DO SOME STUFF HERE */

        $args = array(
            'post_type' => 'post',
            'post_status' => 'any'
        );

        $posts_list = get_posts($args); // <------ This is causing the crash
    }
}

// Create a array
$threads = array();

//Iniciate Miltiple Thread
foreach ( range("A", "C") as $i ) {
    $threads[] = new My_Thread($i);
}

// Start The Threads
foreach ($threads as $thread) {
    $thread->start();
}
Greeso
sumber
itu bukan crash itu adalah kesalahan ..... Anda harus memperbaiki kode Anda sehingga tidak akan ada kesalahan. Bagaimanapun juga, pustaka php tidak selalu aman multitasking sehingga masalahnya mungkin dengan sesuatu yang sama sekali berbeda.
Mark Kaplun
Untuk menambahkan, jika ada kode yang perlu dilindungi untuk eksekusi "waktu yang sama" daripada Anda perlu menggunakan mutex tetapi itu jauh dari ruang lingkup di sini.
Mark Kaplun
@MarkKaplun - Terima kasih atas masukan Anda. Namun, sepertinya Anda melewatkan titik di mana saya menyatakan bahwa " ketika saya melakukan get_posts()panggilan yang sama di bagian kode yang tidak di-thread, saya tidak mengalami crash "; jadi tidak masalah dengan get_posts($args)panggilan saya . Selain itu, tidak ada kode yang perlu dilindungi pada saat ini, saya hanya membaca dari DB WordPress get_posts($args).
Greeso
3
@MarkKaplun - Ada apa denganmu? Mengapa Anda begitu negatif dan sangat agresif? Mengapa Anda menganggap saya tidak mengerti multitasking dan menyarankan agar saya tidak menggunakan pthreads? Bahkan jika Anda benar, bukankah kita seharusnya mencoba apa yang tidak kita pahami untuk memperluas pengetahuan dan batasan kita? Dan bukankah situs ini tentang mengajukan pertanyaan jika Anda tidak tahu bagaimana Anda melakukan hal tertentu? Saya tidak berpura-pura apa pun. Saya menemukan kesalahan, saya menyadari itu karena menggunakan pthreads, dan saya meminta solusi, baik setup atau solusi pemrograman. Saya mengharapkan jawaban konstruktif dari diri Anda sendiri.
Greeso
2
Sampai kita benar - benar tahu bahwa WordPress bukan alasan untuk memecah kode ini, itu adalah topik.
fuxia

Jawaban:

2

Karena ada begitu banyak upvotes untuk pertanyaan tersebut, meskipun masalah multithreading terlalu luas untuk format jawaban, saya akan mencoba menjelaskan mengapa Anda tidak boleh menggunakan wordpress API dengan cara multithreaded ....

TL; DR - PHP tidak diasumsikan multithreading siap, masalahnya bukan PHP itu sendiri tetapi terutama perpustakaan yang digunakannya. Inilah sebabnya mengapa disarankan untuk tidak menggunakan mode eksekusi multithreaded di apache walaupun secara teori seharusnya lebih cepat. Untuk menambah masalah lapisan yang mendasarinya tidak siap multithread, inti wordpress melanggar persyaratan paling mendasar multithread- tidak ada akses gratis ke global.

Apa masalah dengan global dalam lingkungan multithreaded? mari kita asumsikan kita memiliki kode yang terlihat naif

function inc() {
  global $g;

  $g++;
}

Meskipun hanya satu liner, itu bukan operasi atom untuk CPU, dan dibutuhkan beberapa instruksi tingkat mesin untuk menjalankannya secara aktual. Sesuatu seperti

move $g to register D
increment register D
move register D to $g

Sekarang mari kita asumsikan kita memiliki dua utas AB yang memanggil inc()pada "waktu yang sama" (jelas dengan hanya satu CPU tidak ada yang namanya waktu yang sama), dan bahwa nilai awal $ g adalah 0, berapakah nilai $ g setelah kedua utas selesai? Ini akan tergantung pada bagaimana OS menangani multithreading, kapan ia beralih di antara utas. Dalam OS gaya "lama" itu adalah tugas utas untuk mendeklarasikan dengan memanggil API bahwa kontrol dapat diambil darinya, tetapi itu menyebabkan banyak masalah dengan proses perilaku buruk mengunci sistem karenanya dalam "modern" OS yang diambil OS kontrol kapan pun rasanya seperti itu. Dalam kehidupan nyata hasil kode adalah $ g akan memiliki nilai 2, tetapi ada juga kemungkinan berikut

Dalam konteks A

move $g to register D
// value of D is 0
// OS stores the content of registers and switches to thread B
// B increments $g to 1 and finishes working
// OS restores content of registers to the context of thread A
// Value of register D is now 0
increment register D
move register D to $g

Hasil akhirnya adalah $ g memiliki nilai 1.

Jelas global bukan satu-satunya masalah dan penanganan input dan output juga merupakan inti untuk masalah mutithreading.

Dalam kode multithreading yang tepat Anda menggunakan kunci / mutex / semaphore / pipa / socket .... untuk membuat serial akses ke sumber daya global tersebut untuk memastikan akan ada hasil yang dapat diprediksi untuk operasi. Wordpress tidak melakukan itu.

Sial, wordpress bahkan bukan multi-proses yang aman. Sebagian besar waktu berlalu begitu saja karena skema DB dibangun dengan cara yang dalam penggunaan kehidupan nyata mencegah kebutuhan untuk memodifikasi data yang sama dari proses yang berbeda (posting yang berbeda memiliki baris yang berbeda dan tidak berbagi data), tetapi lihatlah kode sidebar / widget dan coba bayangkan apa yang akan terjadi jika dua admin akan mencoba menambahkan widget yang berbeda pada waktu yang bersamaan. Karena ini akan memerlukan manipulasi dari satu opsi tertentu, hasil akhirnya dapat berupa widget yang ditambahkan atau hanya salah satunya.

Kembali ke multithrading. Dalam unix, tidak seperti windows, biaya tambahan untuk menghasilkan suatu proses alih-alih thread dapat diabaikan, karenanya menggunakan wp_remote_getdengan beberapa url khusus untuk memanggil "thread" tambahan adalah hal yang sangat sah untuk dilakukan dan menghindari hampir semua jebakan yang terkait dengan multithreading.

Mark Kaplun
sumber
Ini dijelaskan dengan baik. Terima kasih. Saya juga baru tahu bahwa dukungan untuk pthreads untuk bekerja dengan apache sedang dihapus. Agar pthreads berfungsi, harus berada dalam lingkungan CLI . Bagi saya, saya perlu pthreads , tetapi saya akan menunda solusi ini sampai setelah rilis (yaitu, peningkatan). Selain itu, saya perlu mengatur WordPress sebagai lingkungan CLI (detail di sini wp-cli.org ); melakukan hal itu akan memungkinkan saya untuk bekerja di lingkungan pthreads / WordPress dari CLI, memungkinkan saya untuk melakukan pekerjaan berat di backend tanpa apache. Terima kasih lagi.
Greeso
Hanya untuk menambahkan, saya akan membatasi pthreads untuk menangani masalah terkait non-db. Dan sesuai saran Anda, gunakan mutex untuk menulis db.
Greeso
@ Greeso, linux dirancang untuk menggunakan banyak proses untuk menangani kebutuhan eksekusi bersamaan, menghasilkan proses baru yang benar-benar lebih aman dan secepat menggunakan pthreads ..
Mark Kaplun