2016-12-16 11 views
5

मुझे पता चला है कि Enum.map |> Enum.sum के साथ गिनती Enum.count से बहुत तेज है। लेकिन अंतर्निहित गिनती कार्य कुशल क्यों नहीं है?क्यों Enum.map Elixir में Enum.count से अधिक कुशल है?

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 

स्रोत कोड: 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

अपने कोड गणन कोड के प्रदर्शन पर निर्भर है होना करने के लिए प्रस्तुत? क्योंकि जब तक कि यह वास्तव में महत्वपूर्ण नहीं है, यह मुझे समझ की लागत पर अनुकूलन के रूप में मारता है। मेरा मतलब है कि इस कोड को बनाए रखने के लिए यह आसान है कि आप 'Enum.count' बनाम' Enum.map |> Enum.sum' के साथ क्या कर रहे हैं। इसलिए जब तक कि इस कोड का प्रदर्शन महत्वपूर्ण नहीं है, मैं पूर्व का चयन करता हूं। –

+0

हां, मेरा कोड इस फ़ंक्शन के प्रदर्शन पर निर्भर है। मैंने अपनी गिनती() फ़ंक्शन बनाई है ताकि कोड पठनीय बना रहता है। – raacer

उत्तर

11

इसका कारण यह है दोनों Enum.map/2 और सूची के विभिन्न लंबाई के साथ परीक्षण के

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

परिणाम:

इन दो पंक्तियों की तुलना करें Enum.reduce/3 (जिसका उपयोगद्वारा किया जाता है 0) सूचियों के लिए अत्यधिक अनुकूलित हैं, जबकि Enum.count/2 में केवल एक सामान्य गणितीय संस्करण है।

भ्रम को जोड़ने के लिए, यहां तक ​​कि एक तेजी से कार्यान्वयन:

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

मेरी मशीन पर, संशोधित बेंचमार्क आप मैं के अनुरूप परिणाम प्राप्त प्रदान की का उपयोग कर: यह कहा

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 

दोनों " नक्शा "और" फिल्टर "संस्करण संचालित होने पर अधिक कचरा उत्पन्न करता है, इसलिए कुछ समय के लाभ को विस्तारित कचरा संग्रहण समय से उपभोग किया जा सकता है। यह पहले से ही बेंचमार्क में दिखाई दे रहा है, क्योंकि संस्करणों के बीच सापेक्ष लाभ सूची की लंबाई (और उत्पादित मध्यवर्ती कचरा की मात्रा) की लंबाई के रूप में घटता है।

संपादित करें: मैं एक पीआर कि अनुकूलन कर Enum.count/2 समारोह सबसे तेजी से एक https://github.com/elixir-lang/elixir/pull/5567

संबंधित मुद्दे