2015-12-27 10 views
10

node.js में मेरे आवेदन के लिए मुझे कुछ संख्यात्मक मान (यानी एक संख्यात्मक रैंक) के आधार पर अवरोही क्रम में किसी सरणी के तत्वों को सॉर्ट करना होगा। चूंकि मेरा एप्लिकेशन प्रदर्शन-महत्वपूर्ण है, इसलिए मैंने अपनी डेटा संरचना बनाने का निर्णय लिया ताकि सॉर्टिंग अनुकूलित हो। मैंने अनुमान लगाया कि मेरे सरणी में प्रति तत्व निहित कम डेटा, तेज़ प्रकार होगा।संख्याओं के सरणी क्यों, ऑब्जेक्ट्स के सरणी से अधिक डेटा सॉर्ट करें, जावास्क्रिप्ट में कम डेटा?

संपादित: दोस्तों, ऐसा लगता है जैसे कि वहाँ कुछ अपने मूल परीक्षण के साथ त्रुटिपूर्ण था मेरी परिकल्पना का परीक्षण करने के लिए, मैं लंबाई 10000 के तीन विभिन्न सरणियों पर निम्नलिखित भाग गया। पहला परीक्षण उन लोगों की तुलना में काफी अधिक समय लेता है जो अनुसरण करते हैं। इस प्रकार, मैंने अपने परीक्षण कोड को वास्तविक प्रकार से पहले 'बफर' सॉर्ट करने के लिए संशोधित किया है। इसके अलावा, मैंने परीक्षणों के क्रम से होने वाली किसी भी पूर्वाग्रह को कम करने के लिए परीक्षणों की एक निश्चित संख्या के लिए अपने परीक्षणों के आदेश को घुमाया। मैंने तदनुसार परिणामों को संशोधित किया है।

यहाँ पूर्ण स्रोत: https://raw.githubusercontent.com/youngrrrr/js-array-sort-bench-test/master/arraySortTest.js

var buffer = [781197, ... ]; 
var sparseArray = [781197, ... ]; 
var sparseArray2 = [{'a' : 781197}, ...]; 
var denseArray = [{'a' : 781197, 'b': ['r', 'a', 'n', 'd', 'o', 'm'] }, ...]; 

/* buffer : for some reason, the first test always takes significantly longer than the others. I've added this to try to remove whatever bias there was before... */ 
console.time('buffer'); 
random.sort(compareSparse); 
console.timeEnd('buffer'); 
console.log(buffer[0]); // prints "58" 


/* sparseArray : an array whose elements are numbers */ 
console.time('sparse'); 
sparseArray.sort(compareSparse); 
console.timeEnd('sparse'); 
console.log(sparseArray[0]); // prints "58" 

/* sparseArray2 (not an accurate name, just got lazy) : 
    an array whose elements are objects with a single key-value pair mapping 
    an arbitrary name 'a' to a number (which we sort on) */ 
console.time('sparse2'); 
sparseArray2.sort(compareDense); 
console.timeEnd('sparse2'); 
console.log(sparseArray2[0]); // prints "{ a: 58 }" 

/* denseArray : an array whose elements are objects with two key-value 
    pairs mapping an arbitrary key 'a' to a number (which we sort on) and 
    another arbitrary key 'b' to an array (which is just supposed to be 
    extra data for the purpose of my hypothesis) */ 
console.time('dense'); 
denseArray.sort(compareDense); 
console.timeEnd('dense'); 
console.log(denseArray[0]); // prints "{ a: 58, b: [ 'r', 'a', 'n', 'd', 'o', 'm' ] }" 

function compareSparse(a, b) { 
    if (a < b) { 
     return -1; 
    } else if (a > b) { 
     return 1; } 
    else { 
     return 0; 
    } 
} 

function compareDense(a, b) { 
    if (a.a < b.a) { 
      return -1; 
     } else if (a.a > b.a) { 
      return 1; } 
     else { 
      return 0; 
     } 
    } 
} 

