2012-07-28 13 views
11

कल्पना कीजिए कि आप पूर्णांक निम्नलिखित सरणी है:PHP और मिलियन सरणी बच्चे

array(1, 2, 1, 0, 0, 1, 2, 4, 3, 2, [...]); 

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

अगर यह फ़ाइल बाद में PHP में वापस पढ़ा जाता है (उदाहरण के लिए file_get_contents + json_decode का प्रयोग करके) यह 700 से 900ms पर ले जाता है सिर्फ सरणी वापस पाने के लिए - "ठीक है" मैंने सोचा, "यह शायद उचित है, क्योंकि json_decode के बारे में 2 पार्स करने के लिए है लाख अक्षर, चलो इसे कैश करें "। एपीसी इसे एक प्रविष्टि में कैश करता है जो लगभग 68 एमबी लेता है, शायद सामान्य, ज़वाल बड़े होते हैं। हालांकि एपीसी से वापस इस सरणी को कुछ अच्छा 600ms लेता है जो मेरी आंखों में अभी भी बहुत अधिक है।

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

तो सवाल:

  • अगर मैं एक एक लाख प्रविष्टियों सरणी, कोई फर्क नहीं पड़ता डेटा की दुकान या विधि, पीएचपी में लोड करने का इरादा है कि मैं इस विलंबता आशा करनी चाहिए? जहां तक ​​मैं समझता हूँ एपीसी zval ही संग्रहीत करता है, तो सैद्धांतिक रूप से एपीसी से यह पुन: प्राप्त करने के रूप में तेजी से के रूप में यह संभवतः प्राप्त कर सकते हैं (कोई पार्स, कोई रूपांतरण, कोई डिस्क नहीं पहुँच)

  • क्यों एपीसी के लिए इतनी धीमी गति से होना चाहिए है कुछ इतना आसान लगता है?

  • क्या PHP का उपयोग कर स्मृति में पूरी तरह से एक लाख प्रविष्टियों सरणी को लोड करने का कोई प्रभावी तरीका है? मानते हुए राम उपयोग एक समस्या नहीं है।

  • अगर मुझे इंडेक्स के आधार पर इस सरणी के केवल स्लाइसों का उपयोग करना था (उदाहरण के लिए इंडेक्स 15 से इंडेक्स 76 तक खंड लोड करना) और वास्तव में स्मृति में पूरी सरणी नहीं है (हाँ, मुझे समझ में आता है कि यह एक आसान तरीका है यह कर रहा है, लेकिन मैं सभी पक्षों को जानना चाहता था), पूर्ण सरणी के लिए सबसे कुशल डेटा स्टोर सिस्टम क्या होगा? जाहिर है आरडीबीएम नहीं; मैं रेडिस सोच रहा हूं, लेकिन मुझे अन्य विचारों को सुनकर खुशी होगी।

+1

