Apakah layak beralih dari Python ke Nim untuk performa?

Nim adalah campuran sintaks Python dan kinerja C







Beberapa minggu yang lalu saya menjelajahi GitHub dan menemukan repositori yang menarik: proyek itu seluruhnya ditulis dalam bahasa Nim . Saya belum pernah bertemu dengannya sebelumnya, dan kali ini saya memutuskan untuk mencari tahu jenis hewan apa itu.



Pada awalnya saya berpikir bahwa saya ketinggalan zaman, bahwa ini adalah salah satu bahasa pemrograman umum yang banyak digunakan secara aktif, tidak seperti saya. Dan kemudian saya memutuskan untuk mempelajarinya.



Inilah kesimpulan saya:



  • Bahasa ini sebenarnya populer di kalangan orang-orang yang sempit.
  • Mungkin seharusnya begitu.


Jadi, saya akan ceritakan sedikit tentang pengalaman saya dengan Nim, secara singkat berbicara tentang fitur-fitur pemrograman di dalamnya, dan juga mencoba membandingkannya dengan Python dan C. Ke depan, saya perhatikan bahwa bahasa ini tampaknya sangat menjanjikan bagi saya.



Kode di studio!



Sebagai contoh, saya memutuskan untuk menulis sesuatu yang lebih rumit daripada halo, dunia dalam Nim:







Sepertinya tidak ada yang berlebihan, bukan? Tampaknya sangat sederhana sehingga Anda dapat dengan mudah mengetahui apa yang dilakukannya, bahkan jika Anda belum pernah mendengar tentang Nim sebelumnya. (Program akan menampilkan: "num: 5 i: 5")



Jadi, mari kita analisis apa yang tampaknya kita kenal dari suatu tempat.



Deklarasi variabel



Ini sangat familiar bagi pengembang JavaScript. Sementara beberapa bahasa menggunakan var dan beberapa menggunakan let, JS dan Nim memungkinkan Anda untuk menggunakan keduanya saat mendeklarasikan variabel. Namun, penting untuk dicatat bahwa keduanya bekerja secara berbeda di Nim daripada di JS. Tapi lebih dari itu nanti.



Blok



Untuk menunjukkan blok baru di Nim, kami menggunakan titik dua diikuti dengan baris menjorok. Semuanya seperti di Python.



Kata kunci



Kedua loop dan pernyataan if terlihat seperti bagian dari kode Python. Faktanya, semuanya dari baris 5 dan seterusnya adalah kode Python (dengan asumsi kita memiliki fungsi echo yang ditentukan).



Jadi ya, banyak kata kunci dan operator Python juga dapat digunakan di Nim: not, is, dan, atau, dan seterusnya.



Artinya, sejauh ini kami tidak melihat sesuatu yang istimewa di Nim: versi terburuk dari Python (dalam hal

sintaks), dengan mempertimbangkan fakta bahwa Anda perlu menggunakan let atau var untuk mendeklarasikan variabel.



Kita bisa berhenti di situ, tapi ada "tetapi" yang besar: Nim adalah bahasa yang diketik secara statis yang bekerja hampir secepat bahasa C.



Nah, sekarang percakapan lain. Mari kita lihat.



Uji kinerja







Sebelum kita menyelami sintaks Nim (terutama bagian yang diketik secara statis yang belum kita lihat sejauh ini), mari coba mengevaluasi kinerjanya. Untuk melakukan ini, saya menulis implementasi naif untuk menghitung angka Fibonacci ke-n dalam Nim, Python, dan C.



Agar semuanya tetap adil, saya menstandarkan implementasi berdasarkan solusi Leetcode (Opsi 1) dan mencoba mematuhinya seketat mungkin dalam ketiga bahasa.



Anda tentu saja dapat mengingatkan saya pada LRU Cache . Tetapi untuk saat ini, tugas saya adalah menggunakan pendekatan standar, dan tidak mencoba mengoptimalkan perhitungan. Jadi saya memilih implementasi yang naif.