पुरानी परीक्षण:

25 के बाद परीक्षणों मैं (मुझे पता है, छोटा सा नमूना आकार, लेकिन मैं यह सब मैन्युअल रूप से किया था) औसत क्रम समय के लिए निम्नलिखित बार मिला:

  • sparseArray: (24 + 23 + 21 + 23 + 21 + 22 + 22 + 22 + 22 + 22 + 21 + 20 + 22 + 24 + 24 + 21 + 22 + 22 + 25 + 23 + 24 + 23 + 21 + 21 + 23)/25 = 22.32ms
  • sparseArray2: (4 + 4 + 4 + 4 + 4 + 5 + 5 + 5 + 5 + 4 + 6 + 5 + 5 + 4 + 5 + 4 + 4 + 4 + 5 + 6 + 4 + 5 + 4 + 4 + 5)/25 = 4.56ms
  • denseArray: (5 + 5 + 4 + 5 + 5 + 5 + 5 + 5 + 5 + 6 + 5 + 5 + 4 + 4 + 5 + 5 + 5 + 4 + 5 + 5 + 6 + 5 + 5 + 5 + 4)/25 = 4.8 8ms

नई परीक्षण:

के बाद 25 परीक्षणों (मुझे पता है, छोटा सा नमूना आकार, लेकिन मैं सभी मैन्युअल रूप से ऐसा किया) मैं औसत तरह समय के लिए निम्नलिखित समय मिल गया:

  • sparseArray: (4 + 4 + 4 + 4 + 3 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 3 + 4 + 4)/15 = 3.867ms
  • sparseArray2: (4 + 4 + 4 + 6 + 5 + 4 + 4 + 4 + 4 + 5 + 5 + 4 + 5 + 5 + 5)/15 = 4.533ms
  • घने आरे: (4 + 4 + 4 + 5 + 5 + 4 + 4 + 4 + 4 + 5 + 5 + 4 + 5 + 5 + 5)/15 = 4।466ms

तो मैं निम्नलिखित निष्कर्ष पर आए हैं: संख्याओं की

  • सरणी प्रकार वस्तुओं जिसका मान नंबर दिए गए हैं की सरणियों की तुलना में तेजी। यह सहजता से समझ में आता है।
  • किसी कारण से, और विरोधाभासी रूप से, किसी विशेष तत्व में अधिक डेटा के परिणामस्वरूप कम डेटा की तुलना में तेज़ सॉर्टिंग होता है (जैसा कि स्पैरएरे 2 बनाम डेंसएरे रनटाइम्स द्वारा प्रमाणित किया गया है)।

क्या मैं जानना चाहता हूँ है:

  • इन निष्कर्षों किसी भी प्रलेखन/कुछ मेरी परीक्षण के अलावा अन्य के द्वारा समर्थित हैं? यही है, क्या मैं सही निष्कर्ष तक पहुंचा?
  • और क्यों? वस्तुओं के सरणी की तुलना में संख्याओं के सरणी तेजी से क्यों क्रमबद्ध होते हैं (सहजता से समझ में आता है, लेकिन इसके पीछे क्या स्पष्टीकरण है, यदि कोई हो)? इतना ही नहीं, लेकिन अधिक डेटा वाले कम डेटा वाले डेटा को तेज क्यों लगता है?

और ध्यान दें, मैं इन निष्कर्षों या किसी भी चीज़ से शादी नहीं कर रहा हूं। नमूना आकार छोटा है और मेरा परीक्षण पहले त्रुटिपूर्ण साबित हुआ है, इसलिए मेरे परिणाम खराब परीक्षण का परिणाम हो सकते हैं। इसके अलावा, ऐसे कई कारक प्रतीत होते हैं जिनके बारे में मुझे कोई जागरूकता नहीं है जो परिणाम को प्रभावित कर सकती हैं (जैसा कि रयान ओहारा ने मेरी पिछली पोस्ट में बताया था)। इस पोस्ट का बिंदु जावास्क्रिप्ट में व्यवहार को सॉर्ट करने के लिए किसी तथ्य-आधारित स्पष्टीकरण को खोजना है।

