2012-05-28 38 views
10

मुझे एक भाषा कोड स्ट्रिंग को स्टोर करना होगा, जैसे "एन", जिसमें हमेशा 2 अक्षर होंगे।स्ट्रिंग और चार प्रकार मेमरी में .NET में संग्रहीत कैसे हैं?

क्या इस प्रकार को "स्ट्रिंग" या "चार" के रूप में परिभाषित करना बेहतर है?

private string languageCode; 

बनाम

private char[] languageCode; 

या कोई और, बेहतर विकल्प है?

इन 2 को स्मृति में कैसे संग्रहीत किया जाता है? मूल्यों को आवंटित किए जाने पर कितने बाइट्स या बिट्स आवंटित किए जाएंगे?

+5

क्या आपने वास्तव में स्वयं को साबित किया है कि यह अभी तक एक समस्या है? स्ट्रिंग्स का उपयोग करते समय मुझे स्मृति के बारे में चिंता करने की ज़रूरत बहुत ही कम है - खासकर ऐसे छोटे। यदि यह किसी समस्या के रूप में दिखाई नहीं दे रहा है तो इसके बारे में चिंता न करें जब तक कि यह न हो। यदि तार आपको स्मृति समस्या उत्पन्न कर रहे हैं तो यह बाद की तारीख में एक आसान फिक्स है। अन्यथा एक स्ट्रिंग का उपयोग करें और स्मृति समस्याओं के बारे में भी न सोचें। –

+0

मेरे पास एक बहुत ही गहन तर्क है जो हजारों में स्मृति को संग्रहीत करता है ताकि हर छोटी मदद मिल सके। –

+0

@ विलियम यदि प्रदर्शन महत्वपूर्ण है, तो क्यों न 'enum LanguageCode: short' घोषित करें और 2 बाइट्स सहेजें? –

उत्तर

8

वे कैसे जमा हो जाती है

दोनों string और char[] ढेर पर जमा हो जाती है - तो भंडारण में ही है। आंतरिक रूप से मुझे लगता है कि stringके लिए के लिए यह आपके लिए उपयोगी बनाने के लिए अतिरिक्त कोड का एक कवर है।

यदि आपके पास बहुत सारे दोहराव वाले तार हैं, तो आप उन तारों की स्मृति पदचिह्न को कम करने के लिए Interning का उपयोग कर सकते हैं।

बेहतर विकल्प

मैं स्ट्रिंग एहसान होगा - इसे तुरंत अधिक स्पष्ट क्या डेटा प्रकार है है और आप इसे उपयोग करने के लिए कैसे करना चाहते हैं। लोग तारों का उपयोग करने के लिए भी अधिक आदी हैं इसलिए रखरखाव भुगतना नहीं होगा। आपको अपने लिए किए गए सभी बॉयलरप्लेट कोड से भी बहुत फायदा होगा। माइक्रोसॉफ्ट ने यह भी सुनिश्चित करने के लिए बहुत प्रयास किए हैं कि string प्रकार एक प्रदर्शन हॉग नहीं है।

आबंटन आकार

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

Overhead of a .NET array?

वैकल्पिक

आपकी जानकारी केवल 20 भाषा कोड और देखते हैं कि के आधार पर प्रदर्शन, आप क्रम में आकार कोड का प्रतिनिधित्व करने के लिए आवश्यक कम करने के लिए अपनी खुद की enum की घोषणा कर सकता है कुंजी है:

enum LanguageCode : byte 
{ 
    en = 0, 
} 

यह केवल 1 बाइट के रूप में दो char के लिए 4 के लिए विरोध किया (एक सरणी में) ले जाएगा, लेकिन यह उपलब्ध नही की सीमा को सीमित करता है ई LanguageCodebyte की सीमा के मान - जो 20 वस्तुओं के लिए काफी बड़ा है।