क्या आपने [SplfixedArray] (http://php.net/manual/en/class.splfixedarray.php) की कोशिश की है? – Buddy

+0

@ बुड्डी यूप, ज्यादा अंतर नहीं, शायद कम स्मृति का उपयोग करता है लेकिन एपीसी उतना ही लंबा लेता है। – Mahn

+1

यदि संख्याएं छोटी हैं और सरणी स्थैतिक है, तो क्या आप इसके बजाय एक 1 एमबी स्ट्रिंग ऑब्जेक्ट का उपयोग नहीं कर सकते? – 6502

उत्तर

3

कहें कि पूर्णांक सभी 0-15 हैं। तो फिर तुम बाइट प्रति 2 स्टोर कर सकते हैं:

<?php 
$data = ''; 
for ($i = 0; $i < 500000; ++$i) 
    $data .= chr(mt_rand(0, 255)); 

echo serialize($data); 

चलाने के लिए: php ints.php > ints.ser

अब आप 15.

करने के लिए एक 500000 बाइट 0 से 1000000 यादृच्छिक पूर्णांकों युक्त तार के साथ एक फ़ाइल लोड करने के लिए:

<?php 
$data = unserialize(file_get_contents('ints.ser')); 

function get_data_at($data, $i) 
{ 
    $data = ord($data[$i >> 1]); 

    return ($i & 1) ? $data & 0xf : $data >> 4; 
} 

for ($i = 0; $i < 1000; ++$i) 
    echo get_data_at($data, $i), "\n"; 

मेरी मशीन पर लोडिंग समय लगभग 0000 सेकेंड है।

बेशक यह आपकी स्थिति पर सीधे लागू नहीं हो सकता है, लेकिन यह एक लाख प्रविष्टियों के ब्लोएटेड PHP सरणी से बहुत तेज होगा। काफी स्पष्ट रूप से, PHP में बड़ा एक सरणी होने का उचित समाधान कभी नहीं होता है।

मैं यह नहीं कह रहा कि यह उचित समाधान है, लेकिन यह निश्चित रूप से काम करने योग्य है यदि यह आपके पैरामीटर फिट बैठता है।

ध्यान दें कि यदि आपकी सरणी में 0-255 रेंज में पूर्णांक हैं, तो आप पैकिंग से छुटकारा पा सकते हैं और डेटा को ord($data[$i]) के रूप में एक्सेस कर सकते हैं। उस स्थिति में, आपकी स्ट्रिंग 1 एम बाइट लंबी होगी।

अंत में, file_get_contents() के दस्तावेज़ के अनुसार, php स्मृति फ़ाइल को मानचित्र करेगा।यदि हां, तो अपने सबसे अच्छे प्रदर्शन के लिए एक फ़ाइल के लिए कच्चे बाइट्स डंप करने के लिए होगा, और का उपयोग करें इसे पसंद:

$ints = file_get_contents('ints.raw'); 
echo ord($ints[25]); 

मतलब यह है कि ints.raw वास्तव में एक लाख बाइट्स लंबा है।

+0

मैथ्यू, मेरे सुझाव के लांगहैंड संस्करण के लिए धन्यवाद। कुछ बिंदु: हां 'f_g_s()' अधिकांश मामलों में फ़ाइल पर mmap का उपयोग करता है (उदाहरण के लिए, एनएफएस घुड़सवार फ़ाइल के लिए नहीं), लेकिन फिर भी यह सामग्री स्थानीय रूप से आवंटित स्ट्रिंग में प्रतिलिपि बनाता है। हां, 'ord ($ ints [NNN]) 'पहुंच सबसे कुशल ओपोड अनुक्रम उत्पन्न करती है। आपका 2 एमएस इसलिए है क्योंकि फ़ाइल सामग्री VFAT कैश्ड हैं। यह उत्पादन सर्वर पर मामला नहीं हो सकता है। – TerryE

+0

यह मूल रूप से मैंने सोचा था जब 6502 और टेरीई ने इसका सुझाव दिया था, लेकिन फिर भी यह देखना बहुत अच्छा है। उन 2 एमएमएस शायद यह है क्योंकि फाइल को @ टेरीई उल्लेखों जैसे कैश किया गया था, लेकिन एपीसी में कैश किया जा सकता है, यह बिना किसी अचूक ओवरहेड के ठीक है। मैं इसे देख लूंगा। – Mahn

+0

दरअसल, एपीसी से इसे संग्रहित करना और पुनर्प्राप्त करना हवा में किया जा सकता है। मैं इस जवाब को स्वीकार कर रहा हूं क्योंकि प्रदर्शन और स्मृति के अनुसार यह उतना ही अच्छा है जितना संभवतः यह प्राप्त हो सकता है कि कोई व्यक्ति पूरे सरणी को स्मृति में संग्रहीत कर सके; चाहे मैं पूरी चीज को स्मृति में संग्रहीत कर रहा हूं या नहीं, एक और सवाल है जिसे मैंने अभी तक तय नहीं किया है, लेकिन इस बीच यह बेहतर काम करेगा। – Mahn

2

एपीसी डेटा धारावाहिक संग्रहीत करता है, तो यह रूप में यह एपीसी से वापस भरी हुई है unserialized किया जाना है। यही वह जगह है जहां आपका ओवरहेड है।

इसे लोड करने का सबसे प्रभावी तरीका PHP के रूप में फ़ाइल को लिखना और शामिल करना है(), लेकिन आपके पास कभी भी एक लाख तत्वों वाले सरणी के साथ दक्षता का कोई स्तर नहीं होगा ... इसमें एक भारी राशि होती है स्मृति की, और लोड करने में समय लगता है। यही कारण है कि डेटाबेस का आविष्कार किया गया था, तो डेटाबेस के साथ आपकी समस्या क्या है?

संपादित

आप serialize/deserialize तेजी लाने के लिए, igbinary विस्तार पर एक नज़र डालें चाहते हैं

+1

वह इसके बारे में कभी नहीं सुना होगा। –

+0

हां, मैंने कभी डेटाबेस के बारे में नहीं सुना है :) डेटाबेस के खिलाफ कुछ भी नहीं, मैंने अभी सोचा है क्योंकि डेटा स्थिर कुछ सरल है जो स्मृति में रहता है जैसे एपीसी बेहतर काम करेगा; एपीसी डेटा को क्रमबद्ध करने के लिए यह एक दयालुता है, हालांकि मैंने सोचा कि यह मामला नहीं था। – Mahn