पढ़ने के लिए धन्यवाद!

+3

परीक्षणों को पुन: व्यवस्थित करें और आपको बहुत ही महत्वपूर्ण उत्तर मिलेंगे - इन्हें फिर से शुरू करना सबसे अच्छा हो सकता है। – Ryan

+0

@ RyanO'Hara अरे वाह कि शर्मनाक है ... आश्चर्य क्या हो रहा है ... – youngrrrr

+0

@ RyanO'Hara - निर्धारित ... और अब मैं अभी भी बस के रूप में कई सवाल है ... – youngrrrr

उत्तर

4

क्या ये निष्कर्ष किसी भी दस्तावेज/ के अलावा मेरे परीक्षण द्वारा समर्थित हैं? यही है, क्या मैं सही निष्कर्ष तक पहुंचा?

.sort() कैसे कार्यान्वित किया जाता है किसी भी विनिर्देश वजह से नहीं है की बारीकियों, इसलिए .sort() के प्रदर्शन पहलुओं केवल ब्राउज़र या ब्याज की जे एस कार्यान्वयन में निष्पादन परीक्षण दिलचस्प डेटा सेट के माध्यम से खोज होने की कर रहे हैं। आपके लिए महत्वपूर्ण परिस्थितियों में परीक्षण के साथ बहुत अधिक प्रदर्शन प्रश्नों का सबसे अच्छा उत्तर दिया जाता है। इसके बाहर सामान्यीकरण आसानी से भ्रामक या गलत हो सकता है और सभी विन्यासों पर जरूरी नहीं है।

और क्यों? वस्तुओं के सरणी (आसानी से समझ में आता है, लेकिन कोई भी है) के पीछे स्पष्टीकरण क्या है? इतना ही नहीं, लेकिन अधिक डेटा वाले सरणी क्यों कम डेटा वाले लोगों की तुलना में तेज़ी से सॉर्ट करते हैं? सरणी की लंबाई

  1. :

