Apple meluncurkan bahasa pemrograman baru Swift di WWDC14 . Dalam presentasi, mereka membuat beberapa perbandingan kinerja antara Objective-C dan Python. Berikut ini adalah gambar salah satu slide mereka, perbandingan dari ketiga bahasa yang melakukan semacam objek kompleks:
Bahkan ada grafik yang lebih luar biasa tentang perbandingan kinerja menggunakan algoritma enkripsi RC4 .
Jelas ini adalah pembicaraan pemasaran, dan mereka tidak menjelaskan secara terperinci bagaimana ini diterapkan di masing-masing. Saya membuat saya bertanya-tanya:
- Bagaimana bahasa pemrograman baru bisa lebih cepat?
- Apakah hasil Objective-C disebabkan oleh kompiler yang buruk atau apakah ada sesuatu yang kurang efisien di Objective-C daripada Swift?
- Bagaimana Anda menjelaskan peningkatan kinerja 40%? Saya mengerti bahwa pengumpulan sampah / kontrol referensi otomatis mungkin menghasilkan beberapa overhead tambahan, tapi ini banyak?
Jawaban:
Pertama, (IMO) membandingkan dengan Python hampir tidak ada artinya. Hanya perbandingan dengan Objective-C yang bermakna.
Objective-C adalah bahasa yang lambat. (Hanya bagian C yang cepat, tapi itu karena itu C) Tidak pernah sangat cepat. Itu cukup cepat untuk tujuan mereka (Apple), dan lebih cepat dari versi lama mereka. Dan itu lambat karena ...
Objective-C menjamin setiap metode dikirim secara dinamis. Tidak ada pengiriman statis sama sekali. Itu membuatnya mustahil untuk mengoptimalkan program Objective-C lebih lanjut. Yah, mungkin teknologi JIT dapat membantu, tetapi AFAIK, Apple benar-benar membenci karakteristik kinerja yang tidak terduga dan objek seumur hidup. Saya tidak berpikir mereka telah mengadopsi hal-hal JIT. Swift tidak memiliki jaminan pengiriman dinamis seperti itu kecuali Anda menaruh beberapa atribut khusus untuk kompatibilitas Objective-C.
GC atau RC tidak masalah di sini. Swift juga menggunakan RC terutama. Tidak ada GC di sana, dan juga tidak akan kecuali ada lompatan arsitektur besar pada teknologi GC. (IMO, selamanya) Saya percaya Swift memiliki lebih banyak ruang untuk optimasi statis. Terutama algoritma enkripsi level rendah, karena mereka biasanya mengandalkan perhitungan numerik besar, dan ini adalah kemenangan besar untuk bahasa pengiriman statis.
Sebenarnya saya terkejut karena 40% sepertinya terlalu kecil. Saya berharap jauh lebih banyak. Bagaimanapun, ini adalah rilis awal, dan saya pikir optimisasi bukanlah perhatian utama. Swift bahkan tidak lengkap fitur! Mereka akan membuatnya lebih baik.
Memperbarui
Beberapa terus menggangguku untuk berargumen bahwa teknologi GC lebih unggul. Meskipun hal-hal di bawah ini bisa diperdebatkan, dan hanya pendapat saya yang sangat bias, tapi saya pikir saya harus mengatakan untuk menghindari argumen yang tidak perlu ini.
Saya tahu apa itu GC konservatif / tracing / generasional / inkremental / paralel / realtime dan bagaimana mereka berbeda. Saya pikir sebagian besar pembaca juga sudah tahu itu. Saya juga setuju bahwa GC sangat bagus di beberapa bidang, dan juga menunjukkan throughput yang tinggi dalam beberapa kasus.
Bagaimanapun, saya menduga klaim throughput GC selalu lebih baik daripada RC. Sebagian besar overhead RC berasal dari operasi penghitungan ulang dan penguncian untuk melindungi variabel angka penghitungan ulang. Dan implementasi RC biasanya menyediakan cara untuk menghindari penghitungan operasi. Di Objective-C, ada
__unsafe_unretained
dan di Swift, (meskipun masih agak tidak jelas bagi saya)unowned
barang. Jika biaya operasi penghitungan ulang tidak dapat diterima, Anda dapat mencoba untuk memilihnya secara selektif dengan menggunakan mekanisme. Secara teoritis, kita dapat mensimulasikan skenario kepemilikan yang hampir unik dengan menggunakan referensi tidak mempertahankan sangat agresif untuk menghindari overhead RC. Saya juga berharap kompiler dapat menghilangkan beberapa operasi RC yang jelas tidak perlu secara otomatis.Tidak seperti sistem RC, AFAIK, penyisihan sebagian tipe referensi bukan opsi pada sistem GC.
Saya tahu ada banyak grafis dan game yang dirilis yang menggunakan sistem berbasis GC, dan juga tahu kebanyakan dari mereka menderita karena kurangnya determinisme. Tidak hanya untuk karakteristik kinerja, tetapi juga objek manajemen seumur hidup. Unity sebagian besar ditulis dalam C ++, tetapi bagian C # kecil menyebabkan semua masalah kinerja aneh. Aplikasi hibrida HTML dan masih menderita oleh lonjakan tak terduga di sistem apa pun. Digunakan secara luas tidak berarti itu unggul. Itu berarti mudah dan populer bagi orang-orang yang tidak memiliki banyak pilihan.
Perbarui 2
Sekali lagi untuk menghindari argumen atau diskusi yang tidak perlu, saya menambahkan beberapa detail lagi.
@ Asik memberikan pendapat yang menarik tentang paku GC. Itu yang bisa kita anggap pendekatan nilai-tipe-di mana-mana sebagai cara untuk memilih keluar dari barang-barang GC. Ini cukup menarik, dan bahkan dapat dilakukan pada beberapa sistem (misalnya pendekatan murni fungsional). Saya setuju bahwa ini bagus secara teori. Namun dalam praktiknya ada beberapa masalah. Masalah terbesar adalah aplikasi parsial dari trik ini tidak memberikan karakteristik bebas lonjakan yang benar.
Karena masalah latensi selalu menjadi masalah semua atau tidak sama sekali . Jika Anda memiliki satu lonjakan frame selama 10 detik (= 600 frame), maka seluruh sistem jelas gagal. Ini bukan tentang bagaimana lebih baik atau lebih buruk. Itu hanya lulus atau gagal. (atau kurang dari 0,0001%) Lalu di mana sumber lonjakan GC? Itu distribusi beban GC yang buruk. Dan itu karena GC secara fundamental tidak pasti. Jika Anda membuat sampah, maka itu akan mengaktifkan GC, dan lonjakan akan terjadi pada akhirnya. Tentu saja, di dunia ideal di mana beban GC akan selalu ideal, ini tidak akan terjadi, tapi saya hidup di dunia nyata daripada dunia ideal imajiner.
Kemudian jika Anda ingin menghindari lonjakan, Anda harus menghapus semua jenis ref dari keseluruhan sistem. Tapi itu sulit, gila, dan bahkan tidak mungkin karena bagian yang tidak dapat dilepaskan seperti .NET core system dan library. Hanya menggunakan sistem non-GC jauh lebih mudah .
Tidak seperti GC, RC pada dasarnya adalah deterministik, dan Anda tidak harus menggunakan optimasi gila ini (hanya tipe nilai saja) hanya hanya untuk menghindari spike. Yang harus Anda lakukan adalah melacak dan mengoptimalkan bagian yang menyebabkan lonjakan. Dalam sistem RC, spike adalah masalah algoritma lokal, tetapi dalam sistem GC, lonjakan selalu menjadi masalah sistem global.
Saya pikir jawaban saya sudah terlalu banyak di luar topik, dan sebagian besar hanya pengulangan diskusi yang ada. Jika Anda benar-benar ingin mengklaim keunggulan / inferioritas / alternatif atau hal lain dari barang-barang GC / RC, ada banyak diskusi yang ada di situs ini dan StackOverflow, dan Anda dapat terus bertarung di sana.
sumber
Menjadi 3,9 kali lebih cepat dari python, bahasa yang secara konsisten kehilangan sebagian besar tolok ukur dengan margin yang cukup besar (ok, itu setara dengan Perl, Ruby dan PHP; tetapi ia kalah dari apa pun yang diketik secara statis), bukanlah sesuatu yang harus dibanggakan oleh siapa pun.
The benchmark permainan menunjukkan C ++ program yang lebih dari urutan besarnya lebih cepat dari program python dalam kebanyakan kasus. Tidak jauh lebih baik ketika membandingkan dengan Java, C # (pada Mono), OCaml, Haskell dan bahkan Clojure, yang tidak diketik secara statis.
Jadi pertanyaan sebenarnya adalah bagaimana Objective-C hanya 2,8 kali lebih cepat dari python. Tampaknya mereka dengan hati-hati memilih patokan di mana pengiriman ObjC yang lambat sepenuhnya dinamis sangat menyakitkan. Setiap bahasa yang diketik secara statis harus dapat melakukan lebih baik Dalam pengurutan objek kompleks ada banyak pemanggilan metode untuk membandingkan objek dan perbandingan sebenarnya mungkin tidak terlalu kompleks itu sendiri. Jadi jika Swift setidaknya mengambil beberapa keuntungan dari informasi jenis, ia dapat dengan mudah melakukan lebih baik pada pemanggilan metode dan tidak ada cukup operasi lain yang ObjC bisa menjadi lebih baik.
Tentu saja, seperti yang ditunjukkan oleh permainan benchmark , kinerja relatif pada tugas yang berbeda sangat bervariasi, sehingga satu tolok ukur tidak benar-benar representatif. Jika mereka memiliki tolok ukur di mana itu memiliki keuntungan yang lebih besar, mereka akan menunjukkan kepada kita satu itu sebagai gantinya, jadi pada tugas lain itu mungkin tidak lebih baik atau tidak terlalu banyak.
sumber
Objective-C secara dinamis mengirimkan setiap pemanggilan metode.
Hipotesis: Tolok ukur menggunakan pengetikan statis untuk membiarkan kompiler Swift mengangkat
compare
metode pencarian keluar darisort
loop. Ini membutuhkan pembatasan tipe sempit yang hanya memungkinkan objek Kompleks dalam array, bukan subkelas Kompleks.(Di Objective-C Anda bisa mengerek pencarian metode secara manual jika Anda benar-benar ingin, dengan memanggil dukungan runtime bahasa untuk mencari penunjuk metode. Anda sebaiknya memastikan bahwa semua instance dalam array adalah dari kelas yang sama .)
Hipotesis: Swift mengoptimalkan panggilan penghitungan referensi dari loop.
Hipotesis: Patokan Swift menggunakan struct Kompleks sebagai ganti objek Objective-C, jadi perbandingan semacam tidak perlu pengiriman metode dinamis (karena tidak dapat disubklasifikasi) atau pekerjaan penghitungan referensi (karena itu adalah tipe nilai).
(Dalam Objective-C Anda dapat kembali ke C / C ++ untuk kinerja selama itu tidak melibatkan objek Objective-C, misalnya mengurutkan array C dari struct.)
sumber
Jujur, kecuali mereka merilis sumber untuk tes yang mereka gunakan, saya tidak akan percaya apa pun yang dikatakan Apple tentang masalah ini. Ingat, ini adalah perusahaan yang beralih dari PPC ke Intel berdasarkan kekhawatiran daya ketika 6 bulan sebelumnya mereka mengatakan bahwa Intel mengisap dan benar-benar membakar kelinci Intel dalam sebuah iklan. Saya ingin melihat bukti yang sulit dibantah bahwa Swift lebih cepat daripada ObjC dalam lebih banyak kategori daripada hanya menyortir.
Selain itu Anda harus mempertanyakan statistik apa pun yang dirilis di WWDC karena mereka memiliki bau pemasaran di seluruh mereka.
Semua itu dikatakan saya sendiri belum menjalankan tes antara swift dan ObjC, tetapi dari apa yang saya tahu swift memiliki ekstensi IR LLVM itu sendiri dan mungkin saja lebih banyak optimasi dilakukan pada waktu kompilasi daripada di ObjC.
Pengungkapan Penuh: Saya menulis kompiler Swift open source yang terletak di https://ind.ie/phoenix/
Jika ada yang ingin membantu memastikan bahwa Swift tidak hanya tersedia di perangkat keras Apple, beri tahu saya dan saya akan dengan senang hati menyertakan Anda.
sumber
Saya telah berjuang sendiri melalui tutorial Swift, dan menurut saya Swift lebih membumi (membuat saya berpikir tentang Visual Basic) dengan lebih sedikit 'objek-ification' daripada Objective-C. Seandainya mereka memperhitungkan C atau C ++, saya kira yang terakhir akan menang, karena mereka bahkan lebih kompilasi-waktu saja.
Dalam hal ini, saya menganggap Objective-C adalah korban dari kemurnian berorientasi objek (dan overhead).
sumber
qsort
yang akan memungkinkan penyortiran objek yang kompleks; itu hanya menggunakan panggilan balik yang memahami objek yang ada di tangan. Saya curiga C ++ hilang karenastd::sort
akan mempermalukan Swift. (Karena ini adalah templat, kompiler C ++ dapat sangat mengoptimalkannya, hingga loop terbuka.)