Lisedeki ilk programlama dersimden beri, sicim operasyonlarının efsanevi "ortalama operasyon" dan daha yavaş - yani daha maliyetli - olduğunu duydum. Neden onları bu kadar yavaş yapıyor? (Bu soru bilerek geniş bırakılmıştır.)
Lisedeki ilk programlama dersimden beri, sicim operasyonlarının efsanevi "ortalama operasyon" dan daha yavaş - yani daha maliyetli - olduğunu duydum. Neden onları bu kadar yavaş yapıyor? (Bu soru bilerek geniş bırakılmıştır.)
Yanıtlar:
"Ortalama operasyon" ilkellerde gerçekleşir. Ancak, dizgelerin ilkel olarak kabul edildiği dillerde bile, yine de kaputun altındaki dizilerdir ve tüm dizeyi içeren bir şey yapmak, N'nin dizenin uzunluğu olduğu O (N) zaman alır.
Örneğin, iki sayı eklemek genellikle 2-4 ASM komutunu alır. İki dizeyi birleştirmek ("ekleme"), yeni bir bellek ayırma ve dizenin tamamını içeren bir veya iki dizi kopya gerektirir.
Bazı dil faktörleri daha da kötüleştirebilir. Örneğin, C'de bir dize yalnızca boş olarak sonlandırılmış bir karakter dizisine bir göstericidir. Bu, ne kadar süreceğini bilmediğiniz anlamına gelir, bu nedenle hızlı kopyalama işlemleriyle dizge kopyalama döngüsünü optimize etmenin bir yolu yoktur; bir seferde bir karakter kopyalamanız gerekir, böylece boş sonlandırıcı için her baytı test edebilirsiniz.
char*
değil, bir strbuf
ve kare 1'e ediyoruz için bu kadar sadece var sen dilde kötü bir tasarım yapıldığında yapabilir.
buf
işaretçi orada. Asla uygun olmadığını ima etmek istemedim; bunun yerine, gerekli. Standart kütüphane kadar temel olan şeyler de dahil olmak üzere, optimize edilmiş ancak standart dışı dize türünüz hakkında hiçbir şey bilmeyen kodların yavaş ve güvensiz olarak geri çekilmesi gerekir char*
. İsterseniz bu FUD'yi arayabilirsiniz, ancak bu doğru değildir.
Bu eski bir iş parçacığı ve diğer cevapların harika olduğunu düşünüyorum ama bir şeyi görmezden gelin, işte benim (geç) 2 sentim.
İplerle ilgili sorun, çoğu dilde ikinci sınıf vatandaş olmalarıdır ve aslında çoğu zaman dil spesifikasyonunun bir parçası değildir: en üstte zaman zaman bazı sözdizimsel şeker kaplamalı bir kütüphane uygulamasıdır. Onları kullanmak için daha az acı çekmek.
Bunun doğrudan sonucu dilin karmaşıklığının çok büyük bir bölümünü görüşünüzden uzak tutması ve sinsi yan etkilerin karşılığını ödemektir, çünkü onları tıpkı tıpkı bir gibi düşük seviyeli atomik bir varlık gibi düşünme alışkanlığı haline gelirsiniz diğer ilkel türler (en çok oy alan cevap ve diğerleri tarafından açıklandığı gibi).
Bu altta yatan "karmaşıklık" öğelerinin bir tanesi, dize uygulamalarının çoğunun, dizeyi temsil etmek için bitişik bir bellek alanına sahip basit bir veri yapısı kullanmaya başvurmasıdır: dizininiz.
Bu iyi bir anlam ifade ediyor, dizeye bir bütün olarak hızlı erişimin olmasını istediğiniz gibi, dikkat edin. Ancak bu dizgiyi değiştirmek istediğinizde potansiyel olarak korkunç maliyetler anlamına gelir. Ortadan bir elemana erişmek, hangi indeksin peşinde olduğunuzu biliyorsanız, ancak bir koşulu temel alan bir öğe aramak hızlı olmayabilir.
Diliniz dizenin uzunluğunu önbelleğe almıyorsa ve karakterleri saymak için içinden geçmesi gerekiyorsa, dizenin boyutunu döndürmek bile maliyetli olabilir.
Benzer nedenlerden dolayı, dizginize eleman eklemek , büyük olasılıkla bu işlemin gerçekleşmesi için bir miktar bellek ayırmanız gerekeceğinden masraflı olacaktır.
Dolayısıyla farklı diller bu konulara farklı yaklaşımlar getiriyor. Örneğin Java, bazı geçerli nedenlerle (önbellek uzunluğu, iş güvenliği) ve değişken meslektaşları için (StringBuffer ve StringBuilder) dizelerini sabit hale getirme özgürlüğüne kavuştu; Her zaman, ancak en iyi durum senaryoları için umut. Genel olarak iyi çalışır, ancak aşağı tarafı bazen bellek etkileri için ödeme yapmaktır.
Ayrıca, ve bu, yine de, dilinizin sözdizimsel şeker kaplamasının bunu sizden hoş görünmesini engellemesinden kaynaklanmaktadır, genellikle unicode destek terimleriyle düşünmüyorsunuz (özellikle gerçekten ihtiyaç duymadığınız sürece) ve o duvara çarptı). Bazı diller, ileri görüşlü olarak, 8-bitlik basit ilkel karakterlerin altında yatan dizileri olan dizeleri uygulamıyor. UTF-8 veya UTF-16'da pişirilmişler ya da sizin için neyin size destek veriyorlar ve bunun sonucu, çoğu zaman gerekmeyen muazzam derecede daha büyük bir bellek tüketimi ve bellek ayırmak, dizeleri işlemek için daha büyük bir işlem süresidir. ve kod noktalarını değiştirmekle el ele giden bütün mantığı uygulayın.
Tüm bunların sonuçları, sözde kodda eşdeğer bir şey yaptığınızda:
hello = "hello,"
world = " world!"
str = hello + world
- dil geliştiricilerin sizin dışında davranmalarını sağlamak için harcadıkları tüm çabalara rağmen - basit bir şekilde:
a = 1;
b = 2;
shouldBeThree = a + b
Bir takip olarak, okumak isteyebilirsiniz:
Teorik bir Random-Access Stored-Program makinesinin tek bir işlemi için "ortalama işlem" tabiri kısaca açıktır . Bu, çeşitli algoritmaların çalışma zamanını analiz etmek için geleneksel olarak kullanılan teorik makinedir.
Genel işlemler normal olarak yükleme, toplama, çıkarma, saklama, dallanma olarak alınır. Belki de okuyun, yazdırın ve durdurun.
Ancak çoğu string işlemi bu temel işlemlerin birkaçını gerektirir. Örneğin, bir dizgenin çoğaltılması normal olarak bir kopyalama işlemi gerektirir ve bu nedenle bir dizgenin uzunluğuyla orantılı olan bir dizi işlem (yani, "doğrusal" dır). Başka bir dizgide bir alt dizgenin bulunması da doğrusal karmaşıklığa sahiptir.
Tamamen işleme, dizelerin nasıl temsil edildiğine ve hangi optimizasyonların olduğuna bağlıdır. Dizeler 4 veya 8 bayt uzunluğundaysa (ve hizalıysa), mutlaka daha yavaş olmaz - çoğu işlem ilkel kadar hızlı olur. Veya, tüm dizelerin bir 32-bit veya 64-bit karma değeri varsa, birçok işlem de aynı kadar hızlı olur (karma maliyetini siz öderseniz de).
Aynı zamanda "yavaş" ile ne demek istediğine de bağlı. Çoğu program, gerek duyulan şey için dizeleri çok hızlı bir şekilde işler. Dize karşılaştırmaları iki girişi karşılaştırmak kadar hızlı olmayabilir, ancak yalnızca profil oluşturma, programınız için "yavaş" ın ne anlama geldiğini ortaya çıkarır.
Sorunuza bir soru ile cevap vereyim. Neden bir kelime dizisi söylemek, tek bir kelime söylemekten daha uzun sürüyor?