Programlama dillerinin mükemmel bir genel bakış testi. Yedi programlama dilinin deneysel karşılaştırması

  • 12.05.2019

Bu makalenin amacı: Işık tutun ve çok sayıda tartışmayı özetleyin ve oh benprogramlama dilleri. Daha çok programlama yarışmaları alanıyla ilgili, ancak yorumlarımı olabildiğince spesifik yazmaya, geliştirmeye ve programlama dillerini geliştirme ve geliştirme sürecime bir şeyler eklemeye çalışıyorum. Bugün 18 Nisan 2010.

Pascal ( zorunlu, yapılandırılmış )

Arkasında:katı bir sözdizimine sahip çok basit bir dil - yeni başlayanlar için basit - programları yazmak ve bunlarda hata ayıklamak kolaydır.

Vs : yokluk standart kitaplıklar (kitaplıklara karşıC ++ ve Java).

C++ ( birçok paradigmayı destekler ( çoklu paradigma): nesneye yönelik, genel, prosedürel, metaprogramlama )

Arkasında:STL (standart şablon kitaplığı) - birçok standart veri türü ve algoritma. Büyük "özgürlük" - aynı şeyleri farklı şekillerde uygulayabilirsiniz. Derlenmiş kodun iyi performansı. İyi destekC ++ bugün.

Vs:Eksiklik BigInteger ve BigDecimal (kütüphanelerdedirlerJava ve C #). Derleyici ve programcı arasındaki yanlış anlaşılma nedeniyle çeşitli hatalar mümkündür. Bununla ilgili pek çok konu bulabilirsiniz ama bu bir dil problemi değil. Ancak çok büyük özgürlük nedeniyle, program yazmak ve hata ayıklamak daha zor olabilir.C ++.

Java ( nesne yönelimli, yapısal, zorunlu )

Arkasında:daha katı sözdizimiC ++ - kodun okunması daha kolay - hızlı ve kolay hata ayıklama. Hata ipuçları ve kullanılmayan kod. Bir çok çeşitli türlerde kütüphaneler. Çöp toplayıcı. Son sürümlerdeki yeni özellikler varım s( ör.: döngü varyasyonlarıiçin).

Vs:Programların yavaş çalışması (3-4 kez yavaş -denC / C ++), uzun ( sürekli uzun) kod, ancak kod yazmak hızlıdır çünkü otomatik tamamlama mevcuttur.

Fikrinde olmakPetr : Bence Java / C # (hız dışında aralarında çok fazla fark görmüyorum) programlama yarışmaları için en uygun yöntemdir, çünkü hata yapmak çok daha zordur ve bir Java programında bir hatayı bulup düzeltmek çok daha kolaydır. bir C / C ++ programındakinden.

Çok daha sıkı tip denetimi (uzun uzun -e int ve den int -e bool??), aralık dışı kontrol, kod akış kontrolü (başlatılmamış değişkenlerden okumaya izin veriyor? Neden bir dil buna izin veriyor?), sizin için birçok başka hata bulan harika IDE, fevkalade uygun hata ayıklama, daha açık sözdizimi (daha az güce sahip bir dil aslında sizi daha okunaklı programlar yazmaya yönlendirir), daha açık hata mesajları (ve hatalar her zaman tekrarlanabilir!) - -e birkaç avantajı söyleyin, ancak muhtemelen biraz daha kaçırdım.

Doğru programları yazmanın ve doğru olmadıklarında hızlı bir şekilde düzeltmenin yukarıda bahsedilen dezavantajlardan çok daha ağır bastığını düşünüyorum (daha yavaş uygulama, daha uzun programlar). 2x yavaşlama bile programlama yarışmalarında neredeyse hiç önemli değilken, WA her zaman :) Bir programlama yarışmasında çoğu zaman kod yazmakla değil (kod yazarken yaptığınızı düşünmek de dahil olmak üzere) düşünmeye harcandığına inanıyorum, bu nedenle programın uzunluğu (veya bu konuda yazma hızı) alakasızdır.

Ve çeşitli kütüphanelerin mevcudiyetinin de o kadar önemli olmadığına inanıyorum. Dolayısıyla, C ++ ve Pascal arasında seçim yaparsam, aynı argüman nedeniyle Pascal'ı seçerdim (çok daha sıkı her şeyin kontrolü).

Peter'ın fikrini tercüme etmedim çünkü İngilizce'de kulağa çok daha iyi geliyor.

C# ( birçok paradigmayı destekler ( çoklu paradigma): nesneye yönelik, genel, prosedürel programlama )

Arkasında:Java'dan daha hızlı . Standart KitaplıklarC#: son sürümde.olduğu gibi mevcutJava , uzun aritmetik ile çalışmak için sınıflar, ancak şimdi bunları temel türlerin değişkenleri olarak kullanabilirsiniz:c \u003d a + b, vb.

Vs:En son sürüm. çoğu programlama yarışmasında hala mevcut değil.

VB( yordamsal, nesne yönelimli, bileşen yönelimli, olay yönelimli )

AksineC#: Programlama dili -Visual Basic, C # değil.

Görüşmezunlar : VB. NET, Visual Basic sözdizimiyle yalnızca C # 'dır yazılan programların taşınabilirliğini kolaylaştırmak için yapılanVB ... Şunlar. düşünmek için bir sebep yokVB. AĞ.

Python ( nesne yönelimli, zorunlu, işlevsel, yön odaklı )

Görüş_ph_ :

Arkasında:Python - genel amaçlı bir dil, gerçek zamanlı programlar haricinde hemen hemen her tür program içinde yazılır. Python'un Google'daki 3 numaralı resmi dil olması tesadüf değil.

Python Kaydın kısalığı ve yerleşik araçların varlığı nedeniyle çok karmaşık olmayan sorunları çözmek için harika:

· yerleşik uzun aritmetik (hem tam sayı hem de kesirli)

· gömülü liste (aka vektör<>), set, dict, tuple (aka struct)

· normal ifadelerle çalışmak için kitaplık yeniden

· işlevi herhangi bir dizi için sıralanmış ()

· uygun dizi işlemleri

· kullanışlı liste oluşturucuları

· fonksiyonlar sum (), max (), min (), listeleri işleyebilir, vb.

Vs:Python'un Olimpiyat programlama açısından dezavantajları şunlardır:

· programların düşük yürütme hızı (ortalama olarak, 6 kat kayıp FROM++) ve özellikle yavaş G / Ç (bu nedenle özel ayarlamalar olmadan 1 saniyede 10 ^ 6 sayı bile okuyamazsınız)

· az rahat IDE'ler (bildiğim tek normal olan, Eclipse için PyDev'dir)

PHP ve diğer programlama dilleri.

Şimdiye kadar onları yarışmalarda kullanmak için bir neden göremiyorum. Herhangi bir itirazınız varsa - yazın.

Sonuç:

Mümkün olduğunca çok dil bilmek ve pratik yapmak, öğrenmek, tüm nüansları bilmek en iyisidir, ancak bu o kadar kolay değildir ve her zaman mümkün değildir. Biz insanız ve doğamızı değiştiremeyiz ama daha iyi olmaya çalışabiliriz. Her programlama dilinin kendine özgü avantajları ve dezavantajları vardır ve belirli farklı sorunları daha iyi çözmek için her zaman bunlardan birini seçebilirsiniz.

Ne istediğinize kendiniz karar vermelisiniz: dilin esnekliği ve özgürlüğü veya programları yazma, okuma, hata ayıklama ve sürdürme kolaylığı; yüksek hıza ihtiyacınız olup olmadığı ihmal edilebilir.

Umarım bu makale farklı programlama dilleri arasındaki farkları, bunların en temel avantaj ve dezavantajlarını anlamanıza yardımcı olmuştur.

Ek ve kullanılan bilgiler:

Java'ya Alternatif Olarak Lisp:http://norvig.com/java-lisp.html

Silah seçimi - tartışma: http: // kod kuvvetleri.ru/ blog / entry / 254

Silah seçimi 2 - tartışma: http://codeforces.ru/blog/entry/316

C#. Neden mono değil? : http: // kod kuvvetleri.ru/ blog / entry / 229

Hakkında birazC# veLinq: http: // kod kuvvetleri.ru/ blog / entry / 245

Kıyaslamalar ve performans karşılaştırmasıJava, C #, C ++:

Tanımlar:

Programcılar ve bilim adamları, çeşitli programlama dillerinin yararları ve dezavantajları söz konusu olduğunda önyargılı olma eğilimindedir. Yazar, birkaç dili karşılaştırarak C, C ++, Java, Perl, Python, Rexx ve Tcl hakkında objektif bilgi almaya çalıştı.

Karşılaştırma için, tüm diller için aynı gereksinimleri karşılayan bir program kullanıldı. Bu teknik karşılaştırma alanını daraltır, ancak homojen hale getirir. Ayrıca her dil için farklı programcılar tarafından hazırlanan birkaç ayrı program uygulamaları analiz edilmiştir. Grup yaklaşımının iki avantajı vardır. İlk olarak, bireysel programcılar arasındaki farklar düzelir, bu da her dil için tek bir "kalıba" dayalı herhangi bir karşılaştırmayı geçersiz kılabilir. İkinci olarak, farklı dillerde derlenen programların özelliklerinin değişkenliğini karşılaştırmak mümkün hale gelir.

Karşılaştırmalı çalışma, program uzunluğu, programlama çabası, yürütme süresi, bellek ayak izi ve güvenilirlik dahil olmak üzere her dilin çeşitli yönlerini karşılaştırdı. Diller ayrı ayrı ve gruplar arasında karşılaştırıldı. Perl, Python, Rexx ve Tcl gibi komut dosyası dilleri, derlenmekten daha sık yorumlanır (en azından program geliştirme sırasında) ve genellikle değişken tanımları gerektirmez.

Daha geleneksel programlama dilleri - C, C ++ ve Java - yorumlanandan daha sık derlenir ve değişken türlerin bildirilmesini gerektirir. Java birçok kişi tarafından çok verimsiz olarak görüldüğünden, bazen C ve C ++ 'ı bir gruba, Java'yı başka bir gruba koyuyorum.

Grafikler ve istatistiksel yöntemler

Ana değerlendirme aracı olarak makale, Şekil 2'de gösterilen blok diyagramı kullanır. 1. Her satır, adı solda gösterilen verilerin bir alt kümesini temsil eder. Her küçük daire bir veri değerini temsil eder. Grafiğin geri kalanı, verilerin iki veya daha fazla alt kümesini görsel olarak karşılaştırmanıza yardımcı olur. Gölgeli kutu, ilk çeyreğin (% 25) ve üçüncü çeyreğin (% 75) üst sınırları arasında değerlerin orta yarısını içerir. Kutunun solundaki ve sağındaki bıyıklar sırasıyla alt ve üst% 10'u gösterir. Bloğun içindeki kalın nokta, ikinci çeyreğin üst sınırıdır (% 50). "M" sembolü ve etrafındaki kesik çizgi aritmetik ortalama artı / eksi standart hatayı gösterir.

Şekil: 1.Z1000 veri kümesiyle program çalışma süresi
Yaklaşık 21 dakika sonra üç program boşuna sonlandırıldı. "İyi ve kötü değerler" oranının yayılması Tcl için 1.5 ile C ++ için 27 arasında değişir. Eksenin logaritmik ölçeğine dikkat edin. Bu şeklin açıklamaları ayrıca Şek. 2-7. "Grafikler ve İstatistiksel Yöntemler" bölümünde daha ayrıntılı bir açıklama verilmiştir.