Berikut adalah hasil untuk menghitung bilangan Fibonacci ke-40:







Ya, secara tegas, eksperimen tidak dapat disebut bersih, tetapi ini berkorelasi dengan hasil dari peminat lain yang melakukan tes yang lebih serius [1] [2] [3] .



Semua kode yang saya tulis untuk artikel ini tersedia di GitHub, termasuk petunjuk tentang cara menjalankan eksperimen ini.



Jadi mengapa Nim jauh lebih cepat dari Python?



Nah, menurut saya ada dua alasan utama:



  1. Nim adalah bahasa yang dikompilasi dan Python adalah bahasa yang ditafsirkan (lebih lanjut tentang itu di sini ). Ini berarti bahwa lebih banyak pekerjaan dilakukan ketika Anda menjalankan program Python karena program harus diinterpretasikan sebelum dapat dijalankan. Ini biasanya membuat bahasa menjadi lebih lambat.
  2. Nim diketik secara statis. Meskipun tidak ada deklarasi tipe dalam contoh yang saya tunjukkan sebelumnya, kita akan melihat nanti bahwa itu memang bahasa yang diketik secara statis. Dalam kasus Python, yang diketik secara dinamis, interpreter memiliki lebih banyak pekerjaan yang harus dilakukan untuk mendefinisikan dan menangani tipe dengan tepat. Ini juga mengurangi kinerja.


Kecepatan kerja tumbuh - kecepatan pengkodean menurun



Inilah yang dikatakan Python Docs tentang bahasa yang ditafsirkan:

« / , , ».


Ini adalah generalisasi yang baik dari tradeoff antara Python dan C, misalnya. Apa pun yang dapat Anda lakukan dengan Python dapat Anda lakukan di C, tetapi program C Anda akan berjalan berkali-kali lebih cepat.



Tetapi Anda akan menghabiskan lebih banyak waktu untuk menulis dan men-debug kode C Anda, itu akan menjadi sulit dan kurang dapat dibaca. Dan itulah mengapa C tidak lagi diminati dan Python populer. Dengan kata lain, Python jauh lebih sederhana (secara komparatif, tentu saja).



Jadi, jika Python berada di salah satu ujung spektrum dan C di ujung lain, maka Nim mencoba untuk mendapatkan di suatu tempat di tengah. Ini jauh lebih cepat daripada Python, tetapi tidak sesulit program C.



Mari kita lihat implementasi kita dalam menghitung bilangan Fibonacci.



DARI:



#include <stdio.h>
int fibonacci(int n) {
    if (n <= 1) {
        return n;
    } 
    return fibonacci(n-1) + fibonacci(n-2);
}

int main(void) {
    printf("%i", fibonacci(40));
}


Python:



def fibonacci(n):
    if n <= 1:
        return n
    return fibonacci(n-1) + fibonacci(n-2)

print(fibonacci(40))


Nim:



proc fibonacci(n: int): int = 
    if n <= 1:
        return n
    return fibonacci(n-1) + fibonacci(n-2)

echo(fibonacci(40))


Meskipun Nim menggunakan tanda "=" dalam sintaks prosedurnya (fungsi), secara umum jauh lebih mudah untuk menulis kode daripada di C.



Mungkin ini benar-benar trade-off yang layak? Sedikit lebih sulit untuk ditulis daripada Python, tetapi bekerja sepuluh kali lebih cepat. Saya bisa hidup dengan itu.



Sintaks Nim



import strformat

#    https://nim-lang.org/

type
  Person = object
    name: string
    age: Natural #      

let people = [
  Person(name: "John", age: 45),
  Person(name: "Kate", age: 30)
]

for person in people:

  echo(fmt"{person.name} is {person.age} years old")


Saya hanya akan menunjukkan fitur utamanya.



Variabel



Kami menggunakan var, let atau const untuk mendeklarasikan variabel.



var dan const bekerja dengan cara yang sama seperti di JavaScript, tetapi mari kita ceritanya berbeda.