एक कस्टम तुलना समारोह के साथ एक दिया प्रकार का प्रदर्शन निम्न आइटम द्वारा नियंत्रित किया जा रहा है। एक लंबी सरणी को अधिक प्रकार की तुलना की आवश्यकता होगी।

  • आंतरिक तरह एल्गोरिथ्म के स्मार्ट संभव
  • कस्टम प्रकार समारोह (कितनी देर तक यह एक दिया प्रकार तुलना निष्पादित करने के लिए लेता है) के प्रदर्शन के रूप में के रूप में छोटे प्रकार की तुलना की संख्या को कम करने के लिए।
  • इसलिए, यदि आप कस्टम प्रकार समारोह और .sort() कार्यान्वयन आप लगातार प्रयोग कर रहे हैं और सरणी स्थिरांक में डेटा रखें, फिर एक लंबे समय तक सरणी अब सॉर्ट करने के लिए ले जाएगा।

    लेकिन, यदि आप ऊपर 1. और 3. दोनों को बदलते हैं (एक अनुकूल दिशा में और एक कम अनुकूल दिशा में) जैसा कि आप करते हैं जब आप संख्याओं की सरणी को क्रमबद्ध करने के लिए संख्याओं की एक सरणी को सॉर्ट करने से जाते हैं एक विशिष्ट संपत्ति मूल्य, तो गति में डेल्टा इस बात पर निर्भर करेगा कि क्या शुद्ध परिवर्तन सकारात्मक या नकारात्मक है जो कई चीजों पर निर्भर करता है जो एक बहुत ही विशिष्ट कार्यान्वयन और डेटा सेट के बाहर भविष्यवाणी करना कठिन होता है और बहुत से परीक्षण (दूसरे शब्दों में, कुछ भी हो सकता था)।

    वस्तुओं की एक सरणी से एक संपत्ति छँटाई बनाम संख्या की एक सरणी छँटाई पर कुछ परीक्षण जानकारी के लिए, http://jsperf.com/sort-value-vs-property देखते हैं। कोई आश्चर्य की बात नहीं है, संख्याओं की सरणी को सॉर्ट करने के लिए थोड़ा तेज़ है हालांकि बहुत कुछ नहीं।

    +0

    अच्छी चर्चा! हालांकि एक नोट: सभी परीक्षण सरणी एक ही लंबाई हैं: 10,000 तत्व प्रत्येक। और चूंकि सॉर्ट कुंजियां प्रत्येक सरणी में समान दिखाई देती हैं, इसलिए सभी को सॉर्ट फ़ंक्शन में कॉल की समान संख्या में परिणाम होना चाहिए - वास्तव में, वही * अनुक्रम * कॉल और पैरामीटर मानों का। सॉर्ट फ़ंक्शंस के बीच एक स्पष्ट अंतर यह है कि उनमें से एक थोड़ा अधिक काम करता है क्योंकि यह सीधे संख्यात्मक मानों के बजाय संपत्ति संदर्भों का उपयोग कर रहा है। –

    +0

    @ माइकलजीरी - यही बात है - "वैज्ञानिक विधि"। मैं वास्तव में तेजी से देखने के लिए मूल्यों और वस्तुओं के बराबर लंबाई सरणी की तुलना करने की कोशिश कर रहा हूं। एक समय में एक चीज का परीक्षण करने के लिए दूसरे को बदलने के दौरान एक चर स्थिर रखें। यदि आप विभिन्न सामग्रियों के साथ अलग-अलग लंबाई के दो सरणी की तुलना करते हैं, तो परिणाम आपको कुछ भी उपयोगी नहीं बताते हैं क्योंकि आप नहीं जानते कि किस बदलाव से परिणाम में अंतर आया है। हां, परिणाम यह है कि आप इसकी उम्मीद करेंगे, लेकिन परीक्षण आपको बताता है कि अंतर काफी लंबी सरणी के लिए भी बहुत अधिक नहीं है। – jfriend00

    +0

    यहां एक विशिष्ट त्रुटि है जिसका मैं जिक्र कर रहा था: "यदि आप ऊपर 1. और 3. दोनों को बदलते हैं (एक अनुकूल दिशा में और एक कम अनुकूल दिशा में) जैसा कि आप करते हैं तो आप सॉर्ट करने के लिए संख्याओं की सरणी को सॉर्ट करने से करते हैं एक विशिष्ट संपत्ति मूल्य द्वारा वस्तुओं की एक सरणी "केवल आपके बिंदु 3 क्रमबद्ध उदाहरणों के बीच बदल रहा है; बिंदु 1 (सरणी की लंबाई) उन सभी में समान है। –

    0

    मेरा मानना ​​है कि इसे सॉर्टिंग जावास्क्रिप्ट में काम करने के तरीके से करना है। तुलनात्मक कार्य की आपूर्ति नहीं होने पर सॉर्ट करने से पहले are converted to strings नंबर, कार्रवाई में कुछ समय लगता है।

    +2

    यह डिफ़ॉल्ट तुलना फ़ंक्शन के साथ है। ओपी एक कस्टम का उपयोग करता है। – Oriol

    +0

    मुझे लगता है कि यह एक उचित बिंदु है (और कुछ मैं निश्चित रूप से ध्यान में रखूंगा!) लेकिन जैसा कि किसी और ने इंगित किया है, यह मेरे द्वारा उपयोग किए जाने वाले कस्टम तुलना फ़ंक्शन के कारण लागू नहीं होता है। – youngrrrr

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