+0

आपको पता चलेगा कि अधिकांश कैश (एपीसी, मेमकेचे, रेडिस इत्यादि) को डेटा को क्रमबद्ध करने की आवश्यकता होगी क्योंकि उन्हें क्रॉस-प्लेटफ़ॉर्म टूल के रूप में डिज़ाइन किया गया है, इसलिए विशेष रूप से PHP डेटाटाइप/ज़्वल्स के लिए डिज़ाइन नहीं किया गया है। –

1

मैं बेतरतीब ढंग से हर बार उत्पन्न नहीं कर सकते क्योंकि यह अनुरूप होना चाहिए और हमेशा एक ही इंडेक्स पर वही मान हैं।

क्या आपने कभी छद्म-यादृच्छिक संख्याओं पर पढ़ा है? इस छोटी सी चीज को बीज कहा जाता है जो इस मुद्दे को संबोधित करता है।

अपने विकल्पों और दावों को भी बेंचमार्क करें। क्या आपने file_get_contents बनाम json_decode का समय दिया है? भंडारण और पहुंच लागत के बीच यहां एक व्यापार-बंद किया जाना है। उदाहरण के लिए। यदि आपकी संख्या 0..9 (या 0..255) है तो उन्हें 2 एमबी स्ट्रिंग में स्टोर करना आसान हो सकता है और इस पर एक एक्सेस फ़ंक्शन का उपयोग करना आसान हो सकता है। 2 एमबी तेजी से लोड होगा चाहे एफएस या एपीसी से।

+0

हाँ, एल्गोरिदमिक रूप से एक निश्चित बीज के आधार पर पूर्णांक की सूची उत्पन्न करना उन विकल्पों में से एक है जो मैं सोच रहा था, और संभवतः सबसे सुरुचिपूर्ण; मैं छद्म यादृच्छिक संख्याओं को देखूंगा और देख सकता हूं कि यह मेरी जरूरत के अनुसार फिट हो सकता है या नहीं। – Mahn

1

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

यदि आप इसे गति देना चाहते हैं, तो सरणी के प्रत्येक तत्व को अलग से असाइन करने का प्रयास करें - आप धारावाहिकरण में बिताए गए समय के लिए फ़ंक्शन कॉल ओवरहेड का व्यापार कर सकते हैं। आप इसे अपने स्वयं के एक्सटेंशन के साथ भी बढ़ा सकते हैं, अपने डेटासेट को एक छोटे से पुनर्प्राप्ति इंटरफेस में लपेट सकते हैं।

मैं अनुमान लगा रहा हूं कि आप सीधे zvals क्यों स्टोर नहीं कर सकते हैं क्योंकि उनमें आंतरिक स्थिति होती है, और आप बस चर तालिका प्रतीक तालिका को पिछली तालिका में इंगित नहीं कर सकते हैं।

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