आप sizeof() ऑपरेटर का उपयोग कर मूल्य प्रकारों का आकार देख सकते हैं: sizeof(LanguageCode)। Enums हुड के नीचे अंतर्निहित प्रकार के अलावा कुछ भी नहीं हैं, वे int पर डिफ़ॉल्ट हैं, लेकिन जैसा कि आप मेरे कोड नमूने में देख सकते हैं, आप इसे "विरासत" द्वारा एक नए प्रकार से बदल सकते हैं।

+0

आप स्पष्ट रूप से तारों में तारों को प्रशिक्षित नहीं करते हैं। नेट; वे आपके लिए केवल घोषणा के द्वारा निहित हैं। इसके अलावा, स्ट्रिंग्स और चार एरे नेट में बेहद अलग हैं। दिए गए हैं कि चार सरणी ढेर पर उत्परिवर्तनीय संरचनाएं हैं, या यहां तक ​​कि स्टैक भी है कि आपने उन्हें कैसे घोषित किया है, जबकि स्ट्रिंग अपरिवर्तनीय हैं और जैसा कि आपने नोट्स से लिंक किया है, निर्माण करें नियमित रूप से नेट फ्रेमवर्क मेमोरी के बजाय इंटर्न पूल में ऊपर और निर्माण और निर्माण करें - जिसका अर्थ है कि वे बहुत अपमानजनक हो सकते हैं। –

+0

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

+0

यह इस बात पर निर्भर करता है कि कोड कैसे लिखा जाता है - उदाहरण के लिए यदि यह कोड में घोषित स्ट्रिंग बिट्स का एक गुच्छा खोज रहा है, तो फिर भी आप आंतरिक तारों के समूह के साथ समाप्त हो जाते हैं। लेकिन महत्वपूर्ण प्रदर्शन चिंता ढेर पर अनावश्यक मध्यस्थ तारों का एक टन फेंक रही है जब आपको पता है कि आपको उनकी आवश्यकता नहीं है - एक सिंगल चार सरणी हमेशा बहुत सस्ता मेमोरी-वार होने जा रही है, और यदि आप अपना कोड इसी तरह लिखते हैं Regex के आंतरिक, सस्ता CPU-wise। नेट में इस्तेमाल किए गए कम मेम का अर्थ है कम जीसी भी, जिसमें एक और सीपीयू लाभ है। –

0

आप ठीक 2 वर्ण संग्रहीत करना चाहते हैं, और यह सबसे अधिक कुशलता से करते हैं, तो एक struct का उपयोग करें:

struct Char2 
{ 
public char C1, C2; 
} 

इस struct का उपयोग आम तौर पर नई ढेर आवंटन पैदा नहीं होगी। यह केवल मौजूदा ऑब्जेक्ट को अपनाना होगा (न्यूनतम संभव राशि से) या स्टैक स्पेस का उपभोग करें जो बहुत सस्ता है।

+0

हीप आवंटन पूरी तरह से * जहां * आप संरचना घोषित करते हैं, पर निर्भर करेगा। विधियों/गुणों के भीतर घोषित होने पर यह केवल स्टैक पर होगा। कक्षाओं के अंदर यह वर्ग के बाकी सदस्यों के साथ ढेर में होगा। –

+0

यह * * नया * आवंटन नहीं करेगा। यह केवल एक मौजूदा वस्तु (न्यूनतम संभव राशि से) को अपग्रेड करेगा। – usr

+0

हां सच है, लेकिन ढेर आवंटन आमतौर पर बहुत तेज़ होते हैं और शुरुआत में चिंतित नहीं होना चाहिए। उस ने कहा, 'संरचना LanguageCode' की एक संरचना एक अच्छा विकल्प है। –

4

लघु जवाब: उपयोग स्ट्रिंग

लांग जवाब:

private string languageCode; 