JavaScript let berbeda dari var dalam hal cakupan, dan Nim let menunjukkan variabel yang nilainya tidak dapat berubah setelah inisialisasi. Sepertinya Swift bagi saya.



Tapi bukankah itu sama dengan konstanta? - Anda bertanya.



Tidak. Dalam Nim, perbedaan antara const dan let adalah sebagai berikut:

Untuk const, compiler harus dapat menentukan nilai pada waktu kompilasi, sedangkan untuk let dapat ditentukan pada saat run time.


Contoh dari dokumentasi:



const input = readLine(stdin) # Error: constant expression expected
let input = readLine(stdin)   #  


Sebagai alternatif, variabel dapat dideklarasikan dan diinisialisasi seperti ini:



var
   a = 1
   b = 2
   c = 3
   x, y = 10 #   x  y   10


Fungsi



Fungsi di Nim disebut prosedur:



proc procedureName(parameterName: parameterType):returnType =
   return returnVar


Mengingat bahasanya mirip dengan Python dalam banyak hal, prosedurnya tampak sedikit aneh saat Anda pertama kali melihatnya.



Menggunakan "=" alih-alih "{" atau ":" jelas membingungkan. Semuanya sedikit lebih baik dengan menulis prosedur dalam satu baris:



proc hello(s: string) = echo s


Anda juga bisa mendapatkan hasil dari fungsinya:



proc toString(x: int): string =
   result =
       if x < 0: “negative”
       elif x > 0: “positive”
       else: “zero”


Sepertinya Anda masih perlu mengembalikan hasil, tetapi dalam kasus ini, hasil bukanlah variabel - ini adalah kata kunci. Jadi potongan kode di atas akan benar dari sudut pandang Nim.



Anda juga dapat membebani prosedur:




proc toString(x: int): string =   
    result =     
        if x < 0: "negative"     
        elif x > 0: "positive"     
        else: "zero"  
proc toString(x: bool): string =   
    result =     
        if x: "yep"     
        else: "nope"
echo toString(true) #  "yep"
echo toString(5) #  "positive"


Kondisi dan siklus



Ini banyak hubungannya dengan Python.



# if true:

# while true:

# for num in nums:


Untuk mengulang daftar, misalnya, alih-alih range (), Anda bisa menggunakan hitung mundur (mulai, selesai) , atau mundur (mulai, selesai) . Anda dapat melakukannya dengan lebih mudah dan menggunakan untuk saya di awal .. selesai



Masukan dan keluaran pengguna



let input = readLine(stdin)
echo input


Dibandingkan dengan Python, readLine (stdin) setara dengan input () dan echo setara dengan print.



echo dapat digunakan dengan atau tanpa tanda kurung.



Tujuan saya adalah memberi Anda pemahaman dasar tentang Nim, bukan menceritakan kembali semua dokumentasinya. Jadi saya berakhir dengan sintaks dan beralih ke fitur bahasa lainnya.



Fitur tambahan



Pemrograman berorientasi objek



Nim bukanlah bahasa berorientasi objek, tetapi Nim memberikan dukungan minimal untuk bekerja dengan objek . Tentu saja, dia jauh dari kelas Python.



Makro



Nim mendukung makro dan metaprogramming, dan para pengembang tampaknya sangat menekankan hal ini. Ini adalah subjek sendiri bagian dari seri tiga pelajaran.



Contoh kecil:



import macros  macro myMacro(arg: static[int]): untyped =  
   echo arg

myMacro(1 + 2 * 3)


Tipe data dasar



string, char, bool, int, uint  float.


Anda juga dapat menggunakan jenis ini:



int8, int16, int32, int64, uint8, uint16, uint32, uint64, float32, float64


Selain itu, string dalam Nim adalah tipe yang bisa berubah, tidak seperti Python.



Komentar



Tidak seperti Python, Nim menggunakan karakter "#" dalam kombinasi dengan "[" dan "]" untuk komentar multiline.



# a comment#[
a
multi
line
comment
]#


Mengompilasi JavaScript



