Bagaimana Swift bisa jauh lebih cepat daripada Objective-C dalam perbandingan ini?

115

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:

masukkan deskripsi gambar di sini

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:

  1. Bagaimana bahasa pemrograman baru bisa lebih cepat?
  2. Apakah hasil Objective-C disebabkan oleh kompiler yang buruk atau apakah ada sesuatu yang kurang efisien di Objective-C daripada Swift?
  3. Bagaimana Anda menjelaskan peningkatan kinerja 40%? Saya mengerti bahwa pengumpulan sampah / kontrol referensi otomatis mungkin menghasilkan beberapa overhead tambahan, tapi ini banyak?
Kuning
sumber
13
@MathewFoscarini Obj-C pergi ke assembler, tapi punya mekanisme pengiriman pesan objek yang mahal. Untuk sebagian besar pekerjaan GUI itu tidak masalah, tetapi untuk menyortirnya sangat penting.
Donal Fellows
17
Perbandingan dengan Python adalah head-scratcher asli di sini.
asthasr
9
@syrion pemasaran, dan bahasa tersebut tampaknya meminjam dari sintaksis python (seperti golang). Mereka mencoba untuk mengatakan "hei, pengembang python, Anda dapat menulis sesuatu yang tidak terlalu asing di mac dan membuatnya SO jauh lebih cepat, bahkan lebih cepat daripada Objective C yang Anda tidak pernah benar-benar
4
@Michael. Aku mengerti, tapi itu masih aneh. Siapa pun yang tahu apa-apa tentang bahasa akan menyadari bahwa Python, sebagai bahasa yang ditafsirkan, tidak akan berada di stadion baseball yang sama seperti Objective-C atau bahasa yang dikompilasi lainnya (untuk sebagian besar tugas). Menggunakannya sebagai patokan itu aneh.
asthasr
7
Mereka mungkin berarti waktu yang diperlukan untuk menulis kode ...
Lukas Eder

Jawaban:

62

Pertama, (IMO) membandingkan dengan Python hampir tidak ada artinya. Hanya perbandingan dengan Objective-C yang bermakna.

  • Bagaimana bahasa pemrograman baru bisa lebih cepat?

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 ...

  • Apakah hasil Objective-C dari kompiler buruk atau ada sesuatu yang kurang efisien di Objective-C daripada Swift?

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.

  • Bagaimana Anda menjelaskan peningkatan kinerja 40%? Saya mengerti bahwa pengumpulan sampah / kontrol referensi otomatis mungkin menghasilkan beberapa overhead tambahan, tapi ini banyak?

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_unretaineddan di Swift, (meskipun masih agak tidak jelas bagi saya) unownedbarang. 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.

Eonil
sumber
4
Pengumpulan sampah, terutama generasi, biasanya jauh lebih cepat daripada penghitungan referensi.
Jan Hudec
9
@JanHudec Anda secara signifikan lebih cepat sama sekali tidak berarti di bidang grafik realtime. Itu sebabnya saya menyebutkan lompatan besar diperlukan pada GC. Generational GC bahkan tidak mendekati bebas lonjakan baik secara teoritis maupun praktis.
Eonil
5
Lebih cepat dan bebas spike adalah kategori yang sepenuhnya ortogonal. Pengumpul sampah generasi lebih cepat . Mereka tidak bebas lonjakan.
Jan Hudec
4
Yang Anda bicarakan adalah throughput . Lebih cepat selalu merupakan istilah yang samar-samar, dan dapat berarti apa saja sesuai konteksnya. Jika Anda ingin berdebat tentang makna istilah, Anda harus menggunakan istilah yang lebih tepat daripada lebih cepat terutama mempertimbangkan konteks saat ini - grafik waktu nyata.
Eonil
11
@JanHudec: Pada perangkat seluler, atau perangkat apa pun dengan sumber daya terbatas, GC tidak secara signifikan lebih cepat dan pada kenyataannya merupakan bagian utama dari masalah.
Mason Wheeler
72

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.

