`Stackalloc` কীওয়ার্ডের ব্যবহারিক ব্যবহার


134

stackallocসি # তে প্রোগ্রাম করার সময় কেউ কি আসলে ব্যবহার করেছে ? আমি কী করছি তা সম্পর্কে সচেতন, তবে এটি কেবলমাত্র আমার কোডটিতে প্রদর্শিত হয় দুর্ঘটনাক্রমে, কারণ আমি যখন টাইপ করা শুরু করি তখন ইন্টেলিসেন্স এটিকে পরামর্শ দেয় static

যদিও এটির ব্যবহারের দৃশ্যের সাথে সম্পর্কিত নয় stackalloc, আমি আসলে আমার অ্যাপ্লিকেশনগুলিতে প্রচুর পরিমাণে লিগ্যাসি ইন্টারপ করি, তাই এখনই এবং পরে আমি unsafeকোড ব্যবহার করে অবলম্বন করতে পারি । তবে তবুও আমি সাধারণত unsafeসম্পূর্ণরূপে এড়ানোর উপায়গুলি খুঁজে পাই ।

এবং যেহেতু একক থ্রেডের জন্য স্ট্যাক আকার N নেট ~ 1Mb (আমি ভুল হলে আমাকে সংশোধন করুন), তাই আমি ব্যবহার থেকে আরও বেশি সংরক্ষিত stackalloc

এমন কিছু ব্যবহারিক কেস রয়েছে যেখানে কেউ বলতে পারেন: "আমার পক্ষে অনিরাপদ হয়ে ব্যবহার এবং ব্যবহারের জন্য এটি সঠিক পরিমাণের ডেটা এবং প্রক্রিয়াজাতকরণ stackalloc"?


5
ঠিক যে খেয়াল System.Numbersব্যবহারসমূহ এটি একটি অনেক referencesource.microsoft.com/#mscorlib/system/...
Slai

উত্তর:


150

ব্যবহারের একমাত্র কারণ stackallocহ'ল পারফরম্যান্স (হয় গণনা বা আন্তঃবিদ্যুতের জন্য)। ব্যবহারের stackallocএক গাদা বরাদ্দ অ্যারের পরিবর্তে, আপনি কম জিসি চাপ তৈরি করতে, একটি এটি স্বয়ংক্রিয়ভাবে পদ্ধতির উপর মুক্ত হয় (জিসি কম চালানোর জন্য প্রয়োজন), আপনি নিচে অ্যারে পিন প্রয়োজন হবে না, এটি দ্রুত এক গাদা অ্যারের তুলনায় বরাদ্দ করা আছে, প্রস্থান করুন (জিসি চলাকালীন গাদা বরাদ্দ হওয়া অ্যারেগুলি কেবল হ্রাস করা হয়)। এছাড়াও ব্যবহার করে stackallocপরিবর্তে একটি নেটিভ বরাদ্দকরণ (যদি malloc বা .net সমতুল্য মত) আপনার কাছে সুযোগ প্রস্থানে গতি এবং স্বয়ংক্রিয় deallocation লাভ করে।

পারফরম্যান্স ওয়াইস, আপনি যদি ব্যবহার stackallocকরেন তবে ডেটা স্থানীয়তার কারণে সিপিইউতে ক্যাশের হিট হওয়ার সম্ভাবনা অনেক বেড়ে যায়।


26
উপাত্তের লোকেশন, ভালো পয়েন্ট! আপনি বেশ কয়েকটি স্ট্রাকচার বা অ্যারে বরাদ্দ করতে চাইলে পরিচালিত মেমরিটি খুব কমই অর্জন করবে। ধন্যবাদ!
গ্রু