Nim dapat menerjemahkan kodenya ke JavaScript. Tidak yakin apakah banyak orang yang datang untuk menggunakan ini. Tapi ada contoh game browser Snake yang ditulis di Nim.



Iterator



Iterator Nim lebih seperti generator Python:



iterator countup(a, b: int): int =
   var res = a
   while res <= b:
       yield res
       inc(res)


Case Sensitivity dan Underscore

Nim hanya case sensitive untuk karakter pertama.



Artinya, ini membedakan antara HelloWorld dan helloWorld, tetapi bukan helloWorld, helloworld, dan hello_world. Oleh karena itu, prosedur berikut akan bekerja tanpa masalah, misalnya:



proc my_func(s: string) =
   echo myFunc("hello")


Seberapa populer Nim?







Nim memiliki hampir 10.000 bintang di GitHub. Ini adalah nilai tambah yang jelas. Namun demikian, saya mencoba memperkirakan popularitas bahasa dari sumber lain, dan, tentu saja, tidak setinggi itu.



Misalnya, Nim bahkan tidak disebutkan dalam Survei Stack Overflow 2020 . Saya tidak dapat menemukan pekerjaan pengembang Nim di LinkedIn (bahkan dengan geografi Seluruh Dunia), dan pencarian untuk tag [nim-lang] di Stack Overflow hanya menghasilkan 349 pertanyaan (bandingkan dengan ~ 1.500.000 untuk Python atau 270.000 untuk Swift)



. Dengan demikian, akan adil untuk mengasumsikan bahwa sebagian besar pengembang belum menggunakannya dan banyak yang belum pernah mendengar bahasa Nim.



Mengganti Python?



Sejujurnya, menurut saya Nim adalah bahasa yang cukup keren. Untuk menulis artikel ini, saya mempelajari minimal yang disyaratkan, tapi itu sudah cukup. Meskipun saya belum membahasnya terlalu dalam, saya berencana menggunakan Nim di masa depan. Secara pribadi, saya penggemar berat Python, tetapi saya juga menyukai bahasa yang diketik secara statis. Jadi bagi saya, peningkatan kinerja dalam beberapa kasus lebih dari sekadar membuat sedikit redundansi sintaksis.



Meskipun sintaks dasarnya sangat mirip dengan Python, ini lebih kompleks. Oleh karena itu, sebagian besar penggemar Python kemungkinan besar tidak akan tertarik dengannya.



Juga, jangan lupakan bahasa Go. Saya yakin banyak dari Anda telah memikirkan hal ini saat Anda membaca, dan memang demikian. Terlepas dari kenyataan bahwa sintaks Nim lebih dekat dengan sintaks Python, dalam hal kinerja ia bersaing dengan bahasa a la "C ++ yang disederhanakan".

Saya pernah menguji kinerja Go. Secara khusus, untuk Fibonacci (40), ini bekerja secepat C.


Tapi tetap: bisakah Nim bersaing dengan Python? Saya sangat meragukannya. Kami melihat tren peningkatan kinerja komputer dan penyederhanaan pemrograman. Dan, seperti yang saya catat, bahkan jika Nim menawarkan trade-off sintaks / kinerja yang baik, saya rasa itu tidak cukup untuk mengalahkan Python yang murni dan serbaguna.

Saya berbicara dengan salah satu pengembang Nim Core. Menurutnya Nim lebih cocok untuk mereka yang bermigrasi dari C ++ daripada untuk pythonist.


Bisakah Nim bersaing dengan Go? Mungkin (jika Google "mengizinkan"). Bahasa Nim sekuat Go. Selain itu, Nim memiliki dukungan yang lebih baik untuk fitur C / C ++, termasuk makro dan overloading.



Tapi lebih banyak tentang itu lain kali.






Periklanan



Server Epic adalah server virtual terjangkau dengan prosesor dari AMD, frekuensi inti CPU hingga 3,4 GHz. Konfigurasi maksimum akan memungkinkan Anda untuk menggunakan 128 core CPU, RAM 512 GB, NVMe 4000 GB. Cepat pesan!






All Articles