2011-01-26 10 views
9

मेरे पास सी # (.NET 4.0) में लिखा गया एक .NET अनुप्रयोग है। इस एप्लिकेशन में, हमें फ़ाइल से एक बड़ा डेटासेट पढ़ना होगा और सामग्री को ग्रिड जैसी संरचना में प्रदर्शित करना होगा। इसलिए, इसे पूरा करने के लिए, मैंने फ़ॉर्म पर डेटाग्रिड व्यू रखा। इसमें 3 कॉलम हैं, सभी कॉलम डेटा फ़ाइल से आता है। प्रारंभ में, फ़ाइल में 600,000 रिकॉर्ड थे, जो डेटाग्रिड व्यू में 600,000 लाइनों के अनुरूप थे।बहुत बड़े डेटासेट से निपटने और बस समय लोड करने में

मुझे तुरंत पता चला कि, डेटाग्रिड व्यू इतने बड़े डेटा-सेट के साथ गिर गया है, इसलिए मैंने वर्चुअल मोड पर स्विच किया था। इसे पूरा करने के लिए, मैंने पहली बार फ़ाइल को 3 अलग-अलग सरणी (3 कॉलम के अनुरूप) में पढ़ा, और फिर सेलवैल्यूइडेड इवेंट आग लगती है, मैं सरणी से सही मान प्रदान करता हूं।

हालांकि, इस फ़ाइल में रिकॉर्ड की एक बड़ी (बड़ी!) संख्या हो सकती है, जैसा कि हम जल्दी से पता चला। जब रिकॉर्ड आकार बहुत बड़ा होता है, तो सभी डेटा को किसी सरणी में पढ़ना या सूची <> आदि, संभव नहीं है। हम जल्दी से स्मृति आवंटन त्रुटियों में भागते हैं। (स्मृति अपवाद से बाहर)।

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

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

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

धन्यवाद

उत्तर

5

आप स्मृति में अपने पूरे डेटा सेट फिट नहीं कर सकते हैं, तो आप एक बफरिंग योजना की जरूरत है। CellValueNeeded के जवाब में DataGridView भरने के लिए आवश्यक डेटा की मात्रा को पढ़ने के बजाय, आपके आवेदन को उपयोगकर्ता के कार्यों की अपेक्षा करनी चाहिए और आगे पढ़ें। इसलिए, उदाहरण के लिए, जब कार्यक्रम पहली बार शुरू होता है, तो इसे पहले 10,000 रिकॉर्ड (या शायद केवल 1,000 या शायद 100,000 - जो भी आपके मामले में उचित है) पढ़ना चाहिए। फिर, CellValueNeeded अनुरोध तुरंत स्मृति से भरे जा सकते हैं।

चूंकि उपयोगकर्ता ग्रिड के माध्यम से चलता है, तो जितना संभव हो सके आपका प्रोग्राम उपयोगकर्ता से एक कदम आगे रहता है। यदि उपयोगकर्ता आपके आगे कूदता है (कहें, आगे से अंत तक कूदना चाहता है) तो छोटे विराम हो सकते हैं और अनुरोध को पूरा करने के लिए आपको डिस्क पर जाना होगा।

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

16 मिलियन रिकॉर्ड वास्तव में स्मृति में रखने के लिए कई रिकॉर्ड नहीं हैं, जब तक कि रिकॉर्ड बहुत बड़े न हों। या यदि आपके सर्वर पर ज्यादा मेमोरी नहीं है। निश्चित रूप से, 16 मिलियन List<T> के अधिकतम आकार के पास कहीं भी नहीं है, जब तक T एक मान प्रकार (संरचना) नहीं है। आप यहां कितने गीगाबाइट डेटा के बारे में बात कर रहे हैं?

+1

हैलो जिम, टी, 4 डबल-परिशुद्धता फ्लोट के साथ एक संरचना है। तो, 4 * 8 * 16 एम = 512 एमबी डेटा। – SomethingBetter

+0

मैंने .NET MemoryMappedFile का उपयोग करने का प्रयास किया, लेकिन जैसे ही आप एक दृश्य बनाते हैं, यह स्पष्ट रूप से फ़ाइल को स्मृति में लोड करने का प्रयास करता है, क्योंकि मुझे स्मृति अपवादों से बाहर निकलना पड़ता है। मैंने सोचा कि शायद MemoryMappedFile आंतरिक रूप से पृष्ठों तक डेटा तक पहुंच जाएगा और केवल आवश्यक पृष्ठों को स्मृति में लोड करेगा। – SomethingBetter

+0