Gruptaki değerlerin aralığını ölçmek için, "kötü değerlerin iyi değerlere" oranı kullanıldı: verilerin üst ve alt yarılar arasında bölündüğünü ve "kötü ve iyi değerlerin" oranının, üst yarının ortalamasını alt yarının ortalamasına bölme oranı olduğunu hayal edin. ... Bir kutu grafiğinde ortalama, bloğun sağ kenarındaki değerin bloğun sol kenarındaki değere bölünmesiyle elde edilen değerdir. Değerlerdeki yayılmanın standart sapma ölçüsünün aksine, "iyi ve kötü değerlerin" oranı keskin aykırı değerleri etkili bir şekilde ortadan kaldırır.

En önemli sonuç doğrudan diyagramdan çıkarılabilir. Bununla birlikte, iki kez kontrol etmek için istatistiksel testler yapıldı. Ortalamaları karşılaştırmak için tek kuyruklu Mann-Whitney U testi (Wilcoxon sıra toplamı testi olarak da bilinir) kullanılır. Her testin sonucu, iki örnek arasında gözlemlenen farkın yalnızca rastgele olması ve gerçekte iki değer grubu arasında hiçbir fark olmaması veya zıt işarete sahip olma olasılığını karakterize eden bir değer olan p'dir. Genellikle p değerinin kendisi belirtilmez, ancak makale metninde "... büyüktür ...", 0 0.10 ise "önemli fark yoktur" şeklinde belirtilir.

Bazı durumlarda, güven aralıkları, ortalamalardaki farklılıklar veya araçların logaritmalarındaki farklılıklar için, yani araçların oranları için belirtilir. Açık güven seviyeleri, sonsuz bir üst sınırla seçilir. Güven aralıkları, birçok kaynakta ayrıntılı olarak açıklanan önyükleme yöntemiyle hesaplanır (örneğin bkz.).

Bu çalışmanın geçerliliğine ilişkin endişeler göz önüne alındığında, nicel istatistiksel bulgular yalnızca genel kalıpları gösterir ve kesin gerçekler olarak alınmamalıdır.

Sonuçlar

Programları değerlendirmek için üç farklı girdi dosyası kullanıldı: 1000 boş olmayan rasgele telefon numarası içeren z1000; m1000, 1000 rasgele rastgele telefon numarası içeren, bazıları boş olabilir; ve telefon numarası içermeyen ve yalnızca sözlük yükleme süresini ölçmeye yarayan z0.

Program yürütme süresi

Analize toplam yürütme süresini ölçerek başladım ve ardından başlatma ve arama adımlarını ayrı ayrı inceledim.

Veri kümesi z1000'i tamamlayın. Şek. 1, C ++, Java ve Rexx dışındaki tüm programların yürütme süresi 1 dakikadan azdır. Verileri karşılaştırarak, birkaç önemli sonuç çıkarılabilir.

  • Tcl programlarının ortalama yürütme süresi Java'dan ve hatta C ++ 'dan biraz daha uzundur.
  • Python ve Perl için ortalama yürütme süresi Rexx ve Tcl'den daha azdır.
  • Ortalama C ++ puanı yanıltıcı olabilir. Bitişik büyük ve küçük değerler arasındaki oldukça büyük farklılıklar nedeniyle, ortalama kararsızdır. Wilcoxon'un tüm veri setini hesaba katan kriteri, C ++ için ortalama sürenin, kural olarak, Java için ortalama süreden (p \u003d 0.18) daha az olduğunu doğrulamaktadır.
  • C için ortalama yürütme süresi Java, Rexx ve Tcl için olandan daha kısadır ve genellikle Perl ve Python için olandan daha kısadır.
  • Tcl ve Perl için çalışma zamanları - iki çok yavaş program haricinde - diğer dillerdeki programların çalışma zamanlarından daha kararlı olma eğilimindedir.

Sadece birkaç nokta ile oluşturulan C ve Rexx diyagramlarına çok fazla önem vermeyin. Regina yorumlayıcısı daha büyük karma tablolar kullanacak şekilde yeniden derlenirse, Rexx programlarının yürütme süresi yaklaşık dört kat azaltılabilir; bellek gereksinimleri önemsiz ölçüde artar. Dilleri yalnızca üç grupta birleştirirsek (biri C ve C ++, ikincisi Java, üçüncüsü komut dosyası dilleridir), o zaman C ve C ++ 'daki programlar Java'dan daha hızlı çalışır (p \u003d 0,074) ve kural olarak daha hızlıdır senaryolar (p \u003d 0.15).

Java programları ve komut dosyaları için ortalama yürütme süresi arasında önemli bir fark yoktur. Betiğin bir C veya C ++ programından 1.29 kat daha uzun - ve bir Java programını en az 1.22 kat daha uzun - çalıştırma şansı% 80'dir. “İyi ve kötü değerlerin” oranı betiklerde (4,1) Java (18) ve hatta C ve C ++ (35) için önemli ölçüde daha düşüktür.

Yalnızca başlatma aşaması, veri kümesi z0. Sonra sözlüğü okumak, ön işleme koymak ve kaydetmek için geçen süreyi ölçtüm. Karşılık gelen zamanlar Şekil 2'de gösterilmiştir. 2. Sonuçlar açıkça göstermektedir ki, C ve C ++ bu aşamayı diğer test edilen dillerden daha hızlı gerçekleştirmektedir. Bir kez daha, en hızlı komut dosyası dilleri Perl ve Python'dur. Büyütülmüş grupları karşılaştırırken ortaya çıktığı üzere (% 80 olasılıkla), bir Java programı C ve C ++ programlarından en az 1.3 kat daha uzun çalışacak ve komut dosyası en az 5.5 kat sürecektir. daha fazla zaman. Komut dosyası, Java programından en az 3.2 kat daha uzun süre çalışacaktır.

Şekil: 2.Programın yalnızca sözlüğü yüklemek ve ön işlemden geçirmek için harcadığı süre (veri kümesi z0). Eksenin logaritmik ölçeğine dikkat edin. İyi / kötü oranlar Tcl için 1.3 ile Python için 7.5 arasında değişir

Yalnızca arama aşaması. Son olarak, programın yalnızca arama aşamasının zamanını elde etmek için yükleme aşaması süresini (veri kümesi z0) toplam yürütme süresinden (veri kümesi z1000) çıkardım. İncirde. Şekil 3, aşağıdaki sonuçların çıkarılabileceği karşılık gelen zamanları göstermektedir.

  • Rexx ve Tcl dışındaki tüm dillerde çok hızlı programlar yazılır ve tüm dillerde çok yavaş programlar bulunur.
  • Tcl programları için ortalama yürütme süresi Python, Perl ve C için olandan daha uzun, ancak Rexx'ten daha azdır.
  • Python programları için ortalama yürütme süresi Rexx ve Tcl sürelerinden daha azdır ve genellikle Java için yürütme süresinden daha kısadır (p \u003d 0.13).
  • Perl programları için ortalama yürütme süresi Rexx, Tcl ve Java ortalamasından daha azdır.
  • C ++ ortalama süresi, diğer dillerin sonuçlarından önemli ölçüde farklıdır.

Şekil: 3.Program tarafından yalnızca aramada harcanan süre, z1000 veri kümesi ve z0 veri kümesi için harcanan süre arasındaki fark olarak hesaplanır. Eksenin logaritmik ölçeğine dikkat edin. "İyi ve kötü değerlerin" oranı Perl için 2,9 ile C ++ için 50 arasında değişir

Büyütülmüş grupların karşılaştırılması, hiçbir grup arasında büyük bir fark olmadığını göstermektedir. Bununla birlikte, komut dosyası yürütme sürelerinin dağılımının Java'nınkinden en az 2,1 kat ve C ve C ++ 'dan en az 3,4 kat daha az olduğu% 80 olasılıkla tartışılabilir.

Bellek gereksinimleri

İncirde. Şekil 4, z1000 girdi dosyası işlemesinin sonundaki işlemin toplam boyutunu gösterir. Bundan birkaç sonuç çıkarılabilir.

  • Açıkçası, bellek en verimli şekilde C ve C ++ gruplarının programlarında ve en az verimli şekilde Java grubunun programlarında kullanılır.
  • Tcl dışında, birkaç komut dosyası, C ve C ++ programlarının en kötü yarısından daha fazla bellek tüketir.
  • Tcl betikleri diğer betiklerden daha fazla bellek gerektirir.
  • Python ve Perl programları için bellek gereksinimlerinin göreceli dağılımı, kural olarak, C programlarından ve özellikle C ++ 'dan daha azdır.
  • Bazı komut dosyaları geniş bellek alanlarını kaplar.
  • Büyük grupları karşılaştırırken, ortalama olarak Java programlarının C ve C ++ programlarından en az 32 MB daha fazla bellek (% 297) ve en az 20 MB daha fazla (98 %) komut dosyalarından daha fazla. Komut dosyaları, C ve C ++ programlarından en az 9 MB daha fazla bellek (% 85) alır.

Şekil: 4.Yorumlayıcı veya yürütme sistemini, programın kendisini ve tüm statik ve dinamik veri yapılarını barındırmak dahil olmak üzere programın gerektirdiği bellek miktarı. "Kötü ve iyi değerlerin" oranı Python için 1.2 ile C ++ için 4.9 arasında değişir

Bu verilerden, Java'nın bellek gereksinimlerinin genellikle betik gereksinimlerinin iki katı olduğu ve betiklerin, zayıf bir C veya C ++ programından daha iyi performans gösterememelerine rağmen, C ve C ++ ile yazılmış programlardan daha az bellek verimli olmadığı sonucuna varabiliriz. ...

Geleneksel bilgelik, algoritmik programların yürütme süresi ile bellek kullanımı arasında bir değiş tokuşa sahip olduğunu belirtir: yürütme hızını artırmak için genellikle programa daha fazla alan ayırmanız gerekir. İncelediğimiz program kümesinde, bu kural komut dosyası olmayan üç dil için de geçerlidir, ancak tersi kural betik dilleri için daha doğrudur: Daha fazla bellek kullanan betikler, daha az bellek alan betiklerden daha yavaş çalışma eğilimindedir.

Program uzunluğu ve yorum sayısı

İncirde. 5, her programın kaynak dosyasındaki, programın anlamsal bilgilerini içeren satır sayısını gösterir: ifadeler, tanımlar veya en azından sınırlayıcılar, örneğin kapama küme ayracı. Komut dosyası olmayan dosyalar genellikle komut dosyalarının iki veya üç katı uzunluğundadır. En uzun komut dosyaları bile komut dosyası yazılmamış ortalama kaynak koddan daha kısadır. Aynı zamanda, komut dosyalarındaki yorum yoğunluğu çok daha yüksektir (p \u003d 0,020): komut dosyası olmayan programlarda, ortalama olarak, operatörlerin bulunduğu satırlara göre yorum içeren satır sayısı% 22 daha fazladır; senaryolar için bu rakam% 34'tür.

Şekil: beş. Program uzunluğu: yorum içermeyen kaynak metnin satır sayısı. İyi / kötü oranları C için 1.3 ile Java için 2.1 arasında ve Rexx için 3.7 arasında değişir

Programların güvenilirliği

Giriş dosyası z1000 ile çalışırken, biri C, biri C ++ ve diğeri Perl'de olmak üzere üç program, büyük bir sözlüğü yükleyemedikleri veya yükleme aşamasının tamamlanması için ayrılan sürenin dolması nedeniyle doğru sonuçlar üretmedi. İki Java programı neredeyse sıfır güvenilirliğe sahipti ve başka nedenlerle başarısız oldu; ve bir Rexx programı yanlış, yalnızca biçimlendirme komut dosyası kullanarak birçok sonuç üretti - güvenilirliği% 45'ti.

