2016-12-16 25 views
5

Enum.map |> Enum.sum ile saymanın Enum.count'dan daha hızlı çalıştığını buldum. Fakat yerleşik sayım neden etkin değil?Neden Enum.map, Elixir'deki Enum.count'tan daha verimli?

len | map(), µs | count(), µs 
=============================== 
    10 |  0.67 | 2.55 
    100 |  5.52 | 8.91 
1000 |  59.00 | 73.12 
10000 | 642.50 | 734.60 

Kaynak kodu: https://gist.github.com/artemrizhov/fc146f7ab390f7a807be833099e5cb83

$ elixir --version 
Erlang/OTP 19 [erts-8.1] [source-e7be63d] [64-bit] [smp:8:8] [async-threads:10] [hipe] [kernel-poll:false] 

Elixir 1.3.4 
+0

kodunuzu numaralandırma kodunun performansına bağlıdır mı olmak optimize eden bir PR ibraz? Çünkü gerçekten bu kadar önemli olmadıkça, bu beni anlama maliyetinde optimizasyon olarak vurur. Demek istediğim, bu kodu koruyan herkesin, Enum.count ile "Enum.map |> Enum.sum" ile ne yaptığınızı anlaması daha kolay olacaktır. Yani bu kodun performansı kritik değilse, eskiyi tercih ederim. –

+0

Evet, kodum bu işlevin performansına bağlıdır. Kodun okunabilmesi için kendi count() işlevini oluşturdum. – raacer

cevap

11

Bunun nedeni hem Enum.map/2 ve farklı listenin uzunluğu testlerin

elements |> Enum.count(&check/1) 
elements |> Enum.map(&(if check(&1), do: 1, else: 0)) |> Enum.sum 

sonuçları:

bu iki gruplarını karşılaştırma Enum.reduce/3 (Butarafından kullanılır 0) listeler için büyük ölçüde optimize edilmiştir, Enum.count/2 ise sadece jenerik sayılabilir bir versiyona sahiptir. Benim makinede

elements |> Enum.filter(&check/1) |> Enum.count 

ben tutarlı bir sonuç almak sağlanan modifiye kriter kullanılarak:

bile daha hızlı bir uygulama var, karışıklığa eklemek için adı geçen

len = 10 
map: 2.1706 μs 
count: 7.0754 μs 
filter: 1.9765 μs 

len = 100 
map: 19.921 μs 
count: 27.579 μs 
filter: 14.591 μs 

len = 1000 
map: 168.93 μs 
count: 178.93 μs 
filter: 163.43 μs 

len = 10000 
map: 2128.9 μs 
count: 1822.1 μs 
filter: 1664.6 μs 

hem " map "ve" filter "versiyonu çalıştıklarında daha fazla çöp üretirler, bu nedenle zaman kazanımlarının bir kısmı genişletilmiş çöp toplama zamanı tarafından tüketilebilir. Bu, kıyaslamalarda zaten görülebilir, çünkü versiyonlar arasındaki göreceli kazanımlar, listenin uzunluğu (ve üretilen ara çöp miktarı) arttıkça azalır.

DÜZENLEME: Enum.count/2 işlevi en hızlı bir https://github.com/elixir-lang/elixir/pull/5567

İlgili konular