Jan Hudec
sumber
13
Saya tidak begitu mengerti inti dari jawaban ini. Apakah Anda menjawab "bagaimana cepatnya lebih cepat" dengan mengatakan "tolok ukurnya cacat"? Apakah itu maksud Anda? Saya tidak melihat bagaimana itu menjawab apa yang ditanyakan.
Bryan Oakley
15
@BryanOakley: Saya rasa tolok ukurnya tidak cacat, tetapi kemungkinan mereka memilih satu tolok ukur di mana Swift lebih cepat tentunya harus dipertimbangkan.
Jan Hudec
23
Ada kemungkinan bahwa jawaban untuk "Bagaimana Swift lebih cepat?" mungkin "Bukan, sebenarnya", @BryanOakley; itulah inti yang saya dapatkan dari jawaban Jan. "Kebohongan, kebohongan, dan statistik", setelah semua.
Josh Caswell
4
Beberapa waktu lalu kami membuat benchmark Codename One yang berjalan di iOS dan implementasi Java kami jauh lebih cepat daripada Objective-C codenameone.com/blog/... Jan benar, pengiriman dinamis benar-benar lambat, jika mereka memperbaikinya bahkan sedikit maka beberapa tolok ukur akan menunjukkan peningkatan besar. Jika mereka meningkatkan ARC bahkan dalam sepersekian (berkat analisis kode yang lebih baik) mereka dapat menghilangkan sejumlah kompleksitas yang konyol. Semakin terbatas bahasa, semakin banyak yang dapat dilakukan kompiler untuk mengoptimalkan (lihat Java) dan Swift menambahkan batasan.
Shai Almog
7
Jawaban Jan adalah jawaban sempurna untuk Q1 dan mungkin Q2. Ketika saya melihat tolok ukur pada acara pemasaran sebagai keynote, saya berpikir: "Wow, hanya 1,3x dalam kasus terbaik yang dipilih. Apa yang akan kita hasil rata-rata? 0,3x?"
Amin Negm-Awad
5

Objective-C secara dinamis mengirimkan setiap pemanggilan metode.

Hipotesis: Tolok ukur menggunakan pengetikan statis untuk membiarkan kompiler Swift mengangkat comparemetode pencarian keluar dari sortloop. 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.)

Jerry101
sumber
3

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.

greg.casamento
sumber
2
ini berbunyi lebih seperti komentar ranty, lihat How to Answer
gnat
2
Apakah sekarang lebih baik? :)
greg.casamento
0

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).

Dicat hitam
sumber
13
Melakukan tolok ukur "objek kompleks" akan sedikit sulit dalam bahasa seperti C yang tidak memiliki implementasi objek asli. Mengingat bahwa audiensi untuk pembicaraan ini kemungkinan adalah 100% programmer Objective-C, membandingkan dengan bahasa seperti C ++ juga tidak masuk akal. Inti dari swift bukanlah "hei, ini bahasa terbaik yang pernah ada!" melainkan "hei, ini lebih cepat dari bahasa yang Anda gunakan sekarang untuk pengembangan OSX / iOS".
Bryan Oakley
10
C memiliki denda sempurna qsortyang akan memungkinkan penyortiran objek yang kompleks; itu hanya menggunakan panggilan balik yang memahami objek yang ada di tangan. Saya curiga C ++ hilang karena std::sortakan mempermalukan Swift. (Karena ini adalah templat, kompiler C ++ dapat sangat mengoptimalkannya, hingga loop terbuka.)
MSalters
@MSalters: Saya sepenuhnya setuju dengan Anda. Baik C dan C ++ memiliki kemampuan untuk berlari lebih cepat dari Swift. Apakah mungkin untuk mendapatkan tes yang dieksekusi. Saya lebih dari bersedia untuk mengeksekusi tolok ukur yang sama dengan Swift, Objective-C, C ++ dan C.
Painted Black
@BryanOakley juga, "Bahasa ini membutuhkan lebih sedikit tanda kurung!"
Nick Bedford
1
Jawaban ini tidak menampung air sama sekali dan menyesatkan. OO tidak terlalu lambat, bahkan sistem tercepat yang akan Anda temukan adalah C ++, Java dan C # dan gaya (sangat OO atau tidak) pemrograman tidak akan banyak berhubungan dengan kecepatan yang dihasilkan kecuali Anda benar-benar memiliki kode yang buruk.
Bill K