Açıkça hatalı olan bu programları - dolayısıyla, C ve C ++ programlarının% 13'ü, Java programlarının% 8'i ve komut dosyalarının% 5'i hariç tutuldu - ve geri kalanını dil gruplarına göre karşılaştırdığımızda, C ve C ++ programlarının daha az olduğunu gördük Java ve komut dosyasından daha güvenilir. Ancak, bu farklılıklara yalnızca kusurlu birkaç program neden olmuştur ve bu nedenle genel sonuçlar için bir temel oluşturamaz.

Bununla birlikte, bu farklılıkların, dikkate alınmayan tamamen çalışmayan programların oranıyla aynı yasalara uyduğu göz önüne alındığında, dil grupları arasındaki güvenilirlik farklılıklarının gerçek olduğu sonucuna varılabilir. Komut dosyası oluşturma, "Karşılaştırma Geçerliliği" kenar çubuğunda açıklandığı gibi, programcılar için daha kapsamlı test verilerinin kullanılabilirliğinden yararlanabilir.

Ardından, numarasız telefon numaralarını, yalnızca tire ve eğik çizgileri içerebilen bir m1000 giriş dosyasıyla çalışırken davranışı karşılaştırdım. Bu tür telefon numaraları boş girişlere dönüştürülmelidir, ancak programcılar bir görevi okurken bu tür gereksinimleri unuturlar. Bu nedenle, programın Q faktörü m1000 dosyasında kontrol edilir. Çoğu program bu durumu başarıyla ele aldı, ancak Java programlarının yarısı ve dört komut dosyası - biri Tcl ve üçü Python'da - sonuçların% 10'u döndürüldükten sonra ilk boş telefon numarasına takıldı. Genellikle başarısızlık, yanlış bir satır veya dizi indeksinden kaynaklanıyordu. Diğer programların yanı sıra, 15 - biri C, beşi C ++, dört Java, iki Perl, iki Python ve bir Rexx - boş telefon numaralarını işleyemedi, ancak aksi takdirde doğru çalıştı; güvenilirlikleri% 98.4 idi.

Genel olarak, komut dosyalarının güvenilirliği, komut dosyası olmayan programların güvenilirliğinden daha düşük görünmemektedir.

Çalışma saatleri ve işgücü verimliliği

İncirde. Şekil 6, komut dosyası yazarları tarafından bildirilen ve komut dosyası olmayan programcılar için ölçülen bir programı tasarlamak, yazmak ve test etmek için harcanan toplam süreyi gösterir.

Şekil: 6.Program uygulamasına harcanan toplam süre
Senaryo grubunun programcıları çalışma süresini ölçtüler ve rapor ettiler: “senaryo dışı” grubun dillerinin zamanı deneyci tarafından ölçüldü. Kötü / iyi oranı C için 1.5 ile Perl için 3.2 arasında değişir. Java için üç değer - 40, 49 ve 63 saatlik çalışma - diyagramın dışındadır ve bu nedenle gösterilmez.

Ortalama 3,1 saatlik komut dosyası yazma sürelerinin, toplam medyanı 10,0 saat olan komut dosyası içermeyen programların yarısından daha fazla olduğunu bulduk, ancak deneyin tam olmayan güvenilirliği nedeniyle fark muhtemelen abartılıyor.

Neyse ki, iki faktör aynı anda kontrol edilebilir, yani programlamaya harcanan zamanın raporlanmasının doğruluğu ve programcıların senaryo ve senaryo dışı gruplardaki becerilerinin eşitliği. Bu faktörlerin her ikisi de, eğer gerçekten bir rol oynarlarsa, komut dosyası grubu çalışma süresinde bir azalmaya katkıda bulunmalıdır: Öznel mesajların abartılı değil, azaltılmış program çalışma süresi içereceğini varsayıyorum ve farklılıklar olması durumunda, komut dosyası grubunda daha nitelikli programcılar bulmayı umuyoruz. çünkü çalışma yapıldığında 1997 ve 1998'de Java programcıları diğer dillere göre daha az deneyimliydi. Bu test, bir programcının saat başına çıkardığı kaynak kod satırlarının sayısının programlama dilinden bağımsız olduğu şeklindeki eski bir genel kurala dayanmaktadır. Barry Boehm’in Cocomo ve Kuipers Jones fonksiyon noktalarını tahmin etmek için programlama dili tabloları dahil olmak üzere yaygın olarak kullanılan birkaç emek tahmin yöntemi, kaynak metnin saatlik sayısının programlama dilinden bağımsız olduğunu açıkça varsayar. İncirde. Şekil 7, bu kurala dayalı çalışma süresi tahminlerini gösterir. Java için güvenilir bir şekilde bilinen performans aralığına dayanarak, Tcl için en iyi üç zaman ve Perl için en iyi zamanlar hariç tümü makul görünüyor.

Şekil: 7.Tam bir saat içinde yazılan kaynak kod satırlarının sayısı. İyi / kötü oranı C için 1.4 ile Tcl için 3.1 arasında değişir

Java C, Perl, Python ve Tcl'den (0,07) farklı olmasına rağmen, medyan farklılıkların hiçbiri istatistiksel olarak açıkça anlamlı değildir.

Bu karşılaştırma, işgücü maliyetlerine ilişkin karşılaştırmalı çalışmamıza ek güvenilirlik katmaktadır. Senaryo programcıları tarafından bildirilen zamanlar yalnızca biraz hafife alınmış veya doğru görünüyor. Böylece, çalışma süresi maliyetinde betik dillerinin iki kat avantajı doğrulanmış olur. Java ile çalışmak için harcanan zaman abartılı görünüyor çünkü Java programcıları çalışma sırasında diğer programcılardan daha az deneyimliydi.

Program yapısı

İncelenen farklı dillerle çalışan programcılar tarafından seçilen yöntemler dikkate alındığında çarpıcı farklılıklar bulunmaktadır. Komut dosyası grubundaki programcıların çoğu, dillerde uygulanan ilişkilendirilebilir dizileri kullandı ve sözlük kelimelerini sayısal kodlarla daha sonra okumak için sakladı. Arama algoritması, mevcut telefon numarasının geri kalanına bağlı olarak anahtar olarak artan önekleri kullanarak diziden veri çıkarmaya çalışır. Her maç, daha sonra işlenecek olan yeni bir kısmi çözüm sunar.

Buna karşılık, neredeyse tüm komut dosyası olmayan programcılar aşağıdaki çözümlerden birini seçtiler: En basit durumda, sözlüğün tamamını bir dizide, genellikle hem orijinal sembolik formda hem de karşılık gelen sayı gösteriminde depoladılar. Daha sonra, arama alanını azaltmak için anahtar olarak yalnızca ilk rakamı kullanarak, şifrelenmiş telefon numarasının her hanesi için tüm sözlüğün onda birini seçip kontrol ettiler. Bu prosedür, basit ama etkisiz bir çözüme götürür.

Daha karmaşık bir yaklaşım, her bir düğümü belirli bir rakamı temsil eden ve n yüksekliğindeki düğümler, kelimenin n'inci karakterini temsil eden 10-ary ağaç kullanmaktır. Kökten verilen düğüme giden yol, kelimenin sayısal bir şifresini temsil ediyorsa, bir kelime bir düğümde saklanır. Bu en verimli çözümdür, ancak ağacı inşa etmek ve geçmek için nispeten çok sayıda operatör gerekir. Java'da, her bir nesneyi mevcut Java çalışma zamanı uygulamalarında depolamak için son derece büyük alanlar ayırma ihtiyacı nedeniyle ortaya çıkan çok sayıda nesne, bellek yoğun olarak kullanılır.

Komut dosyaları, komut dosyası olmayan programlardan daha az operatör içerir, çünkü arama işlemlerinin çoğu dahili ilişkilendirilebilir dizi karma algoritmaları kullanılarak gerçekleştirilir. Bunun aksine, komut dosyası olmayan programlarda, arama işleminin temel adımlarını açıkça belirlemeniz gerekir. Bu farklılıklar, veri yapıları oluşturma ve değişkenleri açıklama çabası veya eksikliği ile daha da şiddetlenir.

Hem Java hem de C ++ için sınıf kitaplıklarında karma tablolar uygulanmasına rağmen, komut dosyası olmayan dillerle çalışan programcıların hiçbiri bunları kullanmadı ve ağacı elle oluşturmayı tercih etti. Tersine, komut dosyası yazarları kendi dillerinde yerleşik karma tabloları kolayca kullanır.

Önemli bulgular

Telefon numarası kodlama programının yedi farklı dilde 80 uygulamasının karşılaştırmalı analizi aşağıdaki önemli sonuçları getirdi.

  • Perl, Python, Rexx ve Tcl'de program tasarlamak ve yazmak, C, C ++ ve Java'da programlama için gereken sürenin yarısından azını alır - ve kaynak metnin uzunluğu yarıdır.
  • Farklı dil gruplarının programları arasında güvenilirlikte net bir fark bulunmadı.
  • Tipik bir senaryo, bir C veya C ++ programına göre yaklaşık iki kat daha fazla bellek alır. Java programları, C ve C ++ programlarından üç ila dört kat daha fazla bellek kaplar.
  • C ve C ++ programları, 1 MB'lık bir sözlük dosyasını okumak ve Java programlarından üç veya dört kat daha hızlı ve yaklaşık beş veya on adet olmak üzere 70 KB dahili veri yapısı oluşturmayı içeren telefon numarası dönüştürme programını başlatır. komut dosyalarından kat daha hızlı.
  • Telefon numaralarını dönüştürme programının ana aşamasında, dahili veri yapısında bir arama yapılır ve C ve C ++ 'daki programlar Java'nın yalnızca iki katı kadar hızlı çalışır. Komut dosyaları Java programlarından daha hızlı çalışma eğilimindedir.
  • Komut dosyası dilleri arasında Perl ve Python, her iki adımı Tcl'den daha hızlı gerçekleştirdi.
  • Aynı dilde çalışan programcılar arasındaki farklılıklar nedeniyle araştırılan program parametrelerinin dağılımı - "iyi ve kötü" değerlerin ilişkisi ile yansıtılır - ortalama olarak, dillerdeki farklılıklardan kaynaklanan özelliklerde aynı veya daha fazla varyasyon.

Çok sayıda uygulama ve çok çeşitli programcılar göz önüne alındığında, bu çalışmanın sonuçları, onlara karşı eleştirel bir tavırla, güvenilirliği azaltan belirtilen faktörlere rağmen muhtemelen oldukça güvenilirdir. Ancak, sonuçlar yalnızca telefon numarası çeviri problemi için doğru kabul edilmelidir; farklı uygulamalara genelleme yapmak riskli olacaktır. Örneğin, komut dosyası dilleri grubunun göreceli sonuçlarının, diğer problemleri çözerken tam olarak doğrulanacağı şüphelidir.

Bu dezavantajlara rağmen, farklı programlama dilleri arasında doğrudan karşılaştırmalar yararlı bilgiler sağlayabilir. Örneğin, Java'nın bellek yükünün C ve C ++ ile karşılaştırıldığında hala çok büyük olduğu sonucuna varabiliriz, ancak programların yürütme süresi oldukça kabul edilebilir hale geldi. Komut dosyası dilleri, kapsamlı hesaplama ve büyük miktarda veriyi işlemeyi içeren görevler için bile C ve C ++ için mantıklı bir alternatif haline geldi. Göreceli yürütme süreleri ve bellek gereksinimleri genellikle kabul edilebilirdir ve bunlarda programlama, en azından küçük programlar için çok daha hızlıdır.

