Apakah loop peristiwa hanya loop untuk / sementara dengan polling yang dioptimalkan?

55

Saya mencoba memahami apa itu loop acara. Seringkali penjelasannya adalah bahwa dalam suatu perulangan peristiwa, Anda melakukan sesuatu sampai Anda diberi tahu bahwa suatu peristiwa telah terjadi. Anda kemudian menangani acara dan terus melakukan apa yang Anda lakukan sebelumnya.

Untuk memetakan definisi di atas dengan sebuah contoh. Saya memiliki server yang 'mendengarkan' dalam suatu loop peristiwa, dan ketika koneksi soket terdeteksi, data darinya dibaca dan ditampilkan, setelah itu server melanjutkan / mulai mendengarkan seperti sebelumnya.


Namun, peristiwa ini terjadi dan kami mendapat pemberitahuan 'begitu saja' terlalu banyak untuk saya tangani. Anda dapat mengatakan: "Ini bukan 'hanya seperti itu' Anda harus mendaftarkan pendengar acara". Tapi apa itu pendengar acara tetapi fungsi yang karena alasan tertentu tidak kembali. Apakah itu dalam loop itu sendiri, menunggu untuk diberitahu ketika suatu peristiwa terjadi? Haruskah pendengar acara juga mendaftarkan pendengar acara? Di mana itu berakhir?


Acara adalah abstraksi yang bagus untuk dikerjakan, namun hanya abstraksi. Saya percaya bahwa pada akhirnya, pemungutan suara tidak dapat dihindari. Mungkin kita tidak melakukannya dalam kode kita, tetapi level yang lebih rendah (implementasi bahasa pemrograman atau OS) melakukannya untuk kita.

Ini pada dasarnya bermuara pada kode pseudo berikut yang berjalan di suatu tempat yang cukup rendah sehingga tidak menyebabkan kesibukan menunggu:

while(True):
    do stuff
    check if event has happened (poll)
    do other stuff

Ini adalah pemahaman saya tentang keseluruhan ide, dan saya ingin mendengar jika ini benar. Saya terbuka untuk menerima bahwa seluruh gagasan pada dasarnya salah, dalam hal ini saya ingin penjelasan yang benar.

Insinyur Mesin
sumber
3
Sistem acara adalah implementasi dari pola Pengamat . Memahami polanya harus memperkuat pemahaman Anda tentang berbagai peristiwa. Tidak diperlukan polling.
Steven Evers
1
Pada akhirnya ya, bahkan jika bahasa membuat abstraknya.
GrandmasterB
@SteveEvers Di tautan wiki Anda. Apa yang EventSourcedilakukan jika tidak polling input keyboard?
TheMeaningfulEngineer
@Lan: Bisa saja melakukan apa saja, tetapi untuk input keyboard secara khusus ada API untuk mendaftarkan aplikasi Anda sebagai mendengarkan acara keyboard, yang kemudian dapat Anda gunakan sebagai sumber acara Anda tanpa melibatkan pemungutan suara. Tentu saja, jika Anda turun cukup jauh, USB selalu polling, tapi mari kita asumsikan kita menggunakan keyboard PS / 2, yang didorong oleh interupsi, dan kemudian Anda memiliki tumpukan input keyboard berdasarkan peristiwa dengan polling nol.
Phoshi
Saya sudah memiliki pertanyaan ini sejak bertahun-tahun, tetapi saya tidak tahu mengapa saya tidak pernah repot untuk menanyakannya. Terima kasih, saya sekarang puas dengan pengertian @Karl Bielefeldt yang telah mencerahkan saya.
0xc0de

Jawaban:

54

Kebanyakan loop acara akan ditangguhkan jika tidak ada acara yang siap, yang berarti sistem operasi tidak akan memberikan tugas waktu eksekusi hingga terjadi peristiwa.

Katakanlah acara adalah tombol yang ditekan. Anda mungkin bertanya apakah ada loop di sistem operasi yang memeriksa penekanan tombol. Jawabannya adalah tidak. Tombol yang ditekan menghasilkan interupsi , yang ditangani secara serempak oleh perangkat keras. Demikian juga untuk penghitung waktu, gerakan mouse, paket tiba, dll.

Bahkan, untuk sebagian besar sistem operasi, pemungutan suara untuk acara adalah abstraksi. Perangkat keras dan OS menangani acara secara tidak sinkron dan menempatkannya dalam antrian yang dapat disurvei oleh aplikasi. Anda hanya benar-benar melihat polling yang sebenarnya pada tingkat perangkat keras di sistem embedded, dan bahkan di sana tidak selalu.

Karl Bielefeldt
sumber
4
Bukankah interupsi perubahan tegangan pada kabel? Bisakah itu memicu suatu peristiwa dengan sendirinya atau haruskah kita mengumpulkan pin untuk nilai tegangan?
TheMeaningfulEngineer
8
Itu bisa memicu suatu peristiwa dengan sendirinya. Prosesor dirancang seperti itu. Bahkan sebuah prosesor dapat dibangunkan dari tidur dengan interupsi.
Karl Bielefeldt
2
Saya bingung dengan pernyataan itu Most event loops will block. Bagaimana hal ini sesuai dengan "paradigma loop acara, yang bertentangan dengan penggunaan utas, menggunakan panggilan asinkron yang nonblocking"?
TheMeaningfulEngineer
1
Jika Anda melihat loop acara untuk perpustakaan seperti GTK +, mereka memeriksa acara baru kemudian memanggil penangan acara dalam satu lingkaran, tetapi jika tidak ada acara, mereka memblokir semaphore atau timer atau sesuatu. Masing-masing pengembang membuat loop acara sendiri yang tidak memblokir antrian acara kosong, tetapi pustaka yang digunakan secara luas semuanya memblokir. Jika tidak, loop acara terlalu tidak efisien.
Karl Bielefeldt
1
Saya kira Anda bisa melihatnya seperti itu, tetapi multi threading di perpustakaan dan / atau OS daripada kode aplikasi. Loop acara abstrak masalah sinkronisasi untuk pengembang aplikasi.
Karl Bielefeldt
13

Saya menganggap pendengar acara bukan sebagai fungsi yang menjalankan putarannya sendiri, tetapi sebagai lomba lari estafet dengan pelari pertama yang menunggu pistol start. Alasan signifikan untuk menggunakan acara daripada polling adalah bahwa mereka lebih efisien dengan siklus CPU. Mengapa? Lihatlah dari perangkat keras ke atas (bukan kode sumber ke bawah).

Pertimbangkan server Web. Ketika server Anda memanggil listen()dan memblokir, kode Anda menggantikannya sebagai pelari relay. Ketika paket pertama dari koneksi baru tiba, kartu jaringan memulai perlombaan dengan mengganggu sistem operasi. OS menjalankan layanan rutin interupsi (ISR) yang mengambil paket. ISR meneruskan tongkat ke rutinitas tingkat yang lebih tinggi yang membangun koneksi. Setelah sambungan hidup, rutin itu meneruskan tongkat ke listen(), yang meneruskan tongkat ke kode Anda. Pada titik itu, Anda dapat melakukan apa yang Anda inginkan dengan koneksi. Yang kami tahu, di antara balapan, setiap pelari estafet bisa pergi ke pub. Kekuatan abstraksi acara adalah bahwa kode Anda tidak perlu tahu atau peduli.

Beberapa sistem operasi termasuk kode penanganan peristiwa yang menjalankan bagian dari balapan, melepaskan tongkat estafet, kemudian kembali ke titik awal untuk menunggu balapan berikutnya dimulai. Dalam hal itu, penanganan acara dioptimalkan pemungutan suara dalam banyak loop bersamaan. Namun, selalu ada pemicu dari luar yang memulai proses. Pendengar acara bukanlah fungsi yang tidak kembali, tetapi fungsi yang menunggu pemicu eksternal sebelum dijalankan. Daripada:

while(True):
    do stuff
    check if event has happened (poll)
    do other stuff

Saya menganggap ini sebagai:

on(some event):    //I got the baton
     do stuff
     signal the next level up    //Pass the baton

dan antara signaldan saat berikutnya pawang berjalan, secara konseptual tidak ada kode yang berjalan atau berulang.

cxw
sumber
Ini masuk akal, namun apa yang dilakukan loop acara sambil menunggu interupsi? Jika itu memblokir, bukankah itu pendekatan 'multi-threaded' yang merupakan paradigma yang berlawanan dengan loop peristiwa?
TheMeaningfulEngineer
Jika kode Anda memiliki loop forever: { select(); do stuff; }maka Anda memasukkan kembali balapan setiap kali melalui loop. Apakah Anda melakukan itu berulang kali dari utas tunggal atau secara paralel pada utas atau prosesor yang terpisah, saya menganggap setiap peristiwa sebagai balapannya sendiri. Misalnya, browser Web adalah program multithreaded dengan beberapa loop acara di utas terpisah, setidaknya satu untuk UI dan satu untuk setiap halaman yang diunduh. Pertanyaan yang saya tanyakan ketika coding adalah "bagaimana saya bisa memproses acara cukup cepat?" Terkadang jawabannya adalah lingkaran, terkadang utas, sering kombinasi.
cxw
Saya telah melakukan pemrograman berbasis acara selama lebih dari beberapa dekade, dan saya menemukan jawaban ini sangat membingungkan. Agar pendengar berfungsi, harus ada loop yang menunggu acara, kemudian mengarahkannya ke semua pendengar yang terdaftar. (Dengan asumsi kita sedang berbicara tentang perangkat lunak daripada interupsi perangkat keras)
Bryan Oakley
8

Tidak. Ini bukan "polling yang dioptimalkan." Peristiwa-loop menggunakan I / O yang didorong oleh interupsi alih-alih polling.

Sementara, Hingga, Untuk, dll. Loop adalah loop polling.

"Polling" adalah proses berulang kali memeriksa sesuatu. Karena kode loop dijalankan terus menerus, dan karena itu adalah loop kecil, "ketat", ada sedikit waktu bagi prosesor untuk berpindah tugas dan melakukan hal lain. Hampir semua "hang," "freeze," "lockups" atau apa pun yang Anda ingin menyebutnya ketika komputer menjadi tidak responsif, adalah manifestasi dari kode yang terjebak dalam loop polling yang tidak diinginkan. Instrumentasi akan menunjukkan penggunaan CPU 100%.

Loop event yang digerakkan oleh interupsi jauh lebih efisien daripada loop polling. Polling adalah penggunaan siklus CPU yang sangat boros sehingga segala upaya dilakukan untuk menghilangkan atau meminimalkannya.

Namun, untuk mengoptimalkan kualitas kode, sebagian besar bahasa mencoba menggunakan paradigma looping polling sedekat mungkin untuk event menyerahkan perintah karena mereka melayani tujuan yang secara fungsional serupa dalam suatu program. Dengan demikian, dengan polling menjadi cara yang lebih akrab untuk menunggu penekanan tombol atau sesuatu, mudah bagi yang tidak berpengalaman untuk menggunakannya dan berakhir dengan program yang dapat berjalan dengan baik dengan sendirinya, tetapi tidak ada yang berfungsi saat sedang berjalan. Itu telah "mengambil alih" mesin.

Seperti dijelaskan dalam jawaban lain, dalam penyerahan acara yang digerakkan oleh interupsi, pada dasarnya "flag" diatur dalam CPU dan prosesnya "ditangguhkan" (tidak diizinkan untuk dijalankan) sampai flag tersebut diubah oleh beberapa proses lain (seperti keyboard). driver mengubahnya ketika pengguna telah menekan tombol). Jika bendera adalah kondisi perangkat keras aktual seperti garis "ditarik tinggi," itu disebut "interupsi" atau "interupsi perangkat keras." Namun sebagian besar, diimplementasikan hanya sebagai alamat memori pada CPU atau dalam memori utama (RAM) dan disebut "semaphores."

Semafor dapat diubah di bawah kendali perangkat lunak dan karenanya dapat menyediakan mekanisme pensinyalan yang sangat cepat dan sederhana di antara proses perangkat lunak.

Namun, interupsi hanya dapat diubah oleh perangkat keras. Penggunaan interupsi yang paling umum adalah yang dipicu secara berkala oleh chip clock internal. Salah satu jenis tindakan perangkat lunak yang tak terhitung banyaknya yang diaktifkan oleh interupsi jam, adalah perubahan semaphore.

Saya telah meninggalkan banyak tetapi harus berhenti di suatu tempat. Silakan tanyakan apakah Anda membutuhkan detail lebih lanjut.

DocSalvager
sumber
7

Biasanya jawabannya adalah perangkat keras, OS dan utas latar yang tidak Anda kontrol berkonspirasi untuk membuatnya terlihat mudah. Kartu jaringan menerima beberapa data yang menimbulkan gangguan agar CPU tahu. Penangan interupsi OS menanganinya. Kemudian utas latar belakang yang tidak Anda kendalikan (yang dibuat dengan mendaftar untuk acara tersebut dan telah tertidur sejak Anda mendaftar untuk acara tersebut) dibangunkan oleh OS sebagai bagian dari penanganan acara dan menjalankan pengendali acara Anda.

stonemetal
sumber
7

Saya akan menentang semua jawaban lain yang saya lihat sejauh ini dan mengatakan "ya" . Saya pikir jawaban lain terlalu rumit. Dari sudut pandang konseptual, semua loop acara pada dasarnya:

while <the_program_is_running> {
    event=wait_for_next_event()
    process_event(event)
}

Jika Anda mencoba memahami loop peristiwa untuk pertama kalinya, menganggapnya sebagai loop sederhana tidak akan membahayakan. Beberapa kerangka kerja yang mendasar sedang menunggu OS untuk menyampaikan suatu acara, kemudian mengarahkan acara tersebut ke satu atau lebih penangan, kemudian menunggu acara berikutnya, dan seterusnya. Itu benar-benar semua yang ada untuk itu dari perspektif perangkat lunak aplikasi.

Bryan Oakley
sumber
1
+1 karena berterus terang. Namun penekanannya adalah pada "menunggu"; pelaksanaan kode ini akan BERHENTI pada baris pertama dari loop dan tidak berlanjut sampai suatu peristiwa terjadi. Ini berbeda dari loop pemungutan suara sibuk yang berulang kali memeriksa suatu peristiwa sampai terjadi.
Tom Panning
1

Tidak semua pemicu peristiwa ditangani dalam loop. Cara saya sering menulis mesin acara saya sendiri akan seperti ini:

interface Listener {
    void handle (EventInfo info);
}

List<Listener> registeredListeners

void triggerEvent (EventInfo info) {
    foreach (listener in registeredListeners) { // Memo 1
        listener.handle(info) // the handling may or may not be synchronous... your choice
    }
}

void somethingThatTriggersAnEvent () {
    blah
    blah
    blah
    triggerEvent(someGeneratedEventInfo)
    more blah
}

Perhatikan bahwa meskipun Memo 1 ada di loop, loop adalah untuk memberi tahu setiap pendengar. Pemicu acara itu sendiri tidak harus dalam satu lingkaran.

Secara teori, peristiwa kunci tingkat OS dapat menggunakan teknik yang sama (meskipun saya pikir mereka sering melakukan jajak pendapat? Saya hanya berspekulasi di sini), asalkan OS memperlihatkan semacam registerListenerAPI.

Thomas Eding
sumber