@ SomethingBetter: मुझे लगता है कि अगर आप 32-बिट मशीन पर हैं तो 512 एमबी एक समस्या है। यदि आप मेमोरी मैप की गई फ़ाइल का उपयोग करते हैं, तो आप पूरे फ़ाइल आकार से छोटी फ़ाइल में अपना विचार बनाना चाहेंगे। फिर आप डेटा के माध्यम से उपयोगकर्ता पेज के रूप में अपना दृश्य समायोजित करते हैं। –

1

पंक्तियों और स्तंभों को प्रबंधित करना जिन्हें बहु-स्तंभ गणनाओं में उपयोग किया जा सकता है, उप-कुल, चुनौतियों का एक अद्वितीय सेट प्रस्तुत करता है; एक संपादक को सामना करने वाले लोगों की समस्या की तुलना करने के लिए वास्तव में उचित नहीं है। तीसरे पक्ष के डाटाग्रिड नियंत्रण वीबी 6 दिनों के बाद से बड़े डेटासेट क्लाइंट-साइड को प्रदर्शित करने और छेड़छाड़ करने की समस्या को संबोधित कर रहे हैं। लोड-ऑन-डिमांड या स्वयं निहित क्लाइंट-साइड गर्गुआंटआन डेटासेट का उपयोग करके वास्तव में स्नैपी प्रदर्शन प्राप्त करना एक छोटा सा काम नहीं है। लोड-ऑन-डिमांड सर्वर-साइड विलंबता से पीड़ित हो सकता है; क्लाइंट पर पूरे डेटासेट में हेरफेर करना स्मृति और सीपीयू सीमा से पीड़ित हो सकता है। कुछ तृतीय-पक्ष नियंत्रण जो क्लाइंट-साइड और सर्वर-साइड लॉजिक दोनों की आपूर्ति करते हैं, जबकि अन्य समस्या 100% क्लाइंट-साइड को हल करने का प्रयास करते हैं।

3

ठीक है, यहाँ एक समाधान काफी बेहतर काम करने के लिए प्रतीत होता है कि है:

चरण 0: एक कम मूल्य के dataGridView.RowCount सेट, 25 का कहना है (या वास्तविक संख्या है कि अपने प्रपत्र/स्क्रीन में फिट बैठता है)

चरण 1: डेटाग्रिड व्यू के स्क्रॉलबार को अक्षम करें।

चरण 2: अपना स्वयं का स्क्रॉलबार जोड़ें।

चरण 3: अपने CellValueNeeded दिनचर्या में, e.RowIndex + scrollBar.Value का जवाब

चरण 4: Datastore का सवाल है, मैं वर्तमान में एक स्ट्रीम खोलने के लिए, और CellValueNeeded दिनचर्या में, पहले एक शोध करते हैं () और आवश्यक डेटा पढ़ें()।

इन चरणों के साथ, मुझे बहुत बड़ी फ़ाइलों (0.8 जीबी तक परीक्षण) के लिए डेटाग्रिड के माध्यम से बहुत उचित प्रदर्शन स्क्रॉलिंग मिलता है।

तो निष्कर्ष में, ऐसा लगता है कि मंदी का वास्तविक कारण यह तथ्य नहीं था कि हमने सीईसी() आईएनजी और रीड() आईएनजी रखा, लेकिन वास्तविक डेटा ग्रिडव्यू स्वयं ही रखा।

+0

यह सच है। एक टेक्स्टबॉक्स में एक ही डेटासेट प्रदर्शित करना (एक सहायता ओडी स्ट्रिंगबिल्डर (5000000) के साथ;))) लगभग 4 गुना तेज है। – TomeeNS

1

क्योंकि नेट नेट ओएस के शीर्ष पर स्तरित है, रनटाइम लोडिंग और डिस्क से डेटा तक डेटा के प्रबंधन को एक और दृष्टिकोण की आवश्यकता है। देखें क्यों और कैसे: http://www.codeproject.com/Articles/38069/Memory-Management-in-NET

0

इस समस्या से निपटने के लिए, मैं सुझाव दूंगा कि सभी डेटा एक बार में लोड न करें। इसके बजाय भाग में डेटा लोड करें और आवश्यकता होने पर सबसे प्रासंगिक डेटा प्रदर्शित करें। मैंने अभी एक त्वरित परीक्षण किया है और पाया है कि DataSourceDataGridView की संपत्ति एक अच्छी दृष्टिकोण है, लेकिन बड़ी संख्या में पंक्तियों में भी समय लगता है। इसलिए डेटा में लोड करने के लिए डेटाटेबल के Merge फ़ंक्शन का उपयोग करें और उपयोगकर्ता को सबसे प्रासंगिक डेटा दिखाएं। Here मैंने एक उदाहरण प्रदर्शित किया है जो आपकी मदद कर सकता है।

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