Bu makalede anlatılanlar gibi ek, daha geniş araştırmalara ihtiyaç olduğuna inanıyorum. Her dilin avantajlarını, dezavantajlarını ve özelliklerini bulmak için reklam tedarikçilerinin sisini ve uzmanların önyargılarını sona erdirmek için bu tür çalışmalar gereklidir. Bu tür bilgiler, programlama endüstrisini yeni bir seviyeye yükseltmeye yardımcı olacaktır.

Lutz Prehelt([email protected]) - abaXX Technology'de (Stuttgart, Almanya) kalite kontrol başkanı.

Edebiyat

1. E. Bradley ve R. Tibishirani, "An Introduction to the Bootstrap," Monographs on Statistics and Applied Probability 57, Chapman and Hall, New York, 1993
2. L. Prechelt, Arama / Dizgi İşleme Programı için C, C ++, Java, Perl, Python, Rexx ve Tcl'nin Ampirik Bir Karşılaştırması, Tech Report 2000-5, Fakultat fur Informattik, Universitat Karlsruhe, Almanya, Mart. 2000.
3. B.W. Boehm, Yazılım Mühendisliği Ekonomisi, Prentice Hall, Englewood Cliffs, N.J., 1981
4. C. Jones, Yazılım Verimliliği Araştırması , Programlama Dilleri Tablosu, Sürüm 7, 1996.

Yedi Programlama Dilinin Ampirik Bir Karşılaştırması, Lutz Prechelt, IEEE Computer, Ekim 2000, s. 23-29. Telif hakkı IEEE CS, izin alınarak yeniden basılmıştır. Her hakkı saklıdır.

Karşılaştırma güvenilirliği

Örnek programların karşılaştırılmasına dayalı programlama dillerinin herhangi bir karşılaştırması, yalnızca bu dillerle çalışan programcıların yeteneklerinin aynı kabul edilebildiği ölçüde geçerlidir. Bizim durumumuzda, bireysel nitelikleri değil, yalnızca programların genel seviyesi karşılaştırılabilir olmalıydı. Bu çalışmada analiz edilen 80 programın karşılaştırılabilirliğini çeşitli faktörler olumsuz etkilemiş olabilir.

Programlar iki farklı kaynaktan gelmektedir. Java, C ve C ++ programları 1997 ve 1998 yıllarında Bilgisayar Bilimleri Fakültesi son sınıf öğrencilerinin (L. Prechelt ve B. Unger, PSP Kırpmanın Etkileri Üzerine Kontrollü Bir Deney: Ayrıntılı Açıklama ve Değerlendirme, Teknik Rapor 1/1999, Fakultat fur Informattik, Universitat Karlsruhe, Almanya, Mart. 1999). Perl, Python, Rexx ve Tcl programları, çeşitli konferanslarda yayınlanan davetlere yanıt veren gönüllüler tarafından çeşitli koşullar altında yazılmıştır. Bu nedenle, yazarların farklı eğitim ve deneyimleri vardı.

Programcıların nitelikleri

Halka açık bir işbirliği çağrısının yalnızca yüksek yetkinliğe sahip programcıları çekmesi muhtemeldir, bu nedenle komut dosyası programları genellikle komut dosyası olmayan dillerdeki programlardan daha kalifiye uzmanlar tarafından yazılmıştır. Ancak iki durum, bu çelişkinin araştırma sonuçlarında ciddi hatalara yol açmadığını göstermektedir. Birincisi, birkaç istisna dışında, senaryo dışı programlar yazan öğrenciler oldukça deneyimli ve beceriklidirler. İkinci olarak, senaryo yazarlarının önemli bir kısmı, ilgili dillerle çalışmaya yeni başladıklarını veya tam bir programlama geçmişine sahip olmadıklarını bildirdi. Bunların arasında ultra büyük ölçekli bir mikro devre tasarımcısı, bir sistem yöneticisi ve bir sosyolog vardı.

Komut dosyası olmayan grupta, Java programcıları kendi dilleriyle ilgili C ve C ++ programcılarından daha az deneyime sahipti çünkü Java 1997 ve 1998'de hala yeni bir dildi. Senaryo grubunda, Perl programcıları deneydeki diğer katılımcılardan daha nitelikli idi; Perl, özellikle yetenekli programcıların ilgisini çekiyor gibi görünüyor - en azından bu benim kişisel izlenimim.

Çalışma zamanı ölçüm doğruluğu

Komut dosyası olmayan dillerle kontrollü bir deneyde programlama zamanını kesin olarak biliyoruz, ancak hiçbir şey senaryo yazarlarının program yazmak için harcadıkları zamanı küçümsemelerini engellemedi. Daha da kötüsü, bazı yazarlar, yazılım gereksinimlerine aşina olduktan günler sonra işe koyuldu. Bir programcı, "... şu anda bilinçaltında bir çözüm üzerinde çalışıyor olabilirdim" duyurusunu okuduktan iki hafta sonra programı yazmaya başladığını bildirdi.

Bununla birlikte, uygulama, ortalama olarak komut dosyası yazma sürelerinin de doğru olduğunu göstermektedir: tüm diller için veriler, "bir saatte yazılan kaynak metin satırlarının sayısının dile bağlı olmadığı" bilinen mühendislik gerçeğiyle oldukça tutarlıdır. Memnuniyetimiz için, aynı veriler komut dosyası yazarlarının niteliklerinin başka bir gruptaki programcılardan daha yüksek olmadığını doğrulamaktadır.

Görev ve çalışma koşulları farkı

Komut dosyası olmayan grup için temel gereksinim, programın doğruluğu idi; kabul kontrolü, yüksek güvenilirlik ve en azından bir dereceye kadar verimlilik anlamına geliyordu.

Doğruluk ana kriterinin yanı sıra, senaryo grubuna sekiz ek kalite gerekliliği getirildi. Komut dosyası olmayan bir gruptan kontrol almak yerine, komut dosyası yazarlarına kendi testleri için z1000 giriş ve çıkışları verildi. Her iki durumda da, farklılıklar senaryo grubuna avantaj sağlayabilir.

sonuçlar

Genel olarak, önceden veri toplama yöntemi, senaryo grubuna mütevazı da olsa bir dizi önemli avantaj sağlar. Herhangi iki dilde çalışan programcıların ortalama beceri düzeyleri arasındaki farklılıklar da olasıdır. Bu faktörlerin sonuçların güvenilirliği üzerindeki olumsuz etkisini ortadan kaldırmak için, yanlış verilerden kaynaklanıyor olabileceğinden, diller arasındaki küçük farklılıkları ihmal ediyoruz. Ancak, büyük farkların önemli olması muhtemeldir.

Önceki bölümlerde, birkaç farklı programlama dilinde tamamen aynı bir uygulamanın gerçekleştirilmesi yapıldı. İlk olarak, gerçek projelerin geliştirilmesinde en sık kullanılan 10 dildeki uygulamalara baktık ve ardından - yeni veya daha egzotik dillerdeki veya sınırlı uygulama alanlarına sahip olan aynı uygulamalar. Bu karşılaştırmanın amacı, önyargılı bir bakış açısı olmadan, aynı tür kodun farklı dillerde yazıldığında nasıl dışarıdan göründüğünü görmekti.

Ancak, çok dilli uygulamaların performansına ilişkin kabaca karşılaştırmalı tahminler de yapabiliriz, bu ve incelemenin sonraki bölümü buna ayrılmıştır.

Not: Bu tür değerlendirmeler kalite ve hatta performans için bir kriter olarak hizmet edemez. İdeolojide farklılık gösteren diller, farklı problem sınıflarında tamamen farklı göreceli performansa sahip olacaktır. Bu nedenle, yalnızca belirli bir problem sınıfı için performans sıralarını karşılaştırmaktan bahsedebiliriz.

Not: Çeşitli dillerin sunulduğu sırada gizli anlam ve alt metin aramayın - bunlar, kronolojik olarak test edildikleri rasgele sırayla açıklanırlar.

Görev

Önceki bölümde gösterilen görev, performans karşılaştırması için uygun değildir. Bu nedenle, böyle bir karşılaştırma için farklı dillerde bir dizi benzer uygulamayı yeniden uygulamalıyız. En geniş aralıkta hesaplama işlemlerine yönelik integral ihtiyacını değiştirmenin mümkün olması için, hem uygulama hem de anlama açısından en basit olan, boyuttan çok yüksek bir büyüme derecesine sahip olan (örneğin, üstel) bir hesaplama problemi kullanmak istiyoruz.

Kaba tahminler için, Fibonacci sayılarının özyinelemeli hesaplama problemi oldukça uygundur. Bu işlev o kadar basittir ki, formülasyonu sadece C kodunun sunumunda gösterilecektir.

Not (titiz izleyiciler için): Fibonacci dizisinin 2 tanımı vardır: a). F 1 \u003d 0, F 2 \u003d 1, F N \u003d F N-1 + F N-2 ve b). F 1 \u003d 1, F 2 \u003d 1, F N \u003d F N-1 + F N-2. Bu dizilerin kaydırılmış 1 üye için, bu konuda mızrak kırmayın: herhangi bir şekli kullanabilirsiniz. 2.'yi kullanacağız.

Fibonacci sayılarının sırasını hesaplamak için etkili algoritmalar vardır (soldan sağa döngüsel). Kasıtlı olarak, yukarıda yazılan ifadelerle tamamen aynı biçimde, verimsiz bir özyinelemeli uygulama (sağdan sola) kullanacağız. Bu algoritmayla, problem sadece daha önce bahsedilen hesaplama karmaşıklığında yüksek derecede büyüme gereksinimini karşılar.

Başvuruların hazırlanması icra söz konusu diller arasında çok farklıdır: bir yerde yorumlayıcının girişine beslenen sadece kaynak koddur, diğer durumlarda ara bayt kodunda derleme veya çalıştırılabilir makine kodunda derleme gerekir. Gerekli olan tüm ara hazırlık aşamaları, tek bir Makefile'da birleştirilir.

Birçok dil aracı, yürütmeyi optimize etmenin bir yolunu varsayar ve sağlar (örneğin, derleyiciye gösterilen optimizasyon düzeyi). Yürütmeyi nasıl optimize edeceğimi bildiğim yerde, maksimum optimizasyon seviyesi kullanılacaktır.

Zamanlama komutlarını şu formun komutlarıyla çalıştırmaya başlayacağız:

# zaman güzel -19<команда_fibo> 30
  • komut, görevin önceliğinin (güzel -9) normalin üzerine çıkarılmasına izin vermek için kök olarak çalıştırılır ve sonuçların varyansını azaltır;
  • zamanlama, sistem komutu ile gerçekleştirilir zaman (zaman ölçümleri sürecine müdahale etmeyeceğiz);
  • parametre (30, Fibonacci sayısının sıra numarası) problemin boyutunu belirler, buna bağlı olarak hesaplamaların hacmi katlanarak büyür.

Her uygulama için bir başlatma gösterilir, ancak gerçekte, epeyce birçoğu yapılmıştır (seri halinde, 10 veya daha fazla) ve metinde gösterilen, ortalama, en kararlı seçenektir (zaman aralıklarını ölçerken, tekrarlanabilirlik her zaman bir sorundur). Serinin farklı çalıştırmaları için aynı önbelleğe alma koşullarını sağlamak için serideki 1. çalışmanın sonuçlarını kullanmıyoruz.

Yürütme sonuçları, kullanılan araçların (derleyici, yorumlayıcı) sürümüne bağlı olarak kökten değişebilir. Bu nedenle, yürütme özeti, kullanılan yazılımın sürümünü gösterecektir.

C dili