22
ব্যবস্থাপনিত অবজেক্টের চেয়ে গাদা বরাদ্দগুলি সাধারণত পরিচালিত অবজেক্টের চেয়ে দ্রুত হয় কারণ অতিক্রম করার কোনও মুক্ত তালিকা নেই; সিএলআর কেবল হ্যাপ পয়েন্টারকে বাড়িয়ে তোলে। লোকাল হিসাবে, ক্রম বরাদ্দগুলি হিপ কমপ্যাক্টের কারণে দীর্ঘ চলমান পরিচালিত প্রক্রিয়াগুলির জন্য সমষ্টিযুক্ত হওয়ার সম্ভাবনা বেশি থাকে।
শেয়া

1
"একটি হিপ অ্যারের তুলনায় এটি বরাদ্দ করা দ্রুত" কেন এটি? শুধু লোকেশন? যেভাবেই এটি কেবল পয়েন্টার-বাম্প, না?
সর্বাধিক ব্যারাক্লফ

2
@ ম্যাক্সবারাক্লফ কারণ আপনি আবেদনের আজীবন বরাদ্দকে জিসি ব্যয় যোগ করেছেন। মোট বরাদ্দ ব্যয় = বরাদ্দ + অবনতি, এক্ষেত্রে পয়েন্টার বাম্প + জিসি হিপ, বনাম পয়েন্টার বাম্প + পয়েন্টার হ্রাস স্ট্যাক
পপ ক্যাটালিন

35

আমি রিয়েলটাইম ডিএসপি কাজের জন্য [কাছাকাছি] বাফার বরাদ্দ করতে স্ট্যাক্যালোক ব্যবহার করেছি। এটি একটি খুব নির্দিষ্ট ক্ষেত্রে যেখানে পারফরম্যান্সের যথাসম্ভব ধারাবাহিক হওয়া দরকার। নোট করুন ধারাবাহিকতা এবং সামগ্রিক থ্রুপুট মধ্যে পার্থক্য আছে - এই ক্ষেত্রে আমি গাদা বরাদ্দ খুব ধীর হওয়ার সাথে উদ্বিগ্ন ছিলাম না, কেবলমাত্র প্রোগ্রামের সেই মুহুর্তে আবর্জনা সংগ্রহের অ-নির্ধারণীকরণের সাথে। আমি এটি 99% ক্ষেত্রে ব্যবহার করব না।


25

stackallocঅনিরাপদ কোডের জন্য কেবল প্রাসঙ্গিক। পরিচালিত কোডের জন্য আপনি সিদ্ধান্ত নিতে পারবেন না কোথায় ডেটা বরাদ্দ করা যায়। ডিফল্ট প্রতি স্ট্যাকের উপর মান ধরণের বরাদ্দ করা হয় (যদি না তারা কোনও রেফারেন্স ধরণের অংশ হয়, তবে সে ক্ষেত্রে এগুলি গাদাতে বরাদ্দ দেওয়া হয়)। রেফারেন্সের ধরণগুলি গাদাতে বরাদ্দ করা হয়।

প্লেইন ভ্যানিলা। নেট অ্যাপ্লিকেশনটির জন্য ডিফল্ট স্ট্যাকের আকার 1 এমবি, তবে আপনি এটি পিই শিরোলেখগুলিতে পরিবর্তন করতে পারেন। আপনি যদি সুস্পষ্টভাবে থ্রেডগুলি শুরু করছেন, আপনি কনস্ট্রাক্টর ওভারলোডের মাধ্যমেও একটি ভিন্ন আকার নির্ধারণ করতে পারেন। এএসপি.এনইটি অ্যাপ্লিকেশনগুলির জন্য ডিফল্ট স্ট্যাকের আকারটি কেবল 256 কে, যা আপনি যদি দুটি পরিবেশের মধ্যে স্যুইচ করছেন তবে মনে রাখা উচিত।


ভিজ্যুয়াল স্টুডিও থেকে ডিফল্ট স্ট্যাকের আকারটি পরিবর্তন করা সম্ভব?
কনফিগারকারী

@ কনফিগুয়েটর: যতটা আমি সচেতন না
ব্রায়ান রাসমুসেন

