में Noda समय वी 2, हम nanosecond समाधान करने के लिए जा रहे हैं। इसका मतलब है कि हम अब उस समय की पूरी श्रृंखला का प्रतिनिधित्व करने के लिए एक 8-बाइट पूर्णांक का उपयोग नहीं कर सकते हैं जिसमें हम रुचि रखते हैं। इससे मुझे नोदा समय के (कई) संरूपों के स्मृति उपयोग की जांच करने के लिए प्रेरित किया गया है, जिसने मुझे प्रेरित किया है। सीएलआर के संरेखण निर्णय में थोड़ी विषमता को उजागर करने के लिए।
सबसे पहले, मुझे लगता है यह है कि है एक कार्यान्वयन निर्णय, और कहा कि डिफ़ॉल्ट व्यवहार को किसी भी समय बदल सकता है। मुझे लगता है कि मैं कर सकते हैं का उपयोग कर इसे संशोधित [StructLayout]
और [FieldOffset]
, लेकिन मेरे लिए एक समाधान है जो कि आवश्यकता नहीं किया था यदि संभव हो तो साथ आने चाहते हैं।
मेरा मुख्य परिदृश्य यह है कि मेरे पास एक struct
संदर्भ-प्रकार फ़ील्ड और दो अन्य मान-प्रकार फ़ील्ड हैं, जहाँ वे फ़ील्ड उनके लिए सरल आवरण हैं int
। मुझे उम्मीद थी कि 64-बिट सीएलआर (संदर्भ के लिए 8 और अन्य में से प्रत्येक के लिए 4) पर 16 बाइट्स के रूप में प्रतिनिधित्व किया जाएगा, लेकिन किसी कारण से यह 24 बाइट्स का उपयोग कर रहा है। मैं सरणियों का उपयोग करके अंतरिक्ष को माप रहा हूं, वैसे - मैं समझता हूं कि विभिन्न स्थितियों में लेआउट अलग-अलग हो सकता है, लेकिन यह एक उचित शुरुआती बिंदु की तरह लगा।
यहाँ एक नमूना कार्यक्रम इस मुद्दे को प्रदर्शित करता है:
using System;
using System.Runtime.InteropServices;
#pragma warning disable 0169
struct Int32Wrapper
{
int x;
}
struct TwoInt32s
{
int x, y;
}
struct TwoInt32Wrappers
{
Int32Wrapper x, y;
}
struct RefAndTwoInt32s
{
string text;
int x, y;
}
struct RefAndTwoInt32Wrappers
{
string text;
Int32Wrapper x, y;
}
class Test
{
static void Main()
{
Console.WriteLine("Environment: CLR {0} on {1} ({2})",
Environment.Version,
Environment.OSVersion,
Environment.Is64BitProcess ? "64 bit" : "32 bit");
ShowSize<Int32Wrapper>();
ShowSize<TwoInt32s>();
ShowSize<TwoInt32Wrappers>();
ShowSize<RefAndTwoInt32s>();
ShowSize<RefAndTwoInt32Wrappers>();
}
static void ShowSize<T>()
{
long before = GC.GetTotalMemory(true);
T[] array = new T[100000];
long after = GC.GetTotalMemory(true);
Console.WriteLine("{0}: {1}", typeof(T),
(after - before) / array.Length);
}
}
और मेरे लैपटॉप पर संकलन और आउटपुट:
c:\Users\Jon\Test>csc /debug- /o+ ShowMemory.cs
Microsoft (R) Visual C# Compiler version 12.0.30501.0
for C# 5
Copyright (C) Microsoft Corporation. All rights reserved.
c:\Users\Jon\Test>ShowMemory.exe
Environment: CLR 4.0.30319.34014 on Microsoft Windows NT 6.2.9200.0 (64 bit)
Int32Wrapper: 4
TwoInt32s: 8
TwoInt32Wrappers: 8
RefAndTwoInt32s: 16
RefAndTwoInt32Wrappers: 24
इसलिए:
- यदि आपके पास एक संदर्भ प्रकार फ़ील्ड नहीं है, तो CLR
Int32Wrapper
फ़ील्ड को एक साथ पैक करने में प्रसन्न है (TwoInt32Wrappers
जिसका आकार 8 है) - यहां तक कि एक संदर्भ प्रकार के क्षेत्र के साथ, सीएलआर अभी भी
int
खेतों को एक साथ पैक करने में प्रसन्न है (RefAndTwoInt32s
जिसका आकार 16 है) - दोनों को मिलाकर, प्रत्येक
Int32Wrapper
क्षेत्र 8 बाइट्स के लिए गद्देदार / संरेखित प्रतीत होता है। (RefAndTwoInt32Wrappers
24 का आकार है।) - डिबगर में समान कोड चलाना (लेकिन अभी भी रिलीज़ बिल्ड) 12 का आकार दिखाता है।
कुछ अन्य प्रयोगों के समान परिणाम मिले हैं:
- मान प्रकार फ़ील्ड के बाद संदर्भ प्रकार फ़ील्ड को रखने से मदद नहीं मिलती है
- मदद
object
करने के बजाय उपयोग करने सेstring
(मुझे उम्मीद है कि यह "किसी भी संदर्भ प्रकार") - संदर्भ के चारों ओर "रैपर" के रूप में एक और संरचना का उपयोग करने से मदद नहीं मिलती है
- संदर्भ के चारों ओर एक आवरण के रूप में एक सामान्य संरचना का उपयोग करना मदद नहीं करता है
- अगर मैं फ़ील्ड (सादगी के लिए जोड़े में) जोड़ता रहता हूं, तो
int
फ़ील्ड अभी भी 4 बाइट्स के लिए औरInt32Wrapper
8 बाइट्स के लिए फ़ील्ड्स की गणना करता है [StructLayout(LayoutKind.Sequential, Pack = 4)]
दृष्टि में हर संरचना को जोड़ने से परिणाम नहीं बदलते हैं
क्या किसी के पास इसके लिए कोई स्पष्टीकरण है (आदर्श रूप से संदर्भ प्रलेखन के साथ) या मैं सीएलआर को संकेत कैसे दे सकता हूं इसका एक सुझाव है कि मैं चाहूंगा कि खेतों को एक निरंतर क्षेत्र ऑफसेट निर्दिष्ट किए बिना पैक किया जाए ?
TwoInt32Wrappers
, तो दो या एक Int64
ए के साथ एक संरचना बनाते हैं क्या होता है TwoInt32Wrappers
? कैसे के बारे में अगर आप एक सामान्य Pair<T1,T2> {public T1 f1; public T2 f2;}
बनाने के लिए Pair<string,Pair<int,int>>
और फिर बनाने और Pair<string,Pair<Int32Wrapper,Int32Wrapper>>
? कौन सा संयोजन चीजों को पैड करने के लिए जेटर को मजबूर करता है?
Pair<string, TwoInt32Wrappers>
यह सिर्फ 16 बाइट्स देता है, ताकि समस्या का समाधान हो जाए। चित्त आकर्षण करनेवाला।
Marshal.SizeOf
मूल कोड को पारित किए जाने वाले ढांचे के आकार को वापस करेगा, जो .NET कोड में संरचना के आकार से कोई संबंध नहीं है।
Ref<T>
नहीं कर रहे हैं लेकिनstring
इसके बजाय उपयोग कर रहे हैं , ऐसा नहीं है कि यह एक फर्क करना चाहिए।