AFAIK तार वर्ण की लंबाई के उपसर्ग सरणी के रूप में जमा हो जाती है। इस कच्ची सरणी को बनाए रखने के लिए एक स्ट्रिंग ऑब्जेक्ट को ढेर पर तुरंत चालू किया जाता है। लेकिन स्ट्रिंग ऑब्जेक्ट एक सरल सरणी यह ​​तुलना जैसी बुनियादी स्ट्रिंग आपरेशन में सक्षम बनाता है की तुलना में अधिक है, संयोजन, निष्कर्षण सबस्ट्रिंग, आदि खोज

private char[] languageCode; 

वर्ण की एक सरणी के रूप में संग्रहीत किया जाएगा

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

लेकिन ओटीओएच आप इस चार सरणी पर स्ट्रिंग ऑपरेशंस करने की क्षमता खो देते हैं। स्ट्रिंग तुलना जैसे ऑपरेशन अब भी बोझिल हो जाते हैं। इतनी लंबी कहानी एक स्ट्रिंग का उपयोग कम करें!

1

इन 2 को स्मृति में कैसे संग्रहीत किया जाता है? मूल्यों को आवंटित किए जाने पर कितने बाइट्स या बिट्स आवंटित किए जाएंगे? .NET में

हर उदाहरण इस प्रकार संग्रहीत किया जाता है: प्रकार पहचानकर्ता के लिए एक IntPtr आकार के क्षेत्र; उदाहरण पर लॉक करने के लिए एक और; शेष उदाहरण फ़ील्ड डेटा IntPtr-आकार की राशि तक गोल है। इसलिए, 32-बिट प्लेटफार्म पर प्रत्येक उदाहरण 8 बाइट्स + फ़ील्ड डेटा पर कब्जा करता है।

यह string और char[] दोनों पर लागू होता है। इनमें से दोनों डेटा की लंबाई को इंटिप्ट-साइज्ड इंटीजर के रूप में भी संग्रहीत करते हैं, इसके बाद वास्तविक डेटा भी होता है। इस प्रकार, 32-बिट प्लेटफॉर्म पर दो-वर्ण string और दो-वर्ण char[], 8 + 4 + 4 = 16 बाइट्स पर कब्जा करेंगे।

सटीक दो वर्णों को संग्रहीत करते समय इसे कम करने का एकमात्र तरीका वास्तविक वर्ण, या किसी फ़ील्ड या सरणी में वर्णों वाली संरचना को संग्रहीत करना है। इन सभी पात्रों के लिए केवल 4 बाइट का उपभोग होगा:

// Option 1 
class MyClass 
{ 
    char Char1, Char2; 
} 

// Option 2 
class MyClass 
{ 
    CharStruct chars; 
} 
... 
struct CharStruct { public char Char1; public char Char2; } 

MyClass उदाहरण प्रति 8 बाइट (32-बिट मशीन पर) प्लस वर्ण के लिए 4 बाइट का उपयोग कर खत्म हो जाएगा।

// Option 3 
class MyClass 
{ 
    CharStruct[] chars; 
} 

यह MyClass भूमि के ऊपर के लिए 8 बाइट्स, प्लस charsसंदर्भ के लिए 4 बाइट, प्लस सरणी के भूमि के ऊपर के लिए 12 बाइट्स, प्लस सरणी में CharStruct प्रति 4 बाइट का उपयोग करेगा।

+0

दिलचस्प। यद्यपि आपको यह जानकारी कहां से मिली? – kristianp

+1

@ क्रिस्टियनप इस जानकारी में से अधिकांश इस एमएसडीएन आलेख से आता है: https://msdn.microsoft.com/en-us/magazine/cc163791.aspx (चित्र 6 पर नीचे स्क्रॉल करें) –

0

स्ट्रिंग्स में वास्तव में एक पॉइंटर लंबाई का आकार ओवरहेड होता है, यानी 32 बिट प्रक्रिया के लिए 4 बाइट्स, 64 बिट प्रक्रिया के लिए 8 बाइट्स। लेकिन फिर फिर, स्ट्रिंग चार सरणी की तुलना में बदले में बहुत अधिक ऑफर करते हैं।

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