17

স্প্যানগুলির স্ট্যাক্যালোক সূচনা। সি # এর পূর্ববর্তী সংস্করণগুলিতে স্ট্যাক্যালোকের ফলাফল কেবল পয়েন্টার স্থানীয় ভেরিয়েবলে সংরক্ষণ করা যেতে পারে। সি # .2.২ অনুসারে, স্ট্যাক্যালোক এখন একটি অভিব্যক্তির অংশ হিসাবে ব্যবহার করা যেতে পারে এবং একটি স্প্যানকে লক্ষ্যবস্তু করতে পারে এবং এটি অনিরাপদ কীওয়ার্ড ব্যবহার না করেই করা যেতে পারে। এভাবে লেখার বদলে

Span<byte> bytes;
unsafe
{
  byte* tmp = stackalloc byte[length];
  bytes = new Span<byte>(tmp, length);
}

আপনি সহজভাবে লিখতে পারেন:

Span<byte> bytes = stackalloc byte[length];

অপারেশন করার জন্য আপনার কিছু স্ক্র্যাচ স্পেস প্রয়োজন এমন পরিস্থিতিতেও এটি অত্যন্ত কার্যকর, তবে অপেক্ষাকৃত ছোট আকারের জন্য হ্যাপ মেমরি বরাদ্দ এড়াতে চান

Span<byte> bytes = length <= 128 ? stackalloc byte[length] : new byte[length];
... // Code that operates on the Span<byte>

উত্স: সি # - স্প্যান সম্পর্কে সমস্ত: একটি নতুন। নেট মূল ভিত্তি অন্বেষণ


4
বখশিশের জন্য ধন্যবাদ. দেখে মনে হচ্ছে যে সি # এর প্রতিটি নতুন সংস্করণ সি ++ এর থেকে কিছুটা কাছাকাছি চলে গেছে যা আসলে একটি ভাল জিনিস আইএমএইচও।
গ্রু

1
যেমনটি এখানে এবং এখানে দেখা যায় , Spanহায়। NET ফ্রেমওয়ার্ক ৪.7.২ এবং এমনকি ৪.৮ এও পাওয়া যায় না ... সুতরাং সেই নতুন ভাষার বৈশিষ্ট্যটি এখনও এই মুহুর্তের জন্য সীমিত ব্যবহারের নয়।
ফ্রেডেরিক

2

এই প্রশ্নে কিছু দুর্দান্ত উত্তর রয়েছে তবে আমি এটি উল্লেখ করতে চাই

স্ট্যাক্যালোককে দেশীয় এপিআইগুলিতে কল করতেও ব্যবহৃত হতে পারে

অনেক নেটিভ ফাংশনগুলির জন্য রিটার্নের ফলাফল পেতে কলারকে একটি বাফার বরাদ্দ করা প্রয়োজন। উদাহরণস্বরূপ, সিএফগেটপ্লেসোল্ডারআইএনফো ফাংশনে cfapi.hনিম্নলিখিত স্বাক্ষর রয়েছে।

HRESULT CfGetPlaceholderInfo(
HANDLE                    FileHandle,
CF_PLACEHOLDER_INFO_CLASS InfoClass,
PVOID                     InfoBuffer,
DWORD                     InfoBufferLength,
PDWORD                    ReturnedLength);

এটিকে আন্তঃরাজ্যের মাধ্যমে সি # তে কল করার জন্য,

[DllImport("Cfapi.dll")]
public static unsafe extern HResult CfGetPlaceholderInfo(IntPtr fileHandle, uint infoClass, void* infoBuffer, uint infoBufferLength, out uint returnedLength);

আপনি স্ট্যাক্যালোক ব্যবহার করতে পারেন।

byte* buffer = stackalloc byte[1024];
CfGetPlaceholderInfo(fileHandle, 0, buffer, 1024, out var returnedLength);
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.