Liste 1. Görevin C dilinde uygulanması (fibo_c.c):
#Dahil etmek işaretsiz uzun fib (int n) (dönüş n< 2 ? 1: fib(n - 1) + fib(n - 2); } int main(int argc, char **argv) { unsigned num = atoi(argv[ 1 ]); printf("%ld\n", fib(num)); return 0; }

Verim:

$ gcc --version gcc (GCC) 4.8.2 20131212 (Red Hat 4.8.2-7) ... # time nice -19 ./fibo_c 30 1346269 real 0m0.013s user 0m0.010s sys 0m0.002s

C kodundan derlenen bir uygulamanın en hızlı olacağı varsayılabilir. Bu nedenle, bu sayıları karşılaştırma için temel değerler olarak kullanacağız.

C ++

Uygulama şöyle görünecek:

Liste 2. C ++ (fibo_c.cc) ile Uygulama:
#Dahil etmek #Dahil etmek ad alanı std kullanarak; işaretsiz uzun fib (int n) (dönüş n< 2 ? 1: fib(n - 1) + fib(n - 2); } int main(int argc, char **argv) { unsigned num = atoi(argv[ 1 ]); cout << fib(num) << endl; return 0; }

Bu tek koddan 2 uygulama oluşturulacak - GCC derlemesi ve Clang derlemesi:

$ g ++ -O3 fibo_cc.cc -o fibo_cc $ clang ++ fibo_cc.cc -o fibo_cl

GCC tarafından oluşturulmuş bir uygulamayı yürütmek:

# zaman güzel -19 ./fibo_cc 30 1346269 gerçek 0m0.014s kullanıcı 0m0.012s sys 0m0.002s

Burada zaman, beklenen istatistiksel hata içinde, gerçekleşme C durumuna kesinlikle eşittir.

Clang tarafından oluşturulmuş bir uygulamayı yürütmek:

$ clang ++ --version clang version 3.3 (etiketler / RELEASE_33 / final) Hedef: i386-redhat-linux-gnu Konu modeli: posix # time nice -19 ./fibo_cl 30 1346269 real 0m0.035s user 0m0.033s sys 0m0.001s

Burada çok daha kötü! Bu, GCC'den 2,7 kat daha yavaştır. Ancak bunun açıklaması, optimizasyon seçeneğinin (-O ...) Clang derleme komutunda hiç ayarlanmamış olması olabilir.

Java

Liste 3. Görevin Java'da uygulanması (fibo.java):
public class fibo (public static long fib (int n) (return n)< 2 ? 1: fib(n - 1) + fib(n - 2); } public static void main(String args) { int num = new Integer(args[ 0 ]).intValue(); System.out.println(fib(num)); } }

Uygulamanın derlenmesi OpenJDK uygulamasında yapılır:

$ java -version java version "1.7.0_51" OpenJDK Runtime Environment (fedora-2.4.5.1.fc20-i386 u51-b31) OpenJDK Server VM (build 24.51-b03, karma mod) $ javac fibo.java $ ls -l * .class -rw-r - r-- 1 olej olej 594 Şubat 15 16:09 fibo.class

Aynısını orijinal Oracle JDK ile yaparsanız, geçici sonuçlar değişebilir.

Verim:

# time nice -19 java fibo 30 1346269 gerçek 0m0.176s kullanıcı 0m0.136s sys 0m0.047s

JVM'nin Java bayt kodunu yürütmesi burada makine tarafından derlenen C kodundan 13,5 kat daha yavaştır.

Python

Benzer Python kodu:

Liste 4. Python uygulaması (fibo.py):
#! / usr / bin / python # - * - kodlama: utf-8 - * - sys def fib (n) içe aktar: eğer n< 2: return 1 else: return fib(n - 1) + fib(n - 2) n = int(sys.argv[ 1 ]) print("{}".format(fib(int(sys.argv[ 1 ]))))

Bu kod için (uyumlu sözdiziminde yazılmıştır), ayrıca 2 farklı yürütme yöntemi sunabiliriz:

  • Python sürüm 2: $ python --version Python 2.7.5 # time nice -19 python fibo.py 30 1346269 gerçek 0m1.109s kullanıcı 0m1.100s sys 0m0.005s
  • Python sürüm 3: $ python3 --version Python 3.3.2 # time nice -19 python3 fibo.py 30 1346269 gerçek 0m1.838s kullanıcı 0m1.823s sys 0m0.009s

Burada hemen gözünüze çarpan ilk şey: Python 2, Python 3'ten% 65 daha hızlıdır. Bu oldukça bekleniyor - bu, önemli ölçüde genişletilmiş sözdizimi için ödenmesi gereken doğal bir bedeldir. Bazı yayınlar, belirli problem sınıfları için 2 veya 3 kata kadar önemli ölçüde daha büyük bir fark göstermektedir.

Ancak yerel derlenmiş C koduyla karşılaştırıldığında, Python 2 100 (85) kata kadar kaybeder! Bu aynı zamanda yayınlardaki seslerle de tutarlıdır.

Yakut

Liste 5. Bir Ruby görevini uygulama (fibo.rb):
#! / usr / bin / ruby \u200b\u200b# kodlama: utf-8 def fib (n) return n< 2 ? 1: fib(n - 1) + fib(n - 2) end puts fib(ARGV[ 0 ].to_i)

Verim:

$ ruby \u200b\u200b--version ruby \u200b\u200b2.0.0p353 (2013-11-22 revizyon 43784) # time nice -19 ruby \u200b\u200bfibo.rb 30 1346269 real 0m0.566s user 0m0.554s sys 0m0.009s

Burada çalışma zamanı şaşırtıcı bir şekilde (nedeni açık değil), Python'dan neredeyse 2 kat (1.77) daha iyi ve yerel C kodundan yaklaşık 43 kat daha yavaştır.

Perl

Liste 6. Bir Perl görevinin uygulanması (fibo.pm):
#! / usr / bin / perl alt fib (benim $ n \u003d shift; $ n< 2 ? 1: fib($n - 1) + fib($n - 2) } $f = fib($ARGV[ 0 ]); print "$f\n";

Verim:

$ perl --version Bu, i386-linux-thread-multi ... için oluşturulmuş perl 5, sürüm 18, subversion 2 (v5.18.2) 'dir. # time nice -19 perl fibo.pm 30 1346269 real 0m2.335s user 0m2. 329s sys 0dak0.002s

Burada yerel C kodundaki kayıp 179 katın üzerindedir! Ancak bu oldukça doğal ve beklenen bir durum - Perl bir bilgi işlem dili değil ve amacı metin işlemedir.

JavaScript

Liste 7. JavaScript uygulaması (fibo.js dosyası):
#! / usr / bin / js -U var fib \u003d function (n) (// işlev değişmez değeri dönüş n< 2 ? 1: fib(n - 1) + fib(n - 2); } print(fib(arguments[ 0 ]))

Uygulama yürütme (sürüm açıklamasından başlayarak):

$ js -v JavaScript-C 1.8.5 2011-03-31 # time nice -19 js fibo.js 30 1346269 gerçek 0m0.689s kullanıcı 0m0.683s sys 0m0.005s

Bu sonuç şaşırtıcıydı: bunlar Ruby ile neredeyse aynı sayılar ve Python'dan 2 kat daha iyi. Burada gecikme, yerel C kodundan 53 kat daha fazladır.

PHP

Sorunun PHP eşdeğeri:

Liste 8. PHP uygulaması (fibo.php dosyası):
#! / usr / bin / php

Uygulama yürütme:

$ php --version PHP 5.5.9 (cli) (inşa: 11 Şubat 2014 08:25:04) Telif hakkı (c) 1997-2014 The PHP Group Zend Engine v2.5.0, Copyright (c) 1998-2014 Zend Technologies # zaman güzel -19 php fibo.php 30 1346269 gerçek 0m1.307s kullanıcı 0m1.292s sys 0m0.013s

Bu, C eşdeğeri uygulamadan 108 kat daha yavaştır.

Lua

Liste 9. Görevin Lua dilinde uygulanması (dosya fibo.lua):
#! / usr / bin / lua fib \u003d function (n) - işlev değişmezi if (n< 2) then return 1 else return fib(n - 1) + fib(n - 2) end end print(fib(arg[ 1 ] + 0))

Bunun gibi bir uygulama çalıştırmak (Lua sürümünü kontrol ederek):

$ lua Lua 5.2.2 Telif hakkı (C) 1994-2013 Lua.org, PUC-Rio\u003e # time nice -19 lua fibo.lua 30 1346269 gerçek 0m0.629s kullanıcı 0m0.624s sys 0m0.003s

Bunlar JavaScript ve Ruby ile aynı sonuçlardır.

bash

Bash işlevlerinin yalnızca sınırlar dahilinde çıkış kodu değerleri döndürebildiği, yani bizim açımızdan hesaplanmış değerleri döndürmedikleri göz önüne alındığında, bu tür hesaplamaları bash yorumlayıcısında düzenlemek mümkün müdür? Her şeyden önce, betiğin kendisi ise benzer hesaplamaları organize edebilirsiniz. tekrarlı kopyalarını ara. Bu sadece bu ve her şey:

Liste 10. Bash'de bir görevin uygulanması (dosya fido.sh):
#! / bin / bash eğer ["$ 1" -lt "2"] ise "1" yankılandı yoksa f1 \u003d $ ($ 0 "expr $ 1 - 1") f2 \u003d $ ($ 0 "expr $ 1 - 2") echo ʻexpr $ f1 + $ f2` fi

30 numaralı argümanla böyle bir çözümü çağırmaya cesaret edemem (diğer seçenekler gibi) - çözümü bekleyemem ... Ama böyle bir komut dosyası oldukça başarılı bir şekilde yürütülüyor:

$ bash --version GNU bash, version 4.2.37 (1) -release (i486-pc-linux-gnu) ... # time nice -19 ./fibo.sh 10 89 real 0m1.137s user 0m0.350s sys 0m0. 475s # zaman güzel -19 ./fibo.sh 12 233 gerçek 0m2.979s kullanıcı 0m0.935s sys 0m1.248s # zaman güzel -19 ./fibo.sh 14610 gerçek 0m7.857s kullanıcı 0m2.528s sys 0m3.166s

Görünüşe göre, bash betiğinin işlevi 8'den hesapladığı, çok "aceleye getirilmemiş" Perl'in işlevi 29'dan hesaplaması gerektiği kadar hesaplıyor (bu üstel büyüme ile!):

# time nice -19 perl fibo.pm 29 832040 gerçek 0m1.464s kullanıcı 0m1.448s sys 0m0.004s

Bash'in gösterilen uygulamasının pratik bir anlamı yoktur, ancak böyle bir olasılığın kendisi ilginçtir. Bir başka olasılık, bir komut dosyası içinde bir işlevi çağırırken yapay olarak organize edilmiş özyineleme (kuyruk, dönüş yığını ile) olabilir:

Liste 11. bash içinde dahili özyineleme (fido_f.sh dosyası):
#! / bin / bash bildirmek -a res fib () (eğer ["$ 1" -lt 2] ise res [$ 1] \u003d 1. else. fib ʻexpr $ 1 - 1` s \u003d $ (res [ʻexpr $ 1 - 1`]) + $ (res [ʻexpr $ 1 - 2`]) res [$ 1] \u003d $ s fi) res [0] \u003d 1 fib $ 1 echo $ (res [$ 1])

İşte zaten tamamen farklı sonuçlar:

# zaman güzel -19 ./fibo_f.sh 30 1346269 gerçek 0m0.157s kullanıcı 0m0.037s sys 0m0.083s # zaman güzel -19 ./fibo_f.sh 60 2504730781961 gerçek 0m0.337s kullanıcı 0m0.075s sys 0m0.167s

N \u003d 60 için sonuç, yerel C kodunu çalıştırmanın sonuçlarını bile aşıyor. Ama burada sadece aldatmanın sonucunu gözlemliyoruz: Hesaplamalar sırasında, bir "optimizasyon" yapıldı ve aslında özyinelemeli hesaplama, 2 özyinelemeli çağrı oluşturmayan döngüsel bir hesaplamaya dönüştürüldü.

Programlama dillerinin karşılaştırılabileceği birçok parametre vardır. Platform olarak değil, tam olarak dil olarak. Popülerlik, geliştirme araçları, uygulama alanı, pazardaki konum - bu önemlidir, ancak dillerin kendilerine bakmak ilginçtir.
Ve paradigmaları umurumda değil: C ile OOP tarzında yazabilirsiniz (örneğin GTK +) ve Java'da monadlar yapabilirsiniz.
Ve hayatta nasıllar?

Hangi dilin daha popüler olduğunu bilmek istiyorsanız, o zaman KDPV'yi küstahça çaldığım en popüler programlama dilini ararken makalesini okumanızı şiddetle tavsiye ederim.

Dikkatinizi neredeyse öznel parametrelere çekmek isterim:

1. Bir dizi temel aksiyom.
Çince'ye benzeyen diller var - birçok hiyeroglif. Ve sadece 26 harfin olduğu İngilizce gibi, ancak onlardan kelimeleri ve cümlenin kelimelerinden birleştirebilirsiniz.
Açıktır ki, bu tür temel semboller ne kadar azsa öğrenmeye başlamak o kadar kolay olur. Ama daha çok metin çıkıyor, evet.
Öte yandan, harf kümesini 1 ve 0'a getirmek de anlamsız. Burada bir uzlaşma bulmanız gerekiyor. Ortalama olarak, tüm dillerin yaklaşık 15 operatörü ve en fazla on temel türü vardır.
Aksiyomatik güç hesaplanabilir ve katsayı görüntülenebilir. Hatta bir asır öncesinden dillerin gücü hakkında bazı karşılaştırmalar buldum.
Bu tamamen dürüst ve biraz bilimsel bir sorundur, tez için uygundur. Burada anakartta güzel grafikler bile çizebilir ve Wikipedia'dan anlamsız terimleri biriktirebilirsiniz. Cidden anlamak için en az bir yıl.
Ancak bunun yerine, tüm eleştirmenler, en iyi ihtimalle yeniden düzenleme veya REST hakkında bir tür çöp hakkında yazıyorlar. Ve bu arada, bir tez uzmanı için özellikle zor bir iş değil: bir ayıklama yöntemi veya bir HTTP isteği gönderin. İpucu yakalayın 😉

2. Okunabilirlik.
Programcılar çoğu zaman kod yazmaz, okur.
Kodu python ve pearl ile karşılaştırdığınızda okunabilirliğin ne olduğunu anlamaya başlıyorsunuz.
Böyle bir model var: daha yüksek seviyeli programlama dili, daha iyi okunabilirlik. SQL genellikle düz metin gibi okur.

3. Sözdizimsel şeker
Tekrarlayan ilkel şeyler için. Örneğin, Java'da dizeler nesnelerdir ve iyi bir nedenden ötürü, bir yöntem çağırarak bunları birleştirmeniz gerekir. Ancak insanların hayatını kolaylaştırmak için, + operatörü dizgi birleştirme gerçekleştirdiğinde özellikle sözdizimsel şeker eklendi.
Ancak artı, istisna olarak yalnızca dizeler için işe yarar: diğer tüm sınıflar operatörleri geçersiz kılamaz, böylece kodda sürpriz olmaz.
Ancak C ++, C #, Groovy ve diğer birçok dilde, operatörleri yeniden tanımlayabilirsiniz ve sonuç olarak, genellikle bunun kodda ne tür bir çöplük olduğunu merak edersiniz: kullanıcılar<< new User() пока не узнаёшь что добрые молодцы добавили сахару для добавления в список.
Genel olarak, burada yine, dillerde olduğu gibi - İngilizce'de katı bir dilbilgisi ve kelime sırası varsa, o zaman Rusça'da istediğiniz gibi yazın ve kelimeleri sentezleyin.
Sonuç olarak, yabancılar Rusça'yı anlayamıyor.

4. Bacaktan ateş etme yeteneği.
C ile ayaktan çekim yapmak en iyisidir: burada donuk bir NPE değil, gerçek bir Segmentasyon hatası çıkarırsınız. 1 / 3'ü bölersiniz ve 0 elde edersiniz. İf (x \u003d 3) yazarsınız ve kodun neden çalışmadığını merak edersiniz. Ve taşan arabellek korsanları aracılığıyla sunucuyu sizin için indirir.
C de, derleyicinin optimizasyon seçeneği nedeniyle programın çalışmayı durdurduğu şakalar da vardır.

5. Büyü.
Sihir, yaratıcılar tarafından orijinal olarak sağlanmayan her türlü numarayı yapmanızı sağlayan bir özelliktir.
Çoğu zaman sihir kullandığımızı düşünmüyoruz bile.
Örneğin, ön derleyici yönergeleri ve makroları - C ++ 'yı Albany'ye bile çevirebilirler:

#Dahil etmek #Dahil etmek # if! tanımlıysa (_MSC_VER) || _MSC_VER< 1400 #error Wrong compiler! Use MSVS 8.0 #endif #define НАЧЕЛ { #define КОНЧЕЛ;} #define ТИПА int #define ВДРУГ if (#define ТАДА) #define НИХРИНА else #define ВЗАД return #define КАГДИЛА (#define ЙО; #define ЖЖОШ(p,n) for (; (p) <= (n); (p)++) #define БАЗАР std::cout << #define СЛЫШЬ << #define СТОЙ system ("echo. & pause"); #define БЛИН _wsetlocale (LC_ALL, L"Russian_Russia.ACP"); #define ВРОДЕ try #define ИБАНУЦЦО throw #define АПСТЕНУ catch (const char* __чё__) #define ПРЕВЕД ТИПА main КАГДИЛА ТАДА #define МЕДВЕД ВЗАД 0; КОНЧЕЛ ТИПА КРУТО КАГДИЛА ТИПА фигня ТАДА НАЧЕЛ БАЗАР "ВАЩЕ " ЙО ВДРУГ фигня == 8 ТАДА ИБАНУЦЦО "мля! " ЙО ВЗАД 0 КОНЧЕЛ ПРЕВЕД НАЧЕЛ БЛИН ВРОДЕ НАЧЕЛ ТИПА фишка = 0 ЙО ЖЖОШ (фишка, 10) НАЧЕЛ БАЗАР фишка СЛЫШЬ " "; ВДРУГ фишка >\u003d 5 TADA SOĞUTMA (çip) CUM Cumshot APSTENU BAŞLADI PAZAR "IBANUZZO çağrıldı:" HEAR __chё__; CUM AYI AYI

Şimdi dilleri şu kriterlere göre karşılaştıralım:
Si
1. Minimum temel aksiyomlar kümesi: C'de her şey basittir: işte fonksiyonlar, işte yapılar, işte işaretçiler, saldırı! Torvalds gibi Tru sishniki, artı noktalara konumlayıcı olarak bakar.
2. Okunabilirlik: C'de düşük i ++, j—, for (;;) ama setin minimal olması çok yardımcı olur.
3. Sözdizimsel şeker: diziler için köşeli parantezler (bir işaretçi ile idare edebilirsiniz) ve dize değişmezleri.
4. Sadece bacaktan ateş edersiniz: tamponların ötesine geçersiniz, hafızayı temizlemeyi unutursunuz, bunun sonucunda gerçek bir Segmentasyon hatası yaşarsınız.
5. C'de sihir olmadan şaşırtıcı olmadığından, tek bir adım atamazsınız. C'deki sihir ön derleyici yönergeleridir. Her şey üzerlerinde yapılır: kapanımlar, sabitler, DSL'ler.

C ++
1. Nesneler zaten burada görünür, ancak onlarla birlikte, artıları geri kalanının önünde olan bir dizi ıslık ve sahte var. Genel olarak, artıların tüm programlama konseptleri için bir test alanı olduğu hissi vardır.
2. Neredeyse okunabilirlik yok. Bazı yerlerde, yalnızca C benzeri sözdizimi kaydeder.
3. Şeker yeterlidir: Hello World bile geçersiz kılınmış bir operatörle başlar<< для cout.
4. Makineli tüfekle bacağından ateş ediyoruz. Türün klasiği çoklu kalıtımdır.
5. Sihir, STL ve Boost şablonlarıyla gerçekleştirilir.

Java
1. Burada sadece C ++ aldık ve gereksiz her şeyi kaldırdık. Sonuç olarak, her şey basit: işte sınıf, işte yöntemler, bir nesne yaratıyorsunuz ve yöntemleri çekiyorsunuz, bir şeyler ters giderse, bir istisna atıyorsunuz, "sorun nedir?"
Ama yine de abarttık: iç içe sınıflar, statik yöntemler, ilkel tipler. OSCJP sertifikası için hazırlanmaya başladığınızda, aniden Java bilmediğinizi fark edersiniz.
2. C'den sonraki kalıntılara dikkat etmezseniz sözdizimi oldukça okunabilirdir. Aslında, lingva franca onu ders kitaplarında kullanmayı sevmelerinin nedenidir.
3. C'nin tüm şakalarını biliyorsanız, bacaktan çekim yapmak zaten oldukça zordur. Yetersiz bellek veya Null işaretçi istisnası mı? Java'da bir grup kurumsal yazılım yazılmasının nedeni budur.
4. Sihir, genel olarak programı etkilememesi gereken ek açıklamalar yardımıyla anlaşılır. Ama aslında, ek açıklamaların izlerini takip ederek, bayt kodunu tanınmayacak şekilde karıştırırlar.

Sea Sharp
1. Gerçeği aldık ve pazarlama amaçları için gerekli ve gereksiz her şeyi sürükledik. Yapılar sınıflardan nasıl farklıdır? Neden verim? Görünüşe göre çok sık kullanılmıyor.
3. Yine, operatörleri ve diğer hayvanat bahçesini C ++ 'dan geçersiz kılmak, ancak bir çöp toplayıcı ile.
2. Okunabilirlik normaldir. Delphi gibi bir şey (yaratıcı aynıdır).
4. Sihir için, her zaman LINQ gibi bütün teknolojileri geliştirirler.

Python
1. Kötü seçilmiş çok sayıda temel ilke.
2. Okunabilirlik iyidir - uzaktan Mayakovsky'nin şiirleriyle karıştırılabilir.
4. Sihir, her şeyi yapabilen sishnyh lib'leri kullanılarak elde edilir. Bu nedenle, guey'in yarısı Linux'ta python ile yazılmıştır.
Genel olarak, şahsen piton hakkında iyi bir şey söyleyemem - üzerine bir düzine senaryo yazdım ve her emişinde. Belki bir çeşit numarası vardır.

inci
2. Pearl, metin düzenleyicinin gelişim sürecinde çıktı. Ve açık ara en kötü salt yazılır sözdizimi. Normal ifadeler inciden geldi, bu çok şey söylüyor. Bence Brainfuck'ın yaratıcıları Perl'i biraz basitleştirdi.
4. Bir incinin büyüsü, belgedeki tüm metni tek satırda gösterebilmenizdir.

Yakut
Esasen nesne yönelimli bir İnci.
1. Sözdizimi o kadar şeker kaplıdır ki şeker hastalığına yakalanabilirsiniz.
2. Okunabilirlik inci gibidir, ancak tekdüzelik yardımcı olur - asıl önemli olan kavramı anlamaktır.
4. Büyü, dinamizm üzerinden meta programlama yoluyla elde edilir. Örneğin, var olmayan bir yöntemi çekerseniz, onu durdurabilir ve yine de yürütebilirsiniz. Örneğin, konuşmacı bulanlar bunu böyle yapıyor.
Ruby'de Java'da "bunu yapamazsın" kitaplarında yazılan her şey "bak, bunu bile yapabilirsin!" Yazmaktadır.

Ada
Ada, ABD Ordusu için bir yarışmanın parçası olarak yaratıldı. Şunlar. başlangıçta akademisyenlerden en havalı programlama dilini bulmalarını istedi. Bunun için savaştı ve kaçtı.
1. Temel set çok büyük. Scala'nın ortaya çıkmasından önce, en zengin programlama diliydi.
2. Aynı zamanda, mükemmel okunabilir pascal sözdizimi.
3. Şeker yeterlidir.
4. Neredeyse sihir yok - her şey zaten dilde. Buradan emin olmasam da Ada'da pek kod görmedim.

Ada'dan bir sebeple bahsetmiştim, eleştirisini okudu:

Hoare, "çıngırakların ve ıvır zıvırların temel güvenilirlik ve güvenlik gereksinimlerini aştığı" konusundaki üzüntüsünü dile getirdi ve "Ada'nın derleyicisindeki bir hatanın gözden kaçırılması nedeniyle yanlış yönde uçan bir füze ordusuna" karşı uyarıda bulundu. Niklaus Wirth daha ölçülü ama olumsuz da konuştu. “Programcıya çok fazla şey düşüyor. Ada'nın üçte birini inceledikten sonra normal çalışabileceğinizi sanmıyorum. Dilin tüm ayrıntılarına hakim olmazsanız, gelecekte bunlarla karşılaşabilirsiniz ve bu, hoş olmayan sonuçlara yol açar. " Ada'nın geliştirme ekibi lideri Jean Ishbia, Wirth'e olan "saygı ve hayranlığını" dile getirerek, ona karşı çıkarak, "Wirth karmaşık sorunlara basit çözümlere inanıyor. Ben böyle mucizelere inanmıyorum. Karmaşık sorunlar, karmaşık çözümler gerektirir. "

Kıçtaki cehennem ve Sishechka'da yazılan yazılımın bir sonucu olarak uzaya uçtuğunu söylemeye gerek yok mu?

Scala
Kaya, sağduyu pahasına Java'yı işlevsel hale getirme girişimidir.
Tıpkı Adu gibi, zaten endişe verici olması gereken "programlama dillerinin yaratılması için laboratuvarda" yapay olarak icat edildi.
Herhangi bir işlevselcilik gibi, "matematiksel zihniyete" sahip her zeki insanı orgazma getirir.
Normal mühendisler, Rock'ta bir projeyi nasıl sürdüreceklerini bulduklarında korkarlar. Scala Java'dan daha kötü. Java projelerinin en az yarısı için.

Bu, Andrey Platov'un bir programlama dili seçen makalesinde çok iyi açıklanmıştır:

Scala, Java'ya göre (ve ayrıca C-\u003e C ++) size büyük verimlilik kazançları sağlayacaktır. Bu, boşlukta tek yazarlı bir proje için geçerlidir. Dilin karmaşıklığı ve sınırsız olasılıkları, üretkenliğe kesinlikle katkıda bulunmayacak bir hemoroid tarafından yansıtılacaktır. Tek soru daha ne olacağı. Henüz bilmiyorum ve genel olarak dünyada henüz büyük bir Scala projesi yok.

Çıktı: Andrei Platov ile aynı sonuca vardım - şimdi programlama dillerini kırma sürecindeyiz ve aralarından seçim yapabileceğimiz hiçbir şey yok - mevcut tüm diller açıkça modası geçmiş durumda.
Tamamen yeni nesil programlama dillerine ihtiyaç vardır. Evet, öyle ki mevcut tüm diller delikli kartlara yazmak kadar aptalca görünüyor.
Ama bunun hakkında daha sonra konuşacağım.

Konuyla ilgili daha fazla bilgi

PS

Bu makalede, yalnızca bir teknoloji seçerken göz önünde bulundurulan ve bunların tam bir karşılaştırması değil, her zaman açık olmayan bazı özelliklere dikkat çekmek istiyorum.
Diğer her şey olması gerektiği yere zaten kopyalanmıştır

Tembel olmayın ve çok önemli birkaç madeni okuyun.
Ayrıca, sizler için diğer faydalı makalelerin bağlantılarını ve şirketlerdeki kurs ve staj duyurularını toplamaya çalıştığım IT Juniors grubuna katılmayı unutmayın.

Son zamanlarda, ikinci sınıf öğrencileriyle 2 dönemlik bir disiplin olan "Algoritmik diller" alanında bir kez daha çalıştım. Birkaç düzine programlama dilini inceledik. Öğrencilerden biri olan Vadim Shukalyuk onları daha yakından tanımak, her biri hakkında daha net bir fikir edinmek istedi. Küçük bir araştırma yapmasını tavsiye etti. Sonra ve götürüldü. Onunla birkaç aydır yapılan işlerle ilgili raporumu sunuyorum.

Her programlama dilinin kendine özgü avantajları ve dezavantajları vardır. Herhangi bir dilden bir çevirmenin en önemli özelliklerinden biri, program yürütme hızıdır. Bu uygulama hızının doğru bir tahminini yapmak çok zor hatta imkansızdır. Http://benchmarksgame.alioth.debian.org/ kaynağı, bu hızı farklı görevlerde test etmek için bir oyun formu sunar. Ancak bu kaynakta sunulan dillerin sayısı oldukça azdır. Yinelemeli hesaplamalar için kritik değer olan yığının maksimum kapasitesini kontrol etmek daha kolaydır, ancak çevirmenin farklı sürümlerinde değişebilir ve sistem ayarlarına bağlı olabilir.

Aşağıdaki çevirmenler test edildi: c (gcc, clang, icc), assembler (x86, x86-64), java (OpenJDK), pascal (fpc), javascript (Google Chrome, Mozilla Firefox), lisp (sbcl, clisp), erlang, haskell (ghc, hugs), dino, auk (gawk, mawk, busybox), lua, ruby, basic (gambas, libre office), python-2, pi-h-pi, postscript (gs), prologue (swipl, gprolog ), inci, metapost, T E X, tickl, besh. Hem birkaç küçük ama zaman alan algoritmanın gerçek yürütme hızını araştırdık hem de:

  • bazı çevirmenlerin optimizasyon kalitesi;
  • intel ve AMD işlemcilerle çalışırken karşılaşılan özellikler;
  • özyinelemeli çağrı sayısını sınırlayın (yığın kapasitesi).
Tüm çevirmenlerin test edildiği ilk görev olarak, Fibonacci sayısının çift özyineleme ile hesaplanması tanıma göre seçildi: 1 ve 2 numaralı sayılar birimlerdir ve sonraki olanlar önceki ikisinin toplamıdır. Bu algoritmanın birkaç çekici özelliği vardır:
  1. Eğer n'inci sayıyı hesaplama zamanı t ise, o zaman (n + 1) -th - t * φ, burada ((15 + 1) / 2'ye eşit altın orandır;
  2. Hesaplanan n-e sayısının kendisi, en yakın tam sayı değerine yuvarlanan φ n / √5'e eşittir;
  3. Fib (n + 1) hesaplamak için n'inci yuvalama çağrıları gerekir.
İlk özellik, çevirmenleri kısa sürede test etmenizi sağlar, hızları yüzbinlerce kez farklılık gösterir. İkinci özellik, hesaplamaların doğruluğunu hızlı bir şekilde kontrol etmenizi sağlar. Üçüncü özellik teorik olarak yığının kapasitesini incelemeye izin verir, ancak n\u003e 50 için hesaplamanın bir süper bilgisayarda bile çok yavaş olması nedeniyle, bu özelliği kullanmak pratik olarak imkansızdır.

Aşağıdaki tablo 1'de, ikinci sütun dilin adını, derleyicinin adını ve sürümünü ve kullanılıyorsa, üretilen kodu optimize etme seçeneğini içerir. Üçüncü sütun, AMD Phenom II x4 3,2 GHz işlemcinin göreceli hesaplama süresini gösterir. Testler AMD FX-6100 üzerinde aynı frekansta gerçekleştirildi, ancak sonuçları verilenlerden çok az farklı. Bash dilinde hesaplama süresi bir birim olarak alınır, bu nedenle Erlang'daki hesaplama Bash'den yaklaşık 20.000 kat daha hızlıdır. 4. sütun, Intel Core i3-2100 3.1 GHz işlemcideki göreceli işlem süresini gösterir. İşlemcilerin karşılaştırılması çalışmanın amacı olmadığından çevirmenlerden bazıları Intel platformunda test edilmedi. Beşincisinde, 8 GB RAM ve 8192 KB sistem yığın boyutu (ulimit -s) olan bir bilgisayarda ack (1,1, n) hesaplanırken çevirmen tarafından desteklenen maksimum yinelemeli çağrı sayısının üst sınırı (% 10 doğruluk). Bazı çevirmenler, kullanılan yığının boyutunu belirleyen kendi ayarlarını kullanır - seçilen çevirmen sürümü için varsayılan değerler her zaman kullanılır. Ölçümler bir Linux sisteminde yapılmıştır, ancak başka bir işletim sistemine geçerken sonuçlar değişmemelidir. Veriler 3. sütuna göre sıralanır. Tüm kaynaklar görüntülenebilir.

Tablo 1.

N Dil AMD Intel Yığın
1 C / C ++ (gcc 4.7.2, -O5) 354056 493533 790000
2 C / C ++ (clang 3.0-6.2, -O3) 307294 270000
3 C / C ++ (icc 14.0.3, -hızlı) 250563 232665 530000
4 Birleştirici x86-64 243083 271443 350000
5 Birleştirici x86 211514 301603 700000
6 Java (OpenJDK 1.7.0_25) 186401 239659 8000
7 Pascal (fpc 2.6.0, -O3) 170604 186401 180000
8 C / C ++ (gcc 4.7.2, -O0) 159672 173261 180000
9 C / C ++ (clang 3.0-6.2, -O0) 146726 110000
10 C / C ++ (icc 14.0.3, -O0) 136862 156602 530000
11 Javascript (Mozilla Firefox 25) 121979 4200
12 Javascript (Google Chrome 31) 92850 10000
13 Lisp (sbcl 1.0.57) 54925 51956 31000
14 Erlang (5.9.1) 19845 18589 limit yok
15 Haskell (ghc 7.4.1, -O) 18589 22946 260000
16 Awk (mawk 1.3.3) 6621 6306 44000
17 Lua (5.2) 6420 7075 150000
18 Yakut (1.9.3) 5297 6969 6600
19 Dino (0.55) 5024 6420 190000
20 Temel (Gambas 3.1.1) 3968 4373 26000
21 Python (2.7.3) 3678 4013 1000
22 PHP (5.4.4) 2822 3720 limit yok
23 Awk (gawk 4.0.1) 2648 2547 limit yok
24 Son komut dosyası (gs 9.05) 2355 3246 5000
25 Giriş (swipl 5.10.4) 1996 2407 2300000
26 Perl (5.14.2) 1516 1670 limit yok
27 Prolog (gprolog 1.3.0) 1116 1320 120000
28 Lisp (clisp 2.49) 998 1023 5500
29 Awk (meşgul kutusu 1.20.2) 981 1113 18000
30 T E X (3,1415926) 239 333 3400
31 Metapost (1.504) 235 470 <4100
32 Tcl (8,5) 110 123 1000
33 Haskell (98.200609.21'e sarılır) 82 121 17000
34 Temel (LibreOffice 3.5.4.2) 20 35 6500
35 bash (4.2.37) 1 0,77 600

İkinci problem olarak, tüm aritmetik işlemler ona indirgendiğinde Ackerman fonksiyonunu seçtik, yani, ack (1, x, y) \u003d x + y, ack (2, x, y) \u003d x * y, ack ( 3, x, y) \u003d xy, ack (4, x, y) - x ve y'nin tetrasyonu, vb.

Bu işlev, n arttıkça çok hızlı büyür (ack sayısı (5,5,5) o kadar büyüktür ki, bu sayı sırasındaki basamak sayısı, Evrenin gözlemlenebilir kısmındaki atom sayısından kat kat fazladır), ancak çok yavaş kabul edilir. İkinci özellik teorik olarak performansı test etmek için uygundur. Bununla birlikte, bu işlevin hesaplanması, önemli sayıda yinelemeli çağrı gerektirir ve test edilen dillerin çoğu, fark edilebilir bir süreye sahip hesaplamalar için bunları destekleyemedi. Bu fonksiyonun hesaplanmasının yinelemeye indirgenemeyeceği bilinmektedir. Bu problemin hesaplanması, incelenen dillerin yığınının maksimum kapasitesini araştırmamızı sağladı: ack (1,1, n-1) hesaplaması çağrıların n'inci yuvalanmasını gerektirir ve çok hızlıdır. Aşağıdaki tablo 2, yığını buna dayanabilen diller için (65539 çağrılarının iç içe geçmesi) pentasyon kodunun (5,2,3) hesaplanmasının sonuçlarını göstermektedir. Hız birimi, gcc'nin -O5 seçeneği ile çalışma süresidir, yani php yaklaşık 420 kat daha yavaştır.

Tablo 2.

gcc -O5 1
asm x86 2.15
icc -hızlı 2.18
asm x86-64 2.36
clang -O3 2.76
fpc -O3 4.44
gcc -O0 7.75
icc -O0 8.36
clang -O0 9.64
Erlang 18.51
ghc -O 50.18
lua 122.55
php 423.64
gawk 433.82
swipl 766.55
dino 915.64

Yukarıdaki iki problemi kullanma fikri BV Kernighan ve R. Pike'ın "Unix - evrensel bir programlama ortamı" çalışmasından ödünç alındı, hoc dilini test etmek için kullanıldı.

Tabii ki, daha karmaşık hesaplamalar için, esas olarak standart kitaplıkların araçlarını kullanarak, çevirmenlerin hızındaki fark çok daha küçük olacaktır.

Zaman, standart zaman komutuyla ölçüldü ve imkansız olduğunda (javascript, ofis BASIC), dilde yerleşik araçlar kullanıldı.

Çalışmanın sonuçlarına dayanarak, bazıları biraz beklenmedik olan aşağıdaki sonuçlar çıkarıldı:

  1. Assembly dili programlarının hızı, maksimum optimizasyonlarla derlenen C / C ++ programlarından% 50 daha yavaş olabilir;
  2. Bayt kodlu bir sanal Java makinesinin hızı, yüksek seviyeli dillerden çevirmenler tarafından alınan kodlarla donanımın hızını genellikle aşar. Java makinesi, hız açısından yalnızca assembler'dan sonra ikinci sırada ve en iyi optimize eden çevirmenler;
  3. Popüler tarayıcılarda javascript programlarının derlenme ve çalıştırılma hızı, en iyi çevirmenlerden yalnızca 2-3 kat daha düşüktür ve bazı yüksek kaliteli derleyicileri bile geride bırakmaktadır; kesinlikle (10 kattan fazla), program yürütme hızı açısından diğer komut dosyası dillerinin ve benzer programların çoğu çevirmeninden çok daha iyi performans gösterir;
  4. Intel C derleyicisi tarafından üretilen kodların hızının GNU derleyicisinden ve bazen LLVM'den fark edilir derecede daha yavaş olduğu ortaya çıktı;
  5. X86-64 derleme kodlarının hızı, benzer x86 kodlarından yaklaşık% 10 daha yavaş olabilir;
  6. Optimize edilmiş kodlar Intel işlemcide daha iyi çalışır;
  7. Intel işlemcinin yürütme hızı Lisp, Erlang, Auk (gawk, mawk) ve Bash dışında neredeyse her zaman daha yüksekti. Bash hızındaki fark büyük olasılıkla çevirmen veya donanımın kendisinden değil, test edilen sistemlerdeki farklı ortam ayarlarından kaynaklanmaktadır. Intel'in avantajı özellikle 32 bit kodlarda belirgindir;
  8. Test edilen çoğu dil yığını, özellikle Java ve Javascript, yalnızca çok sınırlı sayıda yinelemeli çağrıyı destekler. Bazı derleyiciler (gcc, icc, ...) çalışma zamanı değişkenlerini değiştirerek veya parametreye göre yığın boyutunu artırmanıza izin verir;
  9. Gawk, php, perl, bash'ın dikkate alınan sürümlerinde, tüm bilgisayarın belleğinin kullanılmasına izin veren dinamik bir yığın uygulanır. Ancak perl ve özellikle bash, yığını o kadar yoğun kullanır ki, ack (5,2,3) hesaplamak için 8-16 GB yeterli değildir. 5.4.20 php sürümünde yığın yaklaşık 200.000 çağrı ile sınırlandırılmıştır.

Sonuç olarak, programlama sanatında ustalaşmaya başlayan bir öğrenciden birkaç kelime.

Herhangi bir dilde gerekli hesaplamalar için programlar yazmak için, öncelikle değişkenlerin belirli bir dilde nasıl bildirildiğini, if-else türü bir yapının nasıl oluşturulacağını ve özyinelemenin nasıl organize edileceğini anlamanız gerekir. İşime basit bir Pascal diliyle başladım çünkü o zamanlar onu herkesten daha iyi biliyordum. Pascal'dan sonra, sözdizimleri kabaca benzer olduğundan C, Java ve Dino'yu ele aldım. C'nin oldukça ilginç, basit ve aynı zamanda sezgisel operatörlerle olduğu ortaya çıktı. Java, C / C ++ 'dan daha az kullanışlı görünüyordu - varsayılan olarak alınabilecek birçok alakasız şey yazmanız gerekiyor. Aynı sınıf ve dosya adlarına ihtiyaç duyulduğu anı da zorladım. Haskell'den sadece olumlu duygular kaldı. Kullanışlı, anlaşılır ve güçlü. Web uygulamaları geliştirmek için bir dil olan PHP, C'ye çok benzer: C kodunu minimum değişiklikle yapıştırabilirsiniz ve her şey olması gerektiği gibi çalışacaktır. Erlang sözdizimi açısından Haskell'e ve biraz da Prolog'a benzer. Ayrıca oldukça hoş ve anlaşılır bir dil, hiçbir zorluk çıkmadı. JavaScript sözdizimi Java veya C sözdizimine benzer.Hem ofis hem de GAMBAS sürümlerinde Visual Basic biraz garip ve garip bir sözdizimine sahiptir, ancak genel olarak onunla çok zor değildi. Daha sonra, C ve Java'nın temel sözdizimi hakkında bilgi edindikten sonra, Python'da oldukça hızlı bir şekilde kod yazdığı ortaya çıktı, çünkü Python C'ye benziyor. Lua ve oldukça güçlü ve esnek yapılarında herhangi bir sorun yoktu. Awk da C'ye benzer bir yapıya sahip, oldukça hızlı bir şekilde ustalaşmayı başardık. Lisp, daha önce C benzeri diller öğrenmiş bir kişi gibi, örneğin önek gösteriminin temel bir anlayışıyla bazı zorluklar yaşadı. Küçük bir geliştirme maliyetinden sonra çok uygun, mantıklı ve güzel görünüyordu. Daha sonra, spesifik, ancak çok ilginç ve temel olduğu ortaya çıkan mantık programlama dili Prolog'a geçtim. Ruby, nesne yönelimli programlama için güçlü bir desteğe sahip ve simgenin üzerinde çok güzel parlak kırmızı bir yakut bulunan bir dildir, mükemmel bir dil olduğu ortaya çıktı: fazladan parantez, noktalı virgül veya diğer gereksiz işaretler yok. En akılda kalanlardan biri. Python, OOP yapılarından ayrı olarak, daha az özlü değildir. Perl - "inci" adını taşısa da, dilin sembolü devedir ve devenin çok güzel olmadığı, ancak çok çalışabilen çok dayanıklı bir hayvan olduğu gerçeğine atıfta bulunur gibi görünüyor. Ruby'den sonra tekrar dolar, parantez ve noktalı virgül koymak pek hoş olmadı. Sözdizimi, bazı yerlerde Bash terminalinin kabuk diline benzer. Sonra montajcıyı aldım. Bazı zorluklar vardı ve işlemcinin ve kayıtlarının çalışmasını anlama ihtiyacı vardı. C'nin hesaplamalarla montajcıdan, makine kodundan daha hızlı başa çıktığı ortaya çıktığında şaşırtacak bir sınır yoktu! Bash ile ilgili herhangi bir sorun yoktu, ancak oraya çok fazla dolar koymanız gerekse de, hesaplama ve parantezler sırasında. Metapost / Metafont dili bazı sorunlara neden olmuştur - yalnızca 4096'dan büyük olmayan sayıları destekler. Sözdizimi oldukça geleneksel olmasına rağmen. Tickle (TCL) de oldukça geleneksel bir sözdizimine sahiptir, ancak satır odaklı - bu ve bash benzeri anlambilim ilk başta çok kafa karıştırıcıydı. En zoru PostScript görünüyordu. Bu dilde sözdizimi çok spesifiktir ve hazırlık yapılmadan hiçbir şey yazmak sezgisel olarak çalışmaz, bu yüzden ilgili literatürü incelemek ve en basit programlarla eğitime başlamak zorunda kaldım. PostScript gerçek bir testti: Ruby ve C'nin tüm araçlarına ve özelliklerine alıştıktan sonra sadece yığını kullanarak postfix gösteriminde çift özyineleme yazmak sorunluydu. Ackermann'ın postscript işlevini yazmak ve test etmek, bir duvarı diş fırçasıyla boyamaya benzer. Ama karmaşıklık açısından ilk sırada kesinlikle T E X. Daha önce hiç bu kadar zor bir şey görmemiştim. Ve bir öğretmenin doğrudan yardımı olmadan, bu dilin üstesinden gelmek mümkün olmazdı.

Dil yığınının boyutuyla ilgili verilerin ilginç olduğu ortaya çıktı. Bir dilin yığını ne kadar büyükse, Ackermann işlevini o kadar iyi idare edebilir. Ancak herhangi bir dildeki bir program, ack (5,2,3) hesaplamasıyla baş edemiyorsa, bu, dilin kötü ve uygunsuz olduğu anlamına gelmez. Bu dilin Metapost veya Postscript gibi başka yararlı amaçlar için yazılmış olması muhtemeldir.

Genel olarak, çalışma bana çok ilginç ve süper tanıdık geldi, örneğin aynı mantıksal ciroyu 20 farklı şekilde yazmak. Ayrıca, işlemci yazmaçları ilkesini anlamak ve yalnızca yığın ve üç işlemi kullanarak çift özyinelemeli bir işlev yazmak: yığını eklemek, silmek ve kaydırmak ufkumu büyük ölçüde genişletti.

Öğrencisinin bazı sonuçları öğretmene fazla kategorik göründü, ancak bunları kendisininkinden daha yeni tutmaya karar verdi.

- Rusya'da tasarlandı