kirim konten lengkap buffer cincin saat berlangganan dan kemudian kirim data baru

Saya seorang pemula dalam boost::asio.

Saya perlu membuat kode modul yang membaca dari pipa dan memasukkan data ke dalam buffer cincin (Saya tidak punya masalah dalam cara mengimplementasikan bagian ini).

Bagian lain dari modul menunggu konsumen untuk membuka koneksi TCP baru atau soket domain unix dan ketika koneksi dibuat, modul tersebut mengirimkan konten buffer ring penuh dan kemudian akan mengirimkan data baru segera setelah dimasukkan ke dalam buffer ring. . Banyak konsumen diperbolehkan dan satu konsumen dapat membuka koneksi baru kapan saja.

Implementasi naif pertama yang saya pikirkan adalah menyimpan asio::streambuf terpisah untuk setiap koneksi dan mendorong seluruh buffer cincin ke dalamnya pada koneksi dan kemudian setiap data baru, tetapi tampaknya ini merupakan metode yang sangat kurang optimal untuk melakukan keduanya di memori dan siklus cpu karena data harus disalin untuk setiap koneksi, mungkin beberapa kali karena saya tidak tahu apakah boost::asio::send (atau tumpukan linux tcp/ip) menyalin data.

Karena ide saya adalah tidak menggunakan multi threading sama sekali, saya berpikir untuk menggunakan beberapa bentuk kelas turunan asio::streambuf khusus yang berbagi buffer aktual dengan buffer cincin, tetapi mempertahankan status terpisah dari penunjuk baca tanpa perlu kunci apa pun.

Tampaknya bagi saya ini adalah kebutuhan yang sangat tidak biasa, karena saya tidak dapat menemukan dokumentasi/pertanyaan terkait yang berhubungan dengan subjek serupa dan dokumentasi peningkatan tampaknya cukup singkat dan langka bagi saya (lihat misalnya: http://www.boost.org/doc/libs/1_57_0/doc/html/boost_asio/reference/basic_streambuf.html).

Akan lebih baik jika seseorang dapat menunjukkan kepada saya beberapa ide yang dapat saya ambil sebagai titik awal untuk mengimplementasikan desain saya atau mengarahkan saya ke desain alternatif jika dia menganggap ide saya buruk, tidak dapat diterapkan dan/atau dapat ditingkatkan.


person Patxitron    schedule 08.02.2015    source sumber
comment
dokumentasi peningkatan tampaknya cukup kasar dan langka bagi saya Saya akan menganggap tidak sopan tidak berarti seperti yang Anda pikirkan. Bisakah Anda menautkan ke dokumentasi yang tidak Anda pahami?   -  person sehe    schedule 08.02.2015
comment
Saya telah melihat dua suara negatif. Saya telah mengedit pertanyaan untuk menambahkan tag linux dan kemudian saya melihat satu suara negatif, lalu saya pikir itu karena saya mengosongkan penjelasan singkat edit jadi saya telah mengedit lagi hanya untuk membenarkan pengeditan sebelumnya dan saya' telah melihat suara negatif kedua. Saya tidak tahu apakah saya mendapat suara negatif otomatis untuk setiap pengeditan atau ada orang yang memberi suara negatif tanpa menjelaskan alasannya.   -  person Patxitron    schedule 08.02.2015
comment
Ini yang terakhir. Pertanyaan Anda sangat luas, dan tidak menunjukkan upaya khusus apa pun. Maksud saya ini persis seperti yang saya katakan. Anda tidak menunjukkan /apa/ yang membuat Anda kesulitan. Anda tidak dapat mengharapkan kami untuk memberikan contoh yang berfungsi, tetapi tanpa kode konkret yang Anda gunakan, pertanyaan tersebut sepertinya tidak cocok untuk SO. (Omong-omong, saya sedang dalam proses menulis jawaban)   -  person sehe    schedule 08.02.2015
comment
Beberapa penilaian negatif Anda mungkin berasal dari fakta bahwa Anda tidak memposting cuplikan kode apa pun tentang upaya Anda. kasar -› belum sempurna juga mungkin meningkatkan penerimaan pertanyaan ;) Selain itu, mungkin tidak jelas bagi banyak orang mengapa Anda tidak hanya membaca dari pipa Anda dan melayani kedua titik akhir Anda dari 1 fungsi. Tapi mungkin itu karena saya belum terlalu paham tentang boost:asio. Jika Anda ingin sesuatu dioptimalkan, lakukan sendiri (daripada menggunakan perpustakaan) ;)   -  person BitTickler    schedule 08.02.2015
comment
@sehe: Maaf jika saya menggunakan kata kasar dengan cara yang salah. Saya bukan orang yang bisa berbahasa Inggris dan dalam bahasa Spanyol rudo mungkin merupakan istilah yang lebih lembut. Saya mengacu pada boost.org/doc /libs/1_57_0/doc/html/boost_asio/reference/ dan saya ingin mengatakan bahwa ini tampaknya tidak ramah bagi saya karena tampaknya sangat singkat dan menjelaskan cara menggunakannya tetapi saya tidak tahu cara mendapatkannya kelas khusus.   -  person Patxitron    schedule 08.02.2015
comment
@Patxitron Anda selalu dapat merujuk ke banyak contoh: boost .org/doc/libs/1_57_0/doc/html/boost_asio/examples.html   -  person sehe    schedule 08.02.2015
comment
@ user2225104 Saya tidak dapat memposting cuplikan kode apa pun karena pertanyaan saya lebih terkait dengan desain. Anda benar, ini adalah pertanyaan yang cukup luas, tapi saya bahkan tidak bisa mendapatkan parameter pencarian yang berguna untuk mempersempitnya.   -  person Patxitron    schedule 08.02.2015
comment
Apa yang masih tidak dapat saya lihat dalam pertanyaan Anda adalah, ketika Anda akhirnya membuang informasi yang Anda baca dari pipa Anda sejauh ini. Kapan konsumen pertama terhubung atau Anda ingin menyimpan informasi Anda sejak awal agar semua konsumen baru datang?   -  person BitTickler    schedule 08.02.2015
comment
@ user2225104 Tujuan saya adalah buffer cincin menyimpan N byte terakhir yang diterima dari pipa. Byte baru yang diterima akan menimpa byte terlama. Kemudian ketika konsumen menghubungkan N byte terbaru tersebut dikirim ke sana dan kemudian setiap byte baru diterima segera setelah diterima. Jadi konsumen tidak membuang data dari ring buffer dan konten lengkapnya (sejarah dengan ukuran terbatas) tersedia untuk konsumen baru.   -  person Patxitron    schedule 08.02.2015
comment
Jika Anda ingin sesuatu yang dioptimalkan, lakukan sendiri (daripada menggunakan perpustakaan) ;) - @user2225104 Kedengarannya agak terbalik bagi saya. Kedengarannya lebih seperti sindrom NIH atau kemungkinan pilihan perpustakaan yang buruk. Saya cukup yakin keseimbangannya tidak akan seperti itu dengan perpustakaan Boost. Mereka mungkin /lebih dari yang Anda butuhkan/ tetapi mereka jarang membatasi sama sekali.   -  person sehe    schedule 08.02.2015
comment
@sehe Itu semua tergantung pada apakah masalahnya cukup sederhana untuk ditangani atau di luar kemampuan seseorang. Saya lebih suka menggunakan beberapa algoritma matematika yang dioptimalkan dari lib. Tetapi untuk menulis antrian, saya lebih suka tidak melakukannya (std::queue akan dianggap tidak ada perpustakaan di sini). Juga untuk membuka soket atau membaca dari pipa. Tidak jika saya harus menghabiskan lebih banyak waktu untuk mempelajari perpustakaan daripada waktu yang saya perlukan untuk menulisnya sendiri.   -  person BitTickler    schedule 08.02.2015
comment
@ user2225104 intinya adalah hal ini harus sangat rumit agar pustaka boost pada umumnya tidak dapat lagi mengikutinya. Tapi saya tidak akan berdebat tentang selera - karena itulah kartu yang sebenarnya Anda tarik.   -  person sehe    schedule 08.02.2015


Jawaban (2)


Anda sebaiknya melakukan apa yang Anda inginkan.

Anda benar-benar tidak memerlukan streambuf untuk digunakan dengan Boost Asio: http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/buffer.html

Jika masalahnya adalah bagaimana menghindari produsen "menunggu" sampai semua konsumen (baca: koneksi) selesai mengirimkan data, Anda selalu dapat menggunakan trik lama buffer keluaran bergantian.

Banyak implementasi ring buffer yang memungkinkan penyambungan langsung rangkaian elemen lengkap sekaligus, (misalnya meningkatkan akses memori cache spsc_queue lockfree). Anda dapat menggunakan operasi seperti itu untuk keuntungan Anda.

Juga relevan:

person sehe    schedule 08.02.2015
comment
Menambahkan tautan ke lebih banyak latar belakang (ditambah ide desain lengkap dan tautan ke implementasi/presentasi) tentang nol salinan menggunakan Boost Asio. - person sehe; 08.02.2015

Tampaknya performa adalah topik di sini. Terlepas dari apakah boost::asio digunakan atau solusi rajutan tangan, kinerja (throughput) mungkin sudah sia-sia karena fakta (seperti yang dinyatakan di bagian komentar OP), bahwa byte tunggal sedang diperdagangkan (baca dari pipa).
Setelah "fase ledakan" awal ketika konsumen terhubung, byte tunggal menetes dari pipa ke soket konsumen yang terhubung dengan operasi read() dan write() per byte (atau beberapa byte, jika aplikasi tidak melakukan polling secara terus-menerus).
Mengingat (fakta bahwa harga untuk panggilan sistem read() dan write() dibayar untuk sejumlah kecil data), saya berani berteori bahwa apa pun tentang banyak antrean atau antrean tunggal, dll. sudah berada dalam bayang-bayang "cacat desain" dasar itu. Saya memberi tanda kutip "cacat desain" karena tidak selalu dapat dihindari untuk menangani situasi seperti itu.

Jadi, jika throughput tidak dapat dioptimalkan, saya akan merekomendasikan solusi paling sederhana dan mudah yang dapat dipikirkan.

Pernyataan "tidak ada utas" di OP menyiratkan deskriptor file non-pemblokiran untuk soket penerimaan, soket data konsumen, dan pipa. Apakah ini akan menjadi aplikasi polling yang memakan CPU/inti 100% lainnya? Jika ini bukan masalah operasi khusus yang sangat dioptimalkan, saya lebih suka tidak menyarankan untuk menggunakan deskriptor file yang tidak memblokir. Selain itu, saya tidak akan khawatir tentang zero-copy atau tidak.

Salah satu pendekatan mudah dengan thread adalah dengan menjadikan soket konsumen tidak menghalangi, sementara pipa berada dalam mode pemblokiran. Thread yang membaca pipa kemudian memompa data ke dalam antrian dan memanggil fungsi yang melayani semua konsumen yang terhubung saat ini. Soket pendengaran (yang memanggil, terima()) berada dalam status sinyal, ketika koneksi klien baru tertunda. Dengan mekanisme seperti kqueue (bsd) atau epoll (linux dll.) atau WaitForMultipleObjects (windows), thread pembaca pipa juga dapat bereaksi terhadap situasi tersebut.

Pada saat tidak ada yang bisa dilakukan, aplikasi Anda sedang tidur/memblokir dan ramah terhadap lingkungan kita :)

person BitTickler    schedule 08.02.2015
comment
Saya berasumsi bahwa fungsi deskriptor file posix dari boost::asio melakukan hal epoll untuk saya tanpa harus menggunakan siklus cpu dalam polling aktif seperti pada boost.org/doc/libs/1_49_0/doc/html/boost_asio/example/chat/ sebenarnya Saya sudah bereksperimen dengan fitur itu: github.com/patxitron/BattleyeRconToolLinux - person Patxitron; 09.02.2015
comment
Anda benar, setelah buffer diunggah, data akan dikirim tidak persis dalam urutan byte demi byte, tetapi dalam beberapa byte setiap kali (biasanya kurang dari 100 sekaligus). Saya sekarang berpikir untuk mengirim pembaruan tersebut dengan mengulangi serangkaian soket terdaftar. Terima kasih untuk bantuannya. - person Patxitron; 09.02.2015