Latar Belakang:
Overhead panggilan sistem jauh lebih besar daripada overhead panggilan fungsi (perkiraan berkisar antara 20-100x) sebagian besar karena pergantian konteks dari ruang pengguna ke ruang kernel dan kembali. Adalah umum untuk fungsi sebaris untuk menyimpan overhead panggilan fungsi dan panggilan fungsi jauh lebih murah daripada syscalls. Masuk akal bahwa pengembang ingin menghindari beberapa overhead panggilan sistem dengan menjaga sebanyak mungkin operasi dalam kernel dalam satu syscall mungkin.
Masalah:
Hal ini telah menciptakan banyak (berlebihan?) Panggilan sistem seperti sendmmsg () , recvmmsg () serta chdir, terbuka, lseek dan / atau kombinasi symlink seperti: openat
, mkdirat
, mknodat
, fchownat
, futimesat
, newfstatat
, unlinkat
, fchdir
, ftruncate
, fchmod
, renameat
, linkat
, symlinkat
, readlinkat
, fchmodat
, faccessat
, lsetxattr
, fsetxattr
, execveat
, lgetxattr
, llistxattr
, lremovexattr
, fremovexattr
, flistxattr
, fgetxattr
, pread
, pwrite
dll ...
Sekarang Linux telah menambahkan copy_file_range()
yang tampaknya menggabungkan read lseek dan write syscalls. Hanya masalah waktu sebelum ini menjadi fcopy_file_range (), lcopy_file_range (), copy_file_rangeat (), fcopy_file_rangeat () ... dan lcopy_file_rangeat () ... tetapi karena ada 2 file yang terlibat, bukan X lebih banyak panggilan, itu bisa menjadi X ^ 2 lebih. OK, Linus dan berbagai pengembang BSD tidak akan membiarkannya sejauh itu, tetapi poin saya adalah bahwa jika ada syscall batching, semua (sebagian besar?) Ini dapat diimplementasikan di ruang pengguna dan mengurangi kompleksitas kernel tanpa menambahkan banyak jika ada overhead di sisi libc.
Banyak solusi kompleks telah diusulkan yang mencakup beberapa bentuk syscall thread khusus untuk syscalls non-blocking ke syscalls proses batch; namun metode ini menambah kompleksitas yang signifikan pada kernel dan ruang pengguna dengan cara yang hampir sama dengan libxcb vs libX11 (panggilan asinkron membutuhkan lebih banyak pengaturan)
Larutan?:
Syscall batching generik. Ini akan mengurangi biaya terbesar (beberapa mode switch) tanpa kerumitan yang terkait dengan memiliki utas kernel khusus (meskipun fungsionalitas itu dapat ditambahkan kemudian).
Pada dasarnya sudah ada dasar yang baik untuk prototipe di soketcall () syscall. Hanya perluas dari mengambil array argumen untuk bukannya mengambil array pengembalian, pointer ke array argumen (yang termasuk nomor syscall), jumlah syscalls dan argumen flags ... sesuatu seperti:
batch(void *returns, void *args, long ncalls, long flags);
Satu perbedaan utama adalah bahwa argumen mungkin semua harus menjadi petunjuk untuk kesederhanaan sehingga hasil dari syscall sebelumnya dapat digunakan oleh syscalls berikutnya (misalnya deskriptor file dari open()
untuk digunakan di read()
/ write()
)
Beberapa kemungkinan keuntungan:
- lebih sedikit ruang pengguna -> ruang kernel -> perpindahan ruang pengguna
- switch kompiler yang mungkin -fcombine-syscalls untuk mencoba melakukan batch secara otomatis
- panji opsional untuk operasi asinkron (kembalikan fd untuk menonton segera)
- kemampuan untuk mengimplementasikan fungsi syscall gabungan di masa depan dalam userspace
Pertanyaan:
Apakah layak untuk menerapkan syscall batching?
- Apakah saya kehilangan beberapa Gotcha yang jelas?
- Apakah saya melebih-lebihkan manfaatnya?
Apakah ada gunanya bagi saya untuk repot menerapkan syscall batching (saya tidak bekerja di Intel, Google atau Redhat)?
- Saya telah menambal kernel saya sendiri sebelumnya, tetapi takut berurusan dengan LKML.
- Sejarah telah menunjukkan bahwa meskipun sesuatu secara luas bermanfaat bagi pengguna "normal" (pengguna akhir non-perusahaan tanpa akses tulis git), itu mungkin tidak akan pernah diterima di hulu (unionfs, aufs, cryptodev, tuxonice, dll ...)
Referensi:
batch
memasukkan syscalls ke dalambatch
syscalls, Anda dapat membuat pohon panggilan yang dalam secara sewenang-wenang dari syscall yang sewenang-wenang. Pada dasarnya, Anda dapat menempatkan seluruh aplikasi Anda menjadi satu syscall.