যা দ্রুত: স্ট্যাক বরাদ্দ বা হিপ বরাদ্দ


503

এই প্রশ্নটি মোটামুটি প্রাথমিক শোনায়, তবে আমি কাজ করছি এমন অন্য বিকাশকারীর সাথে আমার এই বিতর্ক।

আমি জমিগুলি বরাদ্দ করার পরিবর্তে যেখানে বরাদ্দ করতে পারি সেখানে স্ট্যাক করার যত্ন নিচ্ছিলাম। তিনি আমার সাথে কথা বলছিলেন এবং আমার কাঁধে নজর রাখছিলেন এবং মন্তব্য করেছিলেন যে এটি প্রয়োজনীয় ছিল না কারণ তারা একই পারফরম্যান্স বুদ্ধিমান।

আমি সবসময় এই ছাপের মধ্যে ছিলাম যে স্ট্যাকের বর্ধন করা ধ্রুবক সময় ছিল, এবং হ্যাপ বরাদ্দের কার্যকারিতা উভয় বরাদ্দ (সঠিক আকারের একটি গর্ত সন্ধান করা) এবং ডি-বরাদ্দকরণের জন্য খণ্ডের বর্তমান জটিলতার উপর নির্ভর করে যেমন খণ্ডগুলি হ্রাস করার জন্য গর্তগুলি ভেঙে দেয়, অনেক স্ট্যান্ডার্ড গ্রন্থাগার প্রয়োগগুলি মুছে ফেলার সময় এটি করতে সময় নেয় যদি আমার ভুল হয় না)।

এটি আমাকে এমন কিছু হিসাবে আঘাত করে যা সম্ভবত খুব সংকলন নির্ভরশীল হতে পারে। এই প্রকল্পের জন্য বিশেষত আমি পিপিসি আর্কিটেকচারের জন্য একটি মেট্রোওয়ারকস সংকলক ব্যবহার করছি । এই সংমিশ্রণের উপর অন্তর্দৃষ্টি সবচেয়ে সহায়ক হবে, তবে সাধারণভাবে, জিসিসি এবং এমএসভিসি ++ এর ক্ষেত্রে কী? গাদা বরাদ্দ কি স্ট্যাক বরাদ্দের মতো উচ্চ কার্যকারিতা নয়? কোন পার্থক্য আছে? অথবা পার্থক্যগুলি এত মিনিটে এটি অর্থহীন মাইক্রো-অপ্টিমাইজেশনে পরিণত হয়।


11
আমি জানি এটি বেশ প্রাচীন, তবে কিছু সি / সি ++ স্নিপেটগুলি বিভিন্ন ধরণের বরাদ্দের প্রদর্শন করে দেখে ভাল লাগবে।
জোসেফ ওয়েইসমান

42
আপনার গরুর বাচ্চা মারাত্মকভাবে অজ্ঞ যত দ্রুত সম্ভব আপনার দল থেকে এই ধরনের লোকদের এক্সাইজ করুন।
জিম বাল্টার

5
মনে রাখবেন যে গাদাটি সাধারণত স্ট্যাকের চেয়ে অনেক বড়। যদি আপনাকে প্রচুর পরিমাণে ডেটা বরাদ্দ করা হয় তবে আপনাকে এটিকে সত্যিই গাদাতে হবে, অন্যথায় ওএস থেকে স্ট্যাকের আকার পরিবর্তন করতে হবে।
পল ড্রপার

1
সমস্ত অপ্টিমাইজেশানগুলি হ'ল যদি না আপনার কাছে বেঞ্চমার্ক বা জটিলতার তর্কগুলি অন্যথায় প্রমাণিত হয়, ডিফল্ট অর্থহীন অণু-অপ্টিমাইজেশান দ্বারা।
বিজন লিন্ডকভিস্ট

2
আমি ভাবছি আপনার সহকর্মীর বেশিরভাগ জাভা বা সি # অভিজ্ঞতা আছে কিনা। এই ভাষাগুলিতে, প্রায় সমস্ত কিছুই হুডের নীচে apেকে রাখা হয়, যা এই জাতীয় অনুমানের দিকে নিয়ে যেতে পারে।
কর্ন অ্যাম্মন

উত্তর:


493

স্ট্যাক বরাদ্দ অনেক দ্রুত যেহেতু এটি যা যা করে তা স্ট্যাক পয়েন্টারটিকে সরিয়ে দেয়। মেমরি পুল ব্যবহার করে, আপনি গাদা বরাদ্দের তুলনায় তুলনামূলক কর্মক্ষমতা পেতে পারেন, তবে এটি সামান্য যুক্ত জটিলতা এবং তার নিজস্ব মাথা ব্যথার সাথে আসে।

এছাড়াও, স্ট্যাক বনাম হিপ কেবল একটি কার্যকারিতা বিবেচনা নয়; এটি আপনাকে প্রত্যাশিত আয়ুগুলির জীবনকাল সম্পর্কেও অনেক কিছু জানায়।


211
এবং আরও গুরুত্বপূর্ণ, স্ট্যাক সর্বদা গরম থাকে, আপনি যে স্মৃতি পেয়েছেন তা কোনও অতিরিক্ত গাদা বরাদ্দ মেমরির তুলনায় ক্যাশে থাকার সম্ভাবনা অনেক বেশি
বেনোইট

47
কিছু (বেশিরভাগ এম্বেড করা, আমি জানি যে) স্থাপত্যগুলিতে স্ট্যাক দ্রুত অন ডাই মেমরিতে সঞ্চয় করা যেতে পারে (যেমন এসআরএএম)। এটি একটি বিশাল পার্থক্য করতে পারে!
লিয়েন্ডার

38
কারণ স্ট্যাকটি আসলে একটি স্ট্যাক। স্ট্যাকটি ব্যবহার না করা অবধি আপনি মেমরির একটি অংশ মুক্ত করতে পারবেন না যদি না এটির উপরে না থাকে। কোনও পরিচালনা নেই, আপনি এতে চাপ দিন বা পপ করুন। অন্যদিকে, হিপ মেমরি পরিচালনা করা হয়: এটি মেমরি খণ্ডগুলির জন্য কার্নেলকে জিজ্ঞাসা করে, সম্ভবত এগুলিকে বিভক্ত করে, সেগুলিকে একত্রিত করে, পুনরায় ব্যবহার করে এবং তাদের মুক্তি দেয়। স্ট্যাকটি আসলে দ্রুত এবং সংক্ষিপ্ত বরাদ্দের জন্য বোঝানো হয়।
বেনোট

24
@ পেসারিয়ার কারণ স্ট্যাকটি হিপ থেকে অনেক ছোট। আপনি যদি বড় অ্যারে বরাদ্দ করতে চান তবে আপনি সেগুলি আরও ভালভাবে বরাদ্দ করুন। আপনি যদি স্টাকে একটি বড় অ্যারে বরাদ্দ করার চেষ্টা করেন এটি আপনাকে একটি স্ট্যাক ওভারফ্লো দেয়। সি ++ এ উদাহরণস্বরূপ চেষ্টা করুন: int টি [100000000]; উদাহরণস্বরূপ চেষ্টা করুন টি [10000000] = 10; এবং তারপরে << t [10000000]; এটি আপনাকে একটি স্ট্যাকের ওভারফ্লো দিতে হবে বা কেবল কাজ করবে না এবং আপনাকে কিছু দেখায় না। তবে আপনি যদি স্তূপে অ্যারের বরাদ্দ করেন: int * t = new int [100000000]; এবং পরে একই ক্রিয়াকলাপগুলি করুন, এটি কাজ করবে কারণ গাদা এত বড় অ্যারের জন্য প্রয়োজনীয় আকার রয়েছে has
লিলিয়ান এ। মোরারো

7
সবচেয়ে বড় কারণ @Pacerier যে স্ট্যাক বস্তু ব্লক তারা বরাদ্দ থেকে প্রস্থান উপর সুযোগ বাইরে যেতে হয়।
জিম Balter

166

স্ট্যাক অনেক দ্রুত। এটি আক্ষরিক অর্থে বেশিরভাগ আর্কিটেকচারে একক নির্দেশনা ব্যবহার করে, বেশিরভাগ ক্ষেত্রে যেমন x86 তে:

sub esp, 0x10

(এটি স্ট্যাক পয়েন্টারটিকে 0x10 বাইট দ্বারা নীচে সরিয়ে দেয় এবং এর সাহায্যে ভেরিয়েবল দ্বারা ব্যবহারের জন্য সেই বাইটগুলি "বরাদ্দ" দেয়))

অবশ্যই, স্ট্যাকের আকারটি অত্যন্ত সীমাবদ্ধ, আপনি খুব শীঘ্রই খুঁজে পাবেন যে আপনি স্ট্যাক বরাদ্দের অতিরিক্ত ব্যবহার করেছেন বা পুনরাবৃত্তি করার চেষ্টা করছেন :-)

এছাড়াও, কোডটির পারফরম্যান্সের অনুকূলিতকরণের খুব কম কারণ আছে যা যাচাই করে এটির প্রয়োজন হয় না, যেমন প্রোফাইলিং দ্বারা প্রদর্শিত। "অকাল অপ্টিমাইজেশন" প্রায়শই এটির মূল্য ব্যয় করে বেশি সমস্যার কারণ হয়।

আমার থাম্বের নিয়ম: যদি আমি জানি যে সংকলন সময়ে আমার কিছু ডেটা দরকার , এবং এটি কয়েকশ বাইটের আকারের অধীনে, আমি এটি স্ট্যাক-বরাদ্দ করি। অন্যথায় আমি এটি গাদা-বরাদ্দ।


20
একটি নির্দেশনা এবং তা সাধারণত স্ট্যাকের সমস্ত বস্তু দ্বারা ভাগ করা হয়।
MSalters

9
পয়েন্টটি ভাল করে তৈরি করেছেন, বিশেষত এটি যাচাইয়ের জন্য প্রয়োজনীয় বিন্দু। পারফরম্যান্স সম্পর্কে মানুষের উদ্বেগ কীভাবে স্থানান্তরিত হয় তা সম্পর্কে আমি ক্রমাগত অবাক হয়েছি।
মাইক ডুনলাভে

6
"ডিলোকেশন" খুব সহজ এবং একক leaveনির্দেশ দিয়ে সম্পন্ন হয় ।
ডক 21

15
এখানে "লুকানো" ব্যয়টি মনে রাখবেন, বিশেষত প্রথমবার যখন আপনি স্ট্যাকটি প্রসারিত করবেন। এটি করার ফলে পৃষ্ঠার ত্রুটি হতে পারে, কার্নেলের সাথে প্রসঙ্গের স্যুইচ করা যেতে পারে যা মেমরি বরাদ্দ করতে কিছু কাজ করতে হবে (বা এটিকে স্বাপ থেকে লোড করুন, সবচেয়ে খারাপ ক্ষেত্রে)।
টি

2
কিছু ক্ষেত্রে, আপনি 0 টি নির্দেশাবলী সহ এটি বরাদ্দ করতে পারেন। কতগুলি বাইট বরাদ্দ করা উচিত সে সম্পর্কে যদি কিছু তথ্য জানা থাকে তবে সংকলকটি একই সাথে এটি অন্যান্য স্ট্যাক ভেরিয়েবলগুলি বরাদ্দ করে একই সাথে অগ্রিম বরাদ্দ করতে পারে। এই ক্ষেত্রে, আপনি কিছু দিতে হবে না!
আম্মনকে

120

সত্যি বলতে, পারফরম্যান্সের তুলনা করার জন্য একটি প্রোগ্রাম লিখতে এটি তুচ্ছ:

#include <ctime>
#include <iostream>

namespace {
    class empty { }; // even empty classes take up 1 byte of space, minimum
}

int main()
{
    std::clock_t start = std::clock();
    for (int i = 0; i < 100000; ++i)
        empty e;
    std::clock_t duration = std::clock() - start;
    std::cout << "stack allocation took " << duration << " clock ticks\n";
    start = std::clock();
    for (int i = 0; i < 100000; ++i) {
        empty* e = new empty;
        delete e;
    };
    duration = std::clock() - start;
    std::cout << "heap allocation took " << duration << " clock ticks\n";
}

এটি বলা হয় যে একটি মূর্খ ধারাবাহিকতা হ'ল অল্প মনের হাবগোব্লিন । স্পষ্টতই সংকলককে অপ্টিমাইজ করা হ'ল অনেক প্রোগ্রামারদের মনের হবগব্লিন। এই আলোচনাটি উত্তরের নীচে থাকত, তবে লোকেরা সম্ভবত এতদূর পড়তে বিরক্ত হতে পারে না, তাই আমি ইতিমধ্যে উত্তর দিয়েছি এমন প্রশ্নগুলি এড়াতে আমি এটিকে এখানে নিয়ে যাচ্ছি।

একটি অনুকূলিতকরণ সংকলক লক্ষ্য করতে পারে যে এই কোডটি কিছু করে না, এবং এটি সবদূরই অনুকূলিত করতে পারে। এ জাতীয় জিনিস করা অপ্টিমাইজারের কাজ এবং অপটিমাইজারের সাথে লড়াই করা বোকামির কাজ।

আমি এই কোডটি অপ্টিমাইজেশন বন্ধ করে সংকলন করার পরামর্শ দেব কারণ বর্তমানে ব্যবহৃত প্রতিটি অপ্টিমাইজারকে বোকা বানানোর কোনও ভাল উপায় নেই বা ভবিষ্যতে এটি কার্যকর হবে।

যে কেউ এই অপ্টিমাইজারটি চালু করে এবং তারপরে লড়াইয়ের বিষয়ে অভিযোগ করে সে জনসাধারণের উপহাসের বিষয় হওয়া উচিত।

আমি যদি ন্যানোসেকেন্ডের নির্ভুলতার বিষয়ে যত্নশীল থাকি তবে আমি ব্যবহার করব না std::clock()। আমি যদি ডক্টরাল থিসিস হিসাবে ফলাফলগুলি প্রকাশ করতে চাইতাম তবে আমি এ সম্পর্কে আরও বড় চুক্তি করতাম এবং আমি সম্ভবত জিসিসি, তেন্দ্র / টেন 15, এলএলভিএম, ওয়াটকম, বোরল্যান্ড, ভিজ্যুয়াল সি ++, ডিজিটাল মঙ্গল, আইসিসি এবং অন্যান্য সংকলককে তুলনা করতাম। যেমনটি হ'ল, গাদা বরাদ্দ স্ট্যাক বরাদ্দের চেয়ে কয়েকগুণ বেশি সময় নেয় এবং আমি আর কোনও প্রশ্ন তদন্ত করার জন্য দরকারী কিছু দেখতে পাচ্ছি না।

অপটিমাইজারের কোডটি যা আমি পরীক্ষা করছি তা থেকে মুক্তি পাওয়ার জন্য একটি মিশন রয়েছে। অপ্টিমাইজারটি চালানোর জন্য বলার এবং তারপরে অপ্টিমাইজারটিকে বাস্তবে অপ্টিমাইজ না করার জন্য বোকা দেওয়ার চেষ্টা করার কোনও কারণ আমি দেখছি না। তবে আমি যদি এটির মূল্য দেখি তবে আমি নীচের একটি বা আরও কিছু করব:

  1. এতে একটি ডেটা সদস্য যুক্ত করুন emptyএবং লুপটিতে সেই ডেটা সদস্যকে অ্যাক্সেস করুন; তবে আমি যদি কেবল কখনও ডেটা সদস্যের কাছ থেকে পড়ি তবে অপ্টিমাইজার ধ্রুবক ভাঁজ করতে এবং লুপটি সরাতে পারে; আমি যদি কেবল ডেটা মেম্বারকে কেবল লিখি তবে অপটিমাইজার লুপের একেবারে শেষ পুনরাবৃত্তি বাদে সমস্ত কিছু এড়িয়ে যেতে পারে। অতিরিক্তভাবে, প্রশ্নটি "স্ট্যাক বরাদ্দ এবং ডেটা অ্যাক্সেস বনাম হিপ বরাদ্দ এবং ডেটা অ্যাক্সেস নয়।"

  2. ঘোষণা করুন e volatile, তবে volatileপ্রায়শই ভুলভাবে সংকলিত হয় (পিডিএফ)।

  3. eলুপের ভিতরে ঠিকানাটি নিন (এবং সম্ভবত এটি কোনও ভেরিয়েবলের জন্য externনির্ধারণ করুন যা অন্য কোনও ফাইলে ঘোষিত ও সংজ্ঞায়িত করা হয়েছে)। তবে এই ক্ষেত্রেও, সংকলকটি লক্ষ্য করতে পারে - কমপক্ষে স্ট্যাকের ক্ষেত্রে - eসর্বদা একই মেমরি ঠিকানায় বরাদ্দ করা হবে এবং তারপরে উপরের (1) এর মতো ধ্রুবক ভাঁজ করা হবে। আমি লুপের সমস্ত পুনরাবৃত্তি পাই, তবে বস্তুটি কখনই বরাদ্দ হয় না।

স্পষ্টতই, এই পরীক্ষাটি ত্রুটিযুক্ত যে এটি বরাদ্দ এবং অবনতি উভয়ই পরিমাপ করে এবং মূল প্রশ্নটি বিলম্বকরণ সম্পর্কে জিজ্ঞাসা করে না। অবশ্যই স্ট্যাকের জন্য বরাদ্দকৃত ভেরিয়েবলগুলি তাদের সুযোগের শেষে স্বয়ংক্রিয়ভাবে ডিলোক্যাট হয়ে যায়, সুতরাং কলিং deleteনা করে (1) নম্বরগুলি স্কিউ করা হবে না (স্ট্যাক ডিএলোকেশনটি স্ট্যাক বরাদ্দের বিষয়ে সংখ্যার সাথে অন্তর্ভুক্ত করা হয়েছে, সুতরাং এটি হিপ ডিএলোকেশন পরিমাপ করা কেবল ন্যায্য) এবং ( ২) নতুন পয়েন্টারের কোনও রেফারেন্স না রাখলে এবং deleteআমাদের সময় পরিমাপ করার পরে ফোন না করা পর্যন্ত একটি খুব খারাপ মেমরি ফাঁসের কারণ ঘটায় ।

আমার মেশিনে, উইন্ডোজে জি ++ ৩.৪.৪ ব্যবহার করে, আমি ১০০০০০ এর চেয়ে কম বরাদ্দের জন্য স্ট্যাক এবং হিপ উভয় বরাদ্দ উভয়ের জন্যই "0 ক্লক টিক্স" পেয়েছি এবং তারপরেও আমি স্ট্যাক বরাদ্দের জন্য "0 ক্লক টিকস" এবং "15 ক্লক টিক্স" পেয়েছি "গাদা বরাদ্দের জন্য। আমি যখন 10,000,000 বরাদ্দ পরিমাপ করি তখন স্ট্যাক বরাদ্দে 31 টি ঘড়ি টিক লাগে এবং গাদা বরাদ্দে 1562 ক্লক টিক লাগে।


হ্যাঁ, একটি অনুকূলকরণকারী সংকলক শূন্য অবজেক্ট তৈরি করতে পারে ide যদি আমি সঠিকভাবে বুঝতে পারি তবে এটি সম্পূর্ণ প্রথম লুপটি এলিডও করতে পারে। আমি যখন পুনরাবৃত্তিগুলি 10,000,000 এ ছড়িয়ে দিয়েছি তখন স্ট্যাক বরাদ্দে 31 টি ঘড়ির টিকিট লেগেছিল এবং গাদা বরাদ্দে 1562 ক্লক টিকস লেগেছে। আমি মনে করি এটি নির্ধারিতভাবে নিরাপদ যে g ++ এক্সিকিউটেবলের অনুকূলকরণের জন্য না বললে, g ++ নির্মাণকারীদের এলিড করেনি।


আমি এটি লেখার পরের বছরগুলিতে স্ট্যাক ওভারফ্লোতে অগ্রাধিকারটি অনুকূলিত বিল্ডগুলি থেকে পারফরম্যান্স পোস্ট করা। সাধারণভাবে, আমি মনে করি এটি সঠিক। যাইহোক, আমি এখনও মনে করি যে কম্পাইলারকে কোডটি অপ্টিমাইজ করতে জিজ্ঞাসা করা নির্বোধ, যখন আপনি বাস্তবে সেই কোডটি অপ্টিমাইজ করতে চান না। এটি আমাকে ভ্যালেট পার্কিংয়ের জন্য অতিরিক্ত অর্থ প্রদানের অনুরূপ হিসাবে ধরা দেয়, তবে কীগুলি হস্তান্তর করতে অস্বীকার করে। এই বিশেষ ক্ষেত্রে, আমি চাই না যে অপটিমাইজার চলমান।

মাপদণ্ডের সামান্য পরিবর্তিত সংস্করণ ব্যবহার করে (বৈধ পয়েন্টটি সম্বোধনের জন্য যে মূল প্রোগ্রামটি প্রতিটি সময় লুপের মাধ্যমে স্ট্যাকের জন্য কিছু বরাদ্দ দেয় না) এবং অপ্টিমাইজেশন ছাড়াই সংকলন করা হয় তবে লাইব্রেরিগুলি প্রকাশের সাথে সংযোগ স্থাপন (আমরা যে ডানটি দিচ্ছি না তার বৈধ পয়েন্টটি সম্বোধন করার জন্য) 'ডিবাগ লাইব্রেরিগুলির সাথে সংযোগের কারণে যে কোনও ধীরগতি হয়েছে তা অন্তর্ভুক্ত করতে চাই না):

#include <cstdio>
#include <chrono>

namespace {
    void on_stack()
    {
        int i;
    }

    void on_heap()
    {
        int* i = new int;
        delete i;
    }
}

int main()
{
    auto begin = std::chrono::system_clock::now();
    for (int i = 0; i < 1000000000; ++i)
        on_stack();
    auto end = std::chrono::system_clock::now();

    std::printf("on_stack took %f seconds\n", std::chrono::duration<double>(end - begin).count());

    begin = std::chrono::system_clock::now();
    for (int i = 0; i < 1000000000; ++i)
        on_heap();
    end = std::chrono::system_clock::now();

    std::printf("on_heap took %f seconds\n", std::chrono::duration<double>(end - begin).count());
    return 0;
}

প্রদর্শন:

on_stack took 2.070003 seconds
on_heap took 57.980081 seconds

কমান্ড লাইনের সাথে সংকলিত হয়ে গেলে আমার সিস্টেমে cl foo.cc /Od /MT /EHsc

অপ-অনুকূলিতাপূর্ণ বিল্ড পাওয়ার বিষয়ে আপনি আমার পদ্ধতির সাথে একমত হতে পারেন না। এটি ঠিক আছে: আপনি যতটা চান বেঞ্চমার্ককে নির্দ্বিধায় পরিবর্তন করুন। আমি যখন অপ্টিমাইজেশন চালু করি তখন আমি পাই:

on_stack took 0.000000 seconds
on_heap took 51.608723 seconds

স্ট্যাক বরাদ্দ আসলে তাত্ক্ষণিক বলে নয় তবে যে কোনও অর্ধ-শালীন সংকলক লক্ষ্য করতে on_stackপারে যে দরকারী কিছু করে না এবং অপ্টিমাইজ করা যেতে পারে। আমার লিনাক্স ল্যাপটপের জিসিসিও লক্ষ্য করে যেগুলি on_heapকার্যকর কিছু করে না এবং এটি অপ্টিমাইজও করে:

on_stack took 0.000003 seconds
on_heap took 0.000002 seconds

2
এছাড়াও, আপনার প্রধান ফাংশনটির একেবারে শুরুতে আপনার একটি "ক্রমাঙ্কন" লুপ যুক্ত করা উচিত, যা আপনি লুপ-চক্রের জন্য কতটা সময় পাচ্ছেন তা আপনাকে একটি ধারণা দেয় এবং অন্যান্য লুপগুলি সামঞ্জস্য করে যাতে আপনার উদাহরণটি চালিত হয় তা নিশ্চিত করা যায় আপনি যে স্থির ধ্রুবকটি ব্যবহার করছেন তার পরিবর্তে কিছু পরিমাণ সময়।
জো পাইনেদা 19

2
আমি প্রতিটি বিকল্প লুপ রান করার সংখ্যা বৃদ্ধি করে (প্লাস জি ++ অপটিমাইজ না করার নির্দেশ দিচ্ছি?) উল্লেখযোগ্য ফলাফল পেয়েছে বলেও আমি আনন্দিত। সুতরাং এখন আমাদের কাছে স্ট্যাকের দ্রুত বলা শক্ত কারণ আছে। আপনার প্রচেষ্টার জন্য ধন্যবাদ!
জো পাইনেদা

7
এই জাতীয় কোড থেকে মুক্তি পাওয়ার জন্য এটি অপ্টিমাইজারের কাজ। অপ্টিমাইজারটি চালু করার এবং তারপরে বাস্তবে এটি অপ্টিমাইজ করা থেকে বিরত রাখার কোনও উপযুক্ত কারণ আছে? জিনিসগুলিকে আরও পরিষ্কার করার জন্য আমি উত্তরটি সম্পাদনা করেছি: আপনি যদি অপটিমাইজারের সাথে লড়াই করা উপভোগ করেন তবে স্মার্ট সংকলক লেখকরা কীভাবে তা শিখতে প্রস্তুত থাকুন।
ম্যাক্স ল্যাববার্ট

3
আমি খুব দেরী করেছি, তবে এখানে উল্লেখ করা খুব দরকার যে গাদা বরাদ্দ কার্নেলের মাধ্যমে মেমরির জন্য অনুরোধ করে, তাই পারফরম্যান্সের আঘাতও কর্নেলের কার্যকারিতার উপর দৃ strongly়ভাবে নির্ভর করে। লিনাক্স (লিনাক্সের 3.10.7-জেন্টু # 2 জন্য SMP বুধ সেপ্টেম্বর 4 18:58:21 MDT 2013, x86_64) সঙ্গে এই কোড ব্যবহার করে, এইচআর টাইমার জন্য পরিবর্তন, এবং প্রতিটি লুপ 100 মিলিয়ন পুনরাবৃত্তিও ব্যবহার করে এই কর্মক্ষমতা উৎপাদ: stack allocation took 0.15354 seconds, heap allocation took 0.834044 secondsসঙ্গে -O0সেট, তৈরীর আমার বিশেষ মেশিনে লিনাক্স হ্যাপের বরাদ্দটি প্রায় 5.5 এর ফ্যাক্টরের উপর ধীর হয়।
তাইউই

4
অপ্টিমাইজেশন ছাড়াই উইন্ডোগুলিতে (ডিবাগ বিল্ড) এটি ডিবাগ হিপ ব্যবহার করবে যা নন ডিবাগ হ্যাপের চেয়ে অনেক ধীর। আমি অপ্টিমাইজারটিকে "কৌশল" করা মোটেই খারাপ ধারণা মনে করি না। সংকলক লেখকরা স্মার্ট, তবে সংকলকগুলি এআই এর নয়।
পলম

30

এক্সবক্স ৩ He০ জেনন প্রসেসরের স্ট্যাক বনাম হিপ বরাদ্দ সম্পর্কে আমি একটি আকর্ষণীয় বিষয় শিখেছি, যা অন্যান্য মাল্টিকোর সিস্টেমগুলিতেও প্রযোজ্য হতে পারে, হিপ থেকে বরাদ্দকরণের ফলে অন্যান্য সমস্ত কোর বন্ধ করার জন্য একটি সমালোচনামূলক বিভাগ প্রবেশ করানো হয় যাতে বরাদ্দটি না হয় বিরোধ নেই। সুতরাং, একটি শক্ত লুপে, স্ট্যাক বরাদ্দ স্থির আকারের অ্যারেগুলিতে যাওয়ার উপায় ছিল কারণ এটি স্টলগুলি রোধ করে।

আপনি মাল্টিকোর / মাল্টিপ্রোকের জন্য কোডিং করছেন কিনা তা বিবেচনা করার জন্য এটি আর একটি গতিপথ হতে পারে, যাতে আপনার স্ট্যাক বরাদ্দটি কেবল আপনার স্কোপযুক্ত ক্রিয়াকলাপটি চালিত কোর দ্বারা দৃশ্যমান হবে এবং এটি অন্য কোনও কোর / সিপিইউগুলিকে প্রভাবিত করবে না।


4
এটি কেবল জেনন নয়, বেশিরভাগ মাল্টিকোর মেশিনের ক্ষেত্রে সত্য। এমনকি সেলটিকে এটি করতে হবে কারণ আপনি সম্ভবত সেই পিপিইউ কোরটিতে দুটি হার্ডওয়্যার থ্রেড চালাচ্ছেন।
ক্র্যাশ ওয়ার্কস

15
এটি হ্যাপ বরাদ্দকারীর (বিশেষত দরিদ্র) বাস্তবায়নের একটি প্রভাব। আরও ভাল গাদা বরাদ্দকারীদের প্রতিটি বরাদ্দের একটি লক অর্জন করা প্রয়োজন।
ক্রিস ডড

19

আপনি নির্দিষ্ট আকারের অবজেক্টের জন্য খুব পারফরম্যান্সের জন্য একটি বিশেষ গাদা বরাদ্দকারী লিখতে পারেন। তবে সাধারণ গাদা বরাদ্দকারী বিশেষ পারফরম্যান্ট নয়।

এছাড়াও আমি Torbjörn Gyllebring সাথে প্রত্যাশিত অবজেক্টের আয়ু সম্পর্কে সম্মত। ভাল যুক্তি!


1
এটি কখনও কখনও স্ল্যাব বরাদ্দ হিসাবে উল্লেখ করা হয়।
বেনোইট

8

আমি মনে করি না স্ট্যাক বরাদ্দ এবং গাদা বরাদ্দটি সাধারণত বিনিময়যোগ্য। আমি দু'জনের পারফরম্যান্স সাধারণ ব্যবহারের জন্য যথেষ্ট বলে আমিও আশা করি।

আমি ছোট আইটেমগুলির জন্য দৃ strongly়ভাবে সুপারিশ করব, যেকোন একটি বরাদ্দ দেওয়ার সুযোগের জন্য উপযুক্ত। বড় আইটেমগুলির জন্য, গাদা সম্ভবত প্রয়োজনীয়।

একাধিক থ্রেডযুক্ত 32-বিট অপারেটিং সিস্টেমগুলিতে স্ট্যাকটি প্রায়শই সীমাবদ্ধ থাকে (যদিও সাধারণত কমপক্ষে কয়েক এমবিতে থাকে) কারণ ঠিকানার স্থানটি খোদাই করা দরকার এবং শীঘ্রই বা পরে একটি থ্রেড স্ট্যাক অন্যটিতে চলে যাবে। একক থ্রেডেড সিস্টেমে (লিনাক্স গ্লিবসি সিঙ্গল থ্রেডেড যাইহোক) সীমাবদ্ধতা অনেক কম কারণ স্ট্যাকটি কেবল বৃদ্ধি এবং বৃদ্ধি পেতে পারে।

-৪-বিট অপারেটিং সিস্টেমে থ্রেড স্ট্যাকগুলি বেশ বড় করার জন্য যথেষ্ট ঠিকানার জায়গা রয়েছে।


6

সাধারণত স্ট্যাক বরাদ্দ কেবল স্ট্যাক পয়েন্টার রেজিস্টার থেকে বিয়োগ করে থাকে। এটি একটি গাদা অনুসন্ধানের চেয়ে অনেক বেশি দ্রুত।

কখনও কখনও স্ট্যাক বরাদ্দ ভার্চুয়াল মেমরির একটি পৃষ্ঠা (গুলি) যুক্ত করা প্রয়োজন। জিরোড মেমরির একটি নতুন পৃষ্ঠা যুক্ত করার জন্য ডিস্ক থেকে কোনও পৃষ্ঠা পড়ার প্রয়োজন হয় না, তাই সাধারণত এটি এখনও একটি গাদা অনুসন্ধান করার চেয়ে টন দ্রুত হতে চলেছে (বিশেষত যদি গাদাটির অংশটিও পৃষ্ঠাটি বের করে দেওয়া হয়েছিল)। একটি বিরল পরিস্থিতিতে, এবং আপনি যেমন একটি উদাহরণ তৈরি করতে পারেন, র‍্যামের মধ্যে ইতিমধ্যে থাকা স্তূপের অংশে পর্যাপ্ত জায়গা কেবল পাওয়া যায়, তবে স্ট্যাকের জন্য একটি নতুন পৃষ্ঠা বরাদ্দকরণের জন্য অন্য কোনও পৃষ্ঠা লিখিত হওয়ার জন্য অপেক্ষা করতে হবে ডিস্কে যে বিরল পরিস্থিতিতে, গাদা দ্রুত হয়।


আমি মনে করি না যে গাদাটি পৃষ্ঠাযুক্ত না করা পর্যন্ত "অনুসন্ধান" করা হয়েছে। অত্যন্ত নিশ্চিত যে শক্ত রাষ্ট্র মেমরিটি একটি মাল্টিপ্লেক্সর ব্যবহার করে এবং মেমরিতে সরাসরি অ্যাক্সেস পেতে পারে, তাই এলোমেলো অ্যাক্সেস মেমরি।
জো ফিলিপস 17

4
এখানে একটি উদাহরণ। কলিং প্রোগ্রামটি 37 বাইট বরাদ্দ করতে বলে। লাইব্রেরির ফাংশনটি কমপক্ষে 40 বাইটের ব্লক সন্ধান করে। বিনামূল্যে তালিকার প্রথম ব্লকে 16 বাইট রয়েছে। ফ্রি তালিকার দ্বিতীয় ব্লকে 12 বাইট রয়েছে। তৃতীয় ব্লকে 44 বাইট রয়েছে। লাইব্রেরিটি সেই স্থানে অনুসন্ধান বন্ধ করে দেয়।
উইন্ডোজ প্রোগ্রামার 23

6

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


4

একটি স্ট্যাকের সীমাবদ্ধ ক্ষমতা রয়েছে, যখন একটি গাদা হয় না। একটি প্রক্রিয়া বা থ্রেডের জন্য সাধারণ স্ট্যাকটি প্রায় 8K এর কাছাকাছি। বরাদ্দ হয়ে গেলে আপনি আকারটি পরিবর্তন করতে পারবেন না।

একটি স্ট্যাক ভেরিয়েবল স্কোপিংয়ের নিয়মগুলি অনুসরণ করে, যখন একটি গাদা করে না। যদি আপনার নির্দেশ পয়েন্টারটি কোনও ফাংশনের বাইরে চলে যায় তবে ফাংশনের সাথে যুক্ত সমস্ত নতুন ভেরিয়েবল চলে যায়।

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


1
একটি আধুনিক ওএসে ব্যবহারকারী মোড স্ট্যাকের জন্য বরাদ্দ ভার্চুয়াল ঠিকানার জায়গার পরিমাণ কমপক্ষে কমপক্ষে k৪ কেবি বা তার চেয়ে বেশি ডিফল্ট হিসাবে (উইন্ডোজে 1MB) হতে পারে। আপনি কি কার্নেল স্ট্যাকের আকারগুলির বিষয়ে কথা বলছেন?
বিকে

1
আমার মেশিনে, কোনও প্রক্রিয়াটির জন্য ডিফল্ট স্ট্যাকের আকার 8MB হয়, কেবি নয়। আপনার কম্পিউটার বয়স কত হল?
গ্রেগ রজার্স

3

আমি মনে করি আজীবন গুরুত্বপূর্ণ, এবং বরাদ্দকৃত জিনিসটি জটিল পদ্ধতিতে তৈরি করা উচিত কিনা whether উদাহরণস্বরূপ, লেনদেন-চালিত মডেলিংয়ে আপনাকে সাধারণত অপারেশন ফাংশনগুলিতে একগুচ্ছ ক্ষেত্র সহ একটি লেনদেন কাঠামো পূরণ করতে হয় এবং পাস করতে হয়। উদাহরণের জন্য ওএসসিআই সিস্টেমসি টিএলএম -২.০ স্ট্যান্ডার্ডটি দেখুন।

অপারেশনের কলের কাছে এটিকে স্ট্যাকের কাছে বরাদ্দকরণের ফলে নির্মাণ ব্যয়বহুল হওয়ায় প্রচুর ওভারহেড তৈরি করে। ভাল উপায় হ'ল বরাদ্দ করা এবং লেনদেনের মাধ্যমে লেনদেনের অবজেক্টগুলি পুনরায় ব্যবহার করা বা "এই মডিউলের জন্য কেবলমাত্র একটি লেনদেনের বিষয় প্রয়োজন" এর মতো সরল নীতি।

এটি প্রতিটি অপারেশন কলের মধ্যে অবজেক্ট বরাদ্দ করার চেয়ে অনেকগুণ দ্রুত।

কারণটি হ'ল অবজেক্টটির একটি ব্যয়বহুল নির্মাণ এবং মোটামুটি দীর্ঘকালীন কার্যকর জীবনকাল।

আমি বলব: উভয় চেষ্টা করে দেখুন এবং আপনার ক্ষেত্রে সবচেয়ে ভাল কাজ করে দেখুন, কারণ এটি আপনার কোডের আচরণের উপর নির্ভর করে depend


3

স্তূপ বরাদ্দ বনাম স্ট্যাক বরাদ্দের সবচেয়ে বড় সমস্যাটি হ'ল সাধারণ ক্ষেত্রে হিপ বরাদ্দ একটি আনবাউন্ডেড অপারেশন এবং সুতরাং সময় নির্ধারণের বিষয়টি যেখানে আপনি এটি ব্যবহার করতে পারবেন না।

অন্যান্য অ্যাপ্লিকেশনগুলির জন্য যেখানে সময় নির্ধারণের বিষয়টি কোনও সমস্যা নয়, এটি ততটা গুরুত্বপূর্ণ নাও হতে পারে তবে আপনি যদি প্রচুর পরিমাণে বরাদ্দ করেন তবে এটি কার্যকর করার গতিতে প্রভাব ফেলবে। সর্বদা স্বল্পকালীন এবং প্রায়শই বরাদ্দ মেমরির জন্য উদাহরণস্বরূপ ব্যবহার করার চেষ্টা করুন (উদাহরণস্বরূপ লুপগুলিতে), এবং যতক্ষণ সম্ভব - অ্যাপ্লিকেশন প্রারম্ভের সময় গাদা বরাদ্দ করুন।


3

এটি jsut স্ট্যাক বরাদ্দ যে দ্রুত। আপনি স্ট্যাক ভেরিয়েবল ব্যবহার করেও প্রচুর জয়ী হন। তারা রেফারেন্স ভাল লোকেশন আছে। এবং শেষ অবধি, ডিওলোকেশনটিও অনেক সস্তা।


3

স্ট্যাক বরাদ্দ হ'ল কয়েকটি নির্দেশনা যেখানে আমার জানা সবচেয়ে দ্রুততম আরটিওস হিপ বরাদ্দকারী (টিএলএসএফ) গড়ে 150 টি নির্দেশের ক্রম ব্যবহার করে। এছাড়াও স্ট্যাক বরাদ্দগুলির জন্য কোনও লক প্রয়োজন হয় না কারণ তারা থ্রেড স্থানীয় স্টোরেজ ব্যবহার করে যা এটি আরও একটি দুর্দান্ত পারফরম্যান্সের জয়। আপনার পরিবেশ কতটা ভারিভাবে বিস্তৃত হয় তার উপর নির্ভর করে স্ট্যাক বরাদ্দগুলি দ্রুততার পরিমাণের 2-3 অর্ডার হতে পারে।

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


3

সি ++ ভাষার ক্ষেত্রে নির্দিষ্ট উদ্বেগ

প্রথমত, C ++ দ্বারা আদেশিত কোনও তথাকথিত "স্ট্যাক" বা "হিপ" বরাদ্দ নেই । আপনি যদি ব্লক স্কোপগুলিতে স্বয়ংক্রিয় বস্তুর কথা বলছেন তবে সেগুলি এমনকি "বরাদ্দ" হয় না। (বিটিডাব্লু, সিতে স্বয়ংক্রিয় স্টোরেজ সময়কাল অবশ্যই "বরাদ্দকৃত" সমান নয়; পরবর্তীটি সি ++ পার্লেন্সে "গতিশীল" হয়।) গতিশীলভাবে বরাদ্দ হওয়া মেমরিটি ফ্রি স্টোরে রয়েছে , প্রয়োজনীয়ভাবে "হিপ"-তে নেই, যদিও দ্বিতীয়টি প্রায়শই (ডিফল্ট) বাস্তবায়ন হয়

যদিও বিমূর্ত মেশিনের সিনমেটিক নিয়ম অনুসারে, স্বয়ংক্রিয় বস্তুগুলি এখনও মেমরি দখল করে, একটি সিদ্ধিকৃত সি ++ বাস্তবায়ন যখন এই বিষয়টির প্রমাণ দেয় না তখন (যখন এটি প্রোগ্রামের পর্যবেক্ষণযোগ্য আচরণকে পরিবর্তন করে না) প্রমাণ করতে পারে এ বিষয়টিটিকে এড়িয়ে যাওয়ার অনুমতি দেওয়া হয়। এই অনুমতিটি আইএসও সি ++ -তে নিয়ম অনুসারে মঞ্জুর করা হয়েছে , এটি সাধারণ অনুচ্ছেদও সাধারণ অপটিমাইজেশন সক্ষম করে (এবং আইএসও সি-তেও প্রায় একই নিয়ম রয়েছে)। আস-বিধি বিধি ছাড়াও, আইএসও সি ++ এরও অনুলিপি সংক্রান্ত নিয়ম রয়েছেঅবজেক্টের নির্দিষ্ট সৃষ্টি বাদ দেওয়ার অনুমতি দিতে to এতে যুক্ত কন্সট্রাক্টর এবং ডেস্ট্রাক্টর কলগুলি বাদ দেওয়া হয়। ফলস্বরূপ, উত্স কোড দ্বারা ইঙ্গিত নিষ্পাপ বিমূর্ত শব্দার্থবিজ্ঞানের তুলনায় এই নির্মাতা এবং ধ্বংসকারীদের মধ্যে স্বয়ংক্রিয় বস্তুগুলি (যদি থাকে তবে )ও নির্মূল করা হয় eliminated

অন্যদিকে, ফ্রি স্টোর বরাদ্দ অবশ্যই ডিজাইনের দ্বারা "বরাদ্দ"। আইএসও সি ++ নিয়মের অধীনে এই জাতীয় বরাদ্দ কোনও বরাদ্দ ক্রিয়াকলাপের মাধ্যমে অর্জন করা যেতে পারে । যাইহোক, আইএসও সি ++ ১৪ এর পরে, একটি::operator new নির্দিষ্ট ক্ষেত্রে বিশ্বব্যাপী বরাদ্দকরণ ফাংশন (অর্থাত্ ) কলগুলি মার্জ করার অনুমতি দেওয়ার জন্য একটি নতুন (অ-হিসাবে-যেমন) বিধি রয়েছে । সুতরাং গতিশীল বরাদ্দকরণ ক্রিয়াকলাপগুলির অংশগুলি স্বয়ংক্রিয় বস্তুর ক্ষেত্রেও কোনও বিকল্প হতে পারে।

বরাদ্দ ফাংশন মেমরির সংস্থান বরাদ্দ করে। বরাদ্দকারীদের ব্যবহার করে বরাদ্দের ভিত্তিতে অবজেক্টগুলি আরও বরাদ্দ করা যেতে পারে। স্বয়ংক্রিয় বস্তুর জন্য এগুলি সরাসরি উপস্থাপিত হয় - যদিও অন্তর্নিহিত মেমরিটি অ্যাক্সেস করা যায় এবং অন্যান্য বস্তুগুলিকে (স্থান দ্বারা new) মেমরি সরবরাহ করতে ব্যবহৃত হতে পারে তবে এটি ফ্রি স্টোর হিসাবে দুর্দান্ত বোঝায় না, কারণ সরানোর কোনও উপায় নেই because অন্যত্র সংস্থান।

অন্যান্য সমস্ত উদ্বেগগুলি সি ++ এর আওতার বাইরে। তবুও, তারা এখনও তাৎপর্যপূর্ণ হতে পারে।

সি ++ এর বাস্তবায়ন সম্পর্কে

সি ++ রিফাইড অ্যাক্টিভেশন রেকর্ডস বা কিছু ধরণের প্রথম শ্রেণির ধারাবাহিকতা (যেমন বিখ্যাত দ্বারা call/cc) প্রকাশ করে না, অ্যাক্টিভেশন রেকর্ড ফ্রেমগুলি সরাসরি পরিচালনা করার কোনও উপায় নেই - যেখানে বাস্তবায়নের জন্য স্বয়ংক্রিয় বস্তুগুলিকে স্থাপন করা দরকার। অন্তর্নিহিত বাস্তবায়ন ("নেটিভ" নন-পোর্টেবল কোড যেমন ইনলাইন এসেম্বলি কোড) এর সাথে কোনও (অ-বহনযোগ্য) আন্তঃব্যবস্থাগুলি না হয়ে গেলে ফ্রেমের অন্তর্নিহিত বরাদ্দ বাদ দেওয়া বেশ তুচ্ছ হতে পারে। উদাহরণস্বরূপ, যখন ডাকা ফাংশনটি ইনলাইন করা হয় তখন ফ্রেমগুলি কার্যকরভাবে অন্যদের মধ্যে মিশে যায়, সুতরাং "বরাদ্দ" কী তা দেখানোর কোনও উপায় নেই।

যাইহোক, একবার ইন্টারপগুলি সম্মানিত হয়ে গেলে জিনিসগুলি জটিল হয়ে উঠছে। সি ++ এর একটি সাধারণ বাস্তবায়ন দেশীয় (আইএসএ-স্তরীয় মেশিন) কোডের সাথে বাইনারি সীমানা ভাগ করে নেওয়া কিছু কলিং কনভেনশনের সাথে আইএসএ (নির্দেশনা-স্থিতি স্থাপত্য) -এ ইন্টারপ করার ক্ষমতা প্রকাশ করবে । এটি স্পষ্টভাবে ব্যয়বহুল হবে, উল্লেখযোগ্যভাবে, স্ট্যাক পয়েন্টারটি বজায় রাখার সময় , যা প্রায়শই সরাসরি আইএসএ-স্তরের রেজিস্টারে থাকে (সম্ভবত অ্যাক্সেসের জন্য নির্দিষ্ট মেশিনের নির্দেশাবলী সহ)। স্ট্যাক পয়েন্টারটি (বর্তমানে সক্রিয়) ফাংশন কলের শীর্ষ ফ্রেমের সীমানা নির্দেশ করে। যখন কোনও ফাংশন কল প্রবেশ করা হয়, তখন একটি নতুন ফ্রেম প্রয়োজন হয় এবং স্ট্যাক পয়েন্টারটি প্রয়োজনীয় ফ্রেমের আকারের চেয়ে কম নয় এমন একটি মান দ্বারা যুক্ত বা বিয়োগ করা হয় (আইএসএর কনভেনশনের উপর নির্ভর করে) t ফ্রেমটি তখন বরাদ্দকৃত বলা হয়অপারেশন পরে যখন স্ট্যাক পয়েন্টার। কলের জন্য ব্যবহৃত কলিং কনভেনশনের উপর নির্ভর করে ফাংশনগুলির প্যারামিটারগুলি স্ট্যাক ফ্রেমেও পাস করা যেতে পারে। ফ্রেমটি সি ++ উত্স কোড দ্বারা নির্দিষ্ট স্বয়ংক্রিয় বস্তুর (সম্ভবত প্যারামিটার সহ) মেমরি ধরে রাখতে পারে। এই জাতীয় বাস্তবায়নের অর্থে, এই বিষয়গুলি "বরাদ্দ" করা হয়। যখন কন্ট্রোলটি ফাংশন কল থেকে প্রস্থান করে, ফ্রেমের আর প্রয়োজন হয় না, সাধারণত কল করার আগে স্ট্যাক পয়েন্টারটিকে পুনরায় অবস্থায় ফিরিয়ে আনা হয় (কলিং কনভেনশন অনুযায়ী পূর্বে সংরক্ষণ করা হয়েছিল)। এটি "অবনতি" হিসাবে দেখা যেতে পারে। এই ক্রিয়াকলাপগুলি কার্যকরভাবে একটি LIFO ডেটা কাঠামো সক্রিয়করণ রেকর্ড করে তোলে, তাই এটি প্রায়শই " দ্য (কল) স্ট্যাক " নামে পরিচিত ।

যেহেতু বেশিরভাগ সি ++ বাস্তবায়ন (বিশেষত আইএসএ-স্তরীয় নেটিভ কোডকে টার্গেট করে এবং এসেম্বলি ভাষাটিকে তার তাত্ক্ষণিক আউটপুট হিসাবে ব্যবহার করে) এই জাতীয় কৌশলগুলি ব্যবহার করে, এই জাতীয় একটি বিভ্রান্তিকর "বরাদ্দ" প্রকল্পটি জনপ্রিয়। এই জাতীয় বরাদ্দ (পাশাপাশি deallocations) মেশিন চক্র ব্যয় করে এবং এটি ব্যয়বহুল হতে পারে যখন (অ-অনুকূলিতকরণ) কলগুলি ঘন ঘন ঘটে, যদিও আধুনিক সিপিইউ মাইক্রোআরকিটেক্টরগুলিতে সাধারণ কোড প্যাটার্নের জন্য হার্ডওয়ার দ্বারা প্রয়োগ করা জটিল অপ্টিমাইজেশন থাকতে পারে (যেমন ব্যবহার করার মতো) প্রয়োগ / নির্দেশাবলীতে স্ট্যাক ইঞ্জিন )।PUSHPOP

তবে যাইহোক, সাধারণভাবে, এটি সত্য যে স্ট্যাক ফ্রেমের বরাদ্দের ব্যয়টি ফ্রি স্টোর পরিচালনা করে এমন বরাদ্দ ফাংশনের কলের তুলনায় উল্লেখযোগ্যভাবে কম (যদি এটি সম্পূর্ণ অপটিমাইজড না হয়) , যা নিজেই কয়েকশো (যদি লক্ষ লক্ষ না হয়) থাকতে পারে :-) স্ট্যাক পয়েন্টার এবং অন্যান্য রাজ্য বজায় রাখার জন্য ক্রিয়াকলাপ। বরাদ্দ ফাংশন সাধারণত হোস্ট করা পরিবেশ দ্বারা সরবরাহ করা API এর উপর ভিত্তি করে (যেমন ওএস দ্বারা সরবরাহিত রানটাইম)। ফাংশন কলগুলির জন্য স্বয়ংক্রিয় অবজেক্টগুলি ধারণ করার উদ্দেশ্য থেকে পৃথক, এই জাতীয় বরাদ্দগুলি সাধারণ-উদ্দেশ্যযুক্ত, তাই তাদের স্ট্যাকের মতো ফ্রেম কাঠামো থাকবে না। Ditionতিহ্যগতভাবে, তারা পুল স্টোরেজ থেকে হ্যাপ (বা বেশ কয়েকটি হ্যাপ ) নামে স্থান বরাদ্দ করে । "স্ট্যাক" থেকে আলাদা, এখানে ধারণা "হিপ" ডেটা কাঠামোটি ব্যবহৃত হচ্ছে তা নির্দেশ করে না;এটি বহু দশক আগে প্রাথমিক ভাষা প্রয়োগ থেকে উদ্ভূত । (বিটিডাব্লু, কল স্ট্যাকটি সাধারণত প্রোগ্রাম বা থ্রেড স্টার্টআপে পরিবেশ দ্বারা গাদা থেকে স্থির বা ব্যবহারকারী-নির্দিষ্ট আকারের সাথে বরাদ্দ করা হয়)) ব্যবহারের কেসগুলির প্রকৃতি একগাদা থেকে বরাদ্দ এবং ডিএলোকেশনগুলি আরও জটিল করে তোলে (ধাক্কা বা পপ এর চেয়ে বেশি) স্ট্যাক ফ্রেম), এবং হার্ডওয়ার দ্বারা সরাসরি অনুকূলিত হওয়া খুব কমই সম্ভব।

মেমোরি অ্যাক্সেসের উপর প্রভাব

সাধারণ স্ট্যাক বরাদ্দ সর্বদা নতুন ফ্রেমটিকে শীর্ষে রাখে, সুতরাং এটির বেশ ভাল লোকাল রয়েছে। এটি ক্যাশে বন্ধুত্বপূর্ণ। ওটিওএইচ, ফ্রি স্টোর এলোমেলোভাবে বরাদ্দ মেমরির এমন কোনও সম্পত্তি নেই। আইএসও সি ++ 17 হ'ল, এখানে পুলের সংস্থান টেম্পলেট সরবরাহ করা আছে <memory>। এই জাতীয় ইন্টারফেসের প্রত্যক্ষ উদ্দেশ্য হ'ল একটানা বরাদ্দের ফলাফলগুলি মেমরির সাথে একত্রে হওয়া। এটি এই সত্যটি স্বীকার করে যে এই কৌশলটি সমসাময়িক বাস্তবায়নগুলির সাথে পারফরম্যান্সের জন্য সাধারণত ভাল, যেমন আধুনিক স্থাপত্যগুলিতে ক্যাশে বন্ধুত্বপূর্ণ। এটি বরাদ্দ না করে অ্যাক্সেসের কর্মক্ষমতা সম্পর্কে ।

concurrency

মেমরির একযোগে অ্যাক্সেসের প্রত্যাশা স্ট্যাক এবং হিপগুলির মধ্যে পৃথক প্রভাব ফেলতে পারে। একটি কল স্ট্যাক সাধারণত সি ++ বাস্তবায়নে মৃত্যুর এক থ্রেডের দ্বারা একচেটিয়াভাবে মালিকানাধীন। OTOH, হ্যাপগুলি প্রায়শই একটি প্রক্রিয়াতে থ্রেডগুলির মধ্যে ভাগ করা হয় । এই জাতীয় স্তূপগুলির জন্য, বরাদ্দ এবং অবনতি ফাংশনগুলিকে ভাগ করা অভ্যন্তরীণ প্রশাসনিক ডেটা কাঠামোটিকে ডেটা রেস থেকে রক্ষা করতে হয়। ফলস্বরূপ, অভ্যন্তরীণ সিঙ্ক্রোনাইজেশন ক্রিয়াকলাপগুলির কারণে গাদা বরাদ্দ এবং ডিএলোকেশনের অতিরিক্ত ওভারহেড থাকতে পারে।

স্থান দক্ষতা

ব্যবহারের ক্ষেত্রে এবং অভ্যন্তরীণ ডেটা স্ট্রাকচারের প্রকৃতির কারণে, স্তূপগুলি অভ্যন্তরীণ মেমরি খণ্ডিত হতে পারে , যখন স্ট্যাকটি তা করে না। এটি মেমোরি বরাদ্দের কর্মক্ষমতা উপর সরাসরি প্রভাব ফেলবে না, তবে ভার্চুয়াল মেমরি সহ একটি সিস্টেমে কম স্থান দক্ষতা স্মৃতি অ্যাক্সেসের সামগ্রিক কর্মক্ষমতা হ্রাস করতে পারে। এইচডিডি শারীরিক মেমরির অদলবদল হিসাবে ব্যবহৃত হয় এটি বিশেষত ভয়ঙ্কর। এটি বেশ দীর্ঘ বিলম্বের কারণ হতে পারে - কখনও কখনও কোটি কোটি চক্র।

স্ট্যাক বরাদ্দের সীমাবদ্ধতা

যদিও বাস্তবে স্তরের বরাদ্দের তুলনায় স্ট্যাক বরাদ্দগুলি প্রায়শই কার্যক্ষমতায় উন্নত হয় তবে এর অর্থ এই নয় যে স্ট্যাক বরাদ্দ সর্বদা হিপ বরাদ্দ প্রতিস্থাপন করতে পারে।

প্রথমত, আইএসও সি ++ এর সাথে পোর্টেবল উপায়ে রানটাইমের সময় নির্দিষ্ট আকারের সাথে স্ট্যাকের জন্য জায়গা বরাদ্দ করার কোনও উপায় নেই। allocaG ++ এর ভিএলএ (ভেরিয়েবল-দৈর্ঘ্যের অ্যারে) এর মতো বাস্তবায়ন দ্বারা সরবরাহ করা এক্সটেনশন রয়েছে তবে সেগুলি এড়াতে কারণ রয়েছে। (আইআইআরসি, লিনাক্স উত্সটি সম্প্রতি ভিএলএর ব্যবহার সরিয়ে ফেলেছে।) (এছাড়াও নোট করুন যে সিএসও সি৯৯-এ ভিএলএন্ডের বাধ্যবাধকতা রয়েছে, তবে আইএসও সি 11 সমর্থনটি optionচ্ছিকভাবে পরিণত করে।)

দ্বিতীয়ত, স্ট্যাক স্পেস ক্লান্তি সনাক্ত করার জন্য কোনও নির্ভরযোগ্য এবং বহনযোগ্য উপায় নেই। এটিকে প্রায়শই স্ট্যাক ওভারফ্লো (এইচএমএম, এই সাইটের ব্যুৎপত্তি) বলা হয় তবে সম্ভবত আরও সঠিকভাবে স্ট্যাককে ছাড়িয়ে যায় । বাস্তবে, এটি প্রায়শই অবৈধ মেমরি অ্যাক্সেসের কারণ হয়ে থাকে এবং প্রোগ্রামের অবস্থাটি তখন দুর্নীতিগ্রস্থ হয় (... বা আরও খারাপ হতে পারে, একটি সুরক্ষা গর্ত)। আসলে, আইএসও সি ++ এর "স্ট্যাক" সম্পর্কে কোনও ধারণা নেই এবং সংস্থানটি শেষ হয়ে গেলে এটিকে অপরিজ্ঞাত আচরণ করে তোলে । স্বয়ংক্রিয় অবজেক্টগুলির জন্য কতটা জায়গা রেখে দেওয়া উচিত সে সম্পর্কে সতর্ক হন।

যদি স্ট্যাকের জায়গাটি শেষ হয়ে যায়, স্ট্যাকের মধ্যে অনেকগুলি বরাদ্দ রয়েছে, যা ফাংশনগুলির অনেক বেশি সক্রিয় কল বা স্বয়ংক্রিয় বস্তুর অযাচিত ব্যবহারের কারণে হতে পারে। এই জাতীয় কেসগুলি বাগের অস্তিত্বের পরামর্শ দিতে পারে, যেমন সঠিক প্রস্থান শর্ত ছাড়া একটি পুনরাবৃত্ত ফাংশন কল।

তবুও, গভীর পুনরাবৃত্তি কলগুলি কখনও কখনও পছন্দসই হয়। আনবাউন্ড অ্যাক্টিভ কলগুলির ভাষার সমর্থন প্রয়োজন এমন ভাষার প্রয়োগে (যেখানে কলটির গভীরতা কেবলমাত্র সম্পূর্ণ স্মৃতি দ্বারা সীমাবদ্ধ), সাধারণ সি ++ বাস্তবায়নগুলির মতো লক্ষ্য ভাষা অ্যাক্টিভেশন রেকর্ড হিসাবে সরাসরি (সমসাময়িক) নেটিভ কল স্ট্যাকটি ব্যবহার করা অসম্ভব । সমস্যাটি সমাধান করার জন্য, অ্যাক্টিভেশন রেকর্ড নির্মাণের বিকল্প উপায়গুলি প্রয়োজন। উদাহরণস্বরূপ, এসএমএল / এনজে স্পষ্টভাবে গাদাতে ফ্রেম বরাদ্দ করে এবং ক্যাকটাস স্ট্যাক ব্যবহার করে । এই ধরনের অ্যাক্টিভেশন রেকর্ড ফ্রেমের জটিল বরাদ্দ সাধারণত কল স্ট্যাক ফ্রেমের তত দ্রুত হয় না। যাইহোক, যদি এই জাতীয় ভাষাগুলি যথাযথ পুচ্ছ পুনরাবৃত্তির গ্যারান্টি সহ আরও প্রয়োগ করা হয়, অবজেক্ট ল্যাঙ্গুয়েজে সরাসরি স্ট্যাক বরাদ্দ (অর্থাত্ ভাষায় "অবজেক্ট" রেফারেন্স হিসাবে সংরক্ষণ করা হয় না, তবে নেটিভ আদিম মানগুলি যা ভাগ না করা সি ++ অবজেক্টগুলিতে এক থেকে এক ম্যাপ করা যায়) আরও বেশি জটিল সাধারণভাবে কর্মক্ষমতা জরিমানা। এই জাতীয় ভাষা বাস্তবায়নের জন্য সি ++ ব্যবহার করার সময়, পারফরম্যান্সের প্রভাবগুলি অনুমান করা শক্ত is


Stl এর মত, কম এবং কম লোক এই ধারণাগুলি পৃথক করতে ইচ্ছুক। Cppcon2018 এ থাকা অনেকগুলি heapঘন ঘন ব্যবহার করে ।

@ 陳 力 কিছু নির্দিষ্ট বাস্তবায়ন মাথায় রেখে "heালু" দ্ব্যর্থহীন হতে পারে, তাই এটি কখনও কখনও ঠিক হয়ে যায়। যদিও এটি "সাধারণভাবে" অপ্রয়োজনীয়।
ফ্র্যাঙ্কএইচবি

ইন্টারপ কী?

@ 陳 力 আমি সি ++ উত্সের সাথে জড়িত যে কোনও ধরণের "নেটিভ" কোড আন্তঃব্যক্তিকে বোঝাতে চাইছি, উদাহরণস্বরূপ, কোনও ইনলাইন অ্যাসেম্বলি কোড। এটি অনুমানের উপর নির্ভর করে (এবিআই এর) সি ++ দ্বারা আচ্ছাদিত নয়। সিওএম ইন্টারপ (কিছু উইন্ডোজ-নির্দিষ্ট এবিআই-এর ভিত্তিতে) কম-বেশি অনুরূপ, যদিও এটি বেশিরভাগ সি ++ এর চেয়ে নিরপেক্ষ।
ফ্র্যাঙ্কএইচবি

2

এই ধরনের অপ্টিমাইজেশন সম্পর্কে একটি সাধারণ পয়েন্ট আছে।

আপনি যে অপ্টিমাইজেশন পাবেন সেটি প্রোগ্রামের কাউন্টারে আসলে সেই পরিমাণের সাথে আনুপাতিক।

আপনি যদি প্রোগ্রামটির কাউন্টারটি নমুনা করেন তবে আপনি এটি জানতে পারেন যে এটি কোথায় সময় ব্যয় করে এবং এটি সাধারণত কোডের একটি ক্ষুদ্র অংশে থাকে এবং প্রায়শই লাইব্রেরির রুটিনগুলিতে আপনার নিয়ন্ত্রণ থাকে না।

যদি আপনি এটি আপনার বস্তুর হিপ-বরাদ্দে বেশি সময় ব্যয় করতে দেখেন তবে এগুলি স্ট্যাক-বরাদ্দ করা লক্ষণীয়ভাবে দ্রুত হবে।


2

স্ট্যাক বরাদ্দ প্রায় সর্বদা গাদা বরাদ্দের চেয়ে দ্রুত বা দ্রুততর হবে, যদিও স্তূপ বরাদ্দকারীদের পক্ষে কেবল স্ট্যাক ভিত্তিক বরাদ্দ কৌশলটি ব্যবহার করা সম্ভব।

তবে স্ট্যাক বনাম হিপ ভিত্তিক বরাদ্দের সামগ্রিক কর্মক্ষমতা (বা স্থানীয়ভাবে বনাম বাহ্যিক বরাদ্দ) এর সামগ্রিক কার্যকারিতা নিয়ে কাজ করার ক্ষেত্রে আরও বড় সমস্যা রয়েছে issues সাধারণত, গাদা (বাহ্যিক) বরাদ্দটি ধীর হয় কারণ এটি বিভিন্ন ধরণের বরাদ্দ এবং বরাদ্দের নিদর্শনগুলির সাথে কাজ করে। আপনি যে বরাদ্দ ব্যবহার করছেন তার সুযোগ হ্রাস করা (এটিকে অ্যালগোরিদম / কোডে স্থানীয় করে তোলা) কোনও বড় পরিবর্তন ছাড়াই কর্মক্ষমতা বাড়ানোর প্রবণতা বাড়বে। আপনার বরাদ্দের নিদর্শনগুলিতে আরও ভাল কাঠামো যুক্ত করা, উদাহরণস্বরূপ, বরাদ্দ এবং ডিওলোকেশন জোড়গুলিতে লিফোর ক্রম চাপানো আপনার বরাদ্দকারীর কার্যকারিতা আরও সহজ এবং আরও কাঠামোগত উপায়ে উন্নত করতে পারে। অথবা, আপনি আপনার নির্দিষ্ট বরাদ্দের প্যাটার্নের জন্য সুরযুক্ত একটি বরাদ্দ ব্যবহার করতে বা লিখতে পারেন; বেশিরভাগ প্রোগ্রাম ঘন ঘন কয়েকটি আলাদা আকারের বরাদ্দ করে, সুতরাং কয়েকটি স্থির (পছন্দসই হিসাবে পরিচিত) মাপের লুকোসাইড বাফারের উপর ভিত্তি করে একটি গাদা অত্যন্ত ভাল অভিনয় করবে। উইন্ডোজ এই কারণেই তার লো-ফ্র্যাগমেন্টেশন-হিপ ব্যবহার করে।

অন্যদিকে, যদি আপনার খুব বেশি থ্রেড থাকে তবে 32-বিট মেমরির পরিসরে স্ট্যাক-ভিত্তিক বরাদ্দও বিপদে পূর্ণ। স্ট্যাকের একটি স্বচ্ছ মেমরির পরিসর প্রয়োজন, সুতরাং আপনার যত বেশি থ্রেড থাকবে, স্ট্যাকের ওভারফ্লো ছাড়াই চালানোর জন্য আপনার আরও ভার্চুয়াল ঠিকানার স্থানের প্রয়োজন হবে। এটি now৪-বিট নিয়ে (আপাতত) কোনও সমস্যা হবে না, তবে এটি অবশ্যই প্রচুর থ্রেড সহ দীর্ঘ চলমান প্রোগ্রামগুলিতে সর্বনাশ করতে পারে। টুকরো টুকরো করার কারণে ভার্চুয়াল ঠিকানার জায়গার বাইরে চলে যাওয়া সর্বদা ব্যথা হয়।


আমি আপনার প্রথম বাক্যটির সাথে একমত নই।
ব্রায়ান beuning

2

অন্যরা যেমন বলেছে, সাধারণভাবে স্ট্যাক বরাদ্দ অনেক দ্রুত হয়।

তবে, যদি আপনার অবজেক্টগুলি অনুলিপি করা ব্যয়বহুল হয় তবে স্ট্যাকের মধ্যে বরাদ্দ করা যদি আপনি সাবধান না হন তবে পরে অবজেক্টগুলি ব্যবহার করার সময় একটি বিশাল কর্মক্ষমতা হিট হতে পারে।

উদাহরণস্বরূপ, আপনি যদি স্ট্যাকের জন্য কিছু বরাদ্দ করেন, এবং তারপরে এটি একটি পাত্রে রাখেন, তবে গাদাতে বরাদ্দ করা এবং পয়েন্টারে পয়েন্টারটি সংরক্ষণ করা ভাল ছিল (যেমন একটি স্টাড :: শেয়ার্ড_পিটার <> সহ)। একই জিনিস সত্য যদি আপনি মান এবং অন্যান্য অনুরূপ পরিস্থিতি অনুসারে অবজেক্টগুলি পাস বা ফিরিয়ে দিচ্ছেন।

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


2
class Foo {
public:
    Foo(int a) {

    }
}
int func() {
    int a1, a2;
    std::cin >> a1;
    std::cin >> a2;

    Foo f1(a1);
    __asm push a1;
    __asm lea ecx, [this];
    __asm call Foo::Foo(int);

    Foo* f2 = new Foo(a2);
    __asm push sizeof(Foo);
    __asm call operator new;//there's a lot instruction here(depends on system)
    __asm push a2;
    __asm call Foo::Foo(int);

    delete f2;
}

এটি asm এর মতো হবে। আপনি যখন থাকবেন তখন স্ট্যান্ড (স্বয়ংক্রিয় স্টোরেজ) funcf1এবং পয়েন্টার f2বরাদ্দ করা হয়েছে। এবং এইভাবে, ফু f1(a1)স্ট্যাক পয়েন্টার (কোন নির্দেশ প্রভাব esp), এটা বরাদ্দ দেওয়া হয়েছে, যদি funcচায় সদস্য পেতে f1, এটা নির্দেশ ভালো কিছু হল: lea ecx [ebp+f1], call Foo::SomeFunc()। স্ট্যাকের বরাদ্দ হওয়া অন্যটি জিনিসটিকে কেউ মনে করতে পারে মেমোরিটি এমন কিছু FIFO, FIFOআপনি যখন কোনও ফাংশনে যান এবং এমন কিছু বরাদ্দ করেন, ঠিক তখনই int i = 0ঘটেছিল।


1

এটি আগে উল্লেখ করা হয়েছিল যে স্ট্যাক বরাদ্দকরণ কেবল স্ট্যাক পয়েন্টারটি সরিয়ে চলেছে, এটি বেশিরভাগ আর্কিটেকচারের একক নির্দেশনা। গাদা বরাদ্দের ক্ষেত্রে সাধারণত যা হয় তার সাথে তার তুলনা করুন ।

অপারেটিং সিস্টেমটি মুক্ত অংশের প্রারম্ভিক ঠিকানা এবং মুক্ত অংশের আকারের পয়েন্টার সমন্বিত পে-লোড ডেটাযুক্ত লিঙ্কযুক্ত তালিকা হিসাবে মুক্ত মেমরির অংশগুলি বজায় রাখে। মেমরির এক্স বাইটগুলি বরাদ্দ করার জন্য, লিঙ্কের তালিকাটি অতিক্রম করা হয়েছে এবং প্রতিটি নোটটি যথাক্রমে পরিদর্শন করা হবে, এটির আকার কমপক্ষে এক্স কিনা তা পরীক্ষা করে size মাপের এক্স এবং পিএক্স। সংযুক্ত তালিকা আপডেট করা হয় এবং প্রথম অংশের পয়েন্টারটি ফিরে আসে।

আপনি দেখতে পাচ্ছেন যে, আপনি কী পরিমাণ মেমরি অনুরোধ করছেন, মেমরিটি কীভাবে খণ্ডিত হয়েছে ইত্যাদি বিভিন্ন কারণের উপর হিপ বরাদ্দ নির্ভর করে।


1

সাধারণভাবে, উপরে প্রায় প্রতিটি উত্তর দ্বারা উল্লিখিত হিসাবে গাদা বরাদ্দ চেয়ে স্ট্যাক বরাদ্দ দ্রুত হয়। একটি স্ট্যাক পুশ বা পপ হল ও (1), যেখানে বরাদ্দকরণ বা একটি গাদা থেকে মুক্ত করার জন্য পূর্ববর্তী বরাদ্দগুলির পদচারণার প্রয়োজন হতে পারে। তবে আপনি সাধারণত আঁট, কর্মক্ষমতা-নিবিড় লুপগুলিতে বরাদ্দ করা উচিত নয়, তাই পছন্দটি সাধারণত অন্যান্য কারণগুলিতে নেমে আসে।

এই পার্থক্যটি করা ভাল হতে পারে: আপনি গাদা একটি "স্ট্যাক বরাদ্দকারী" ব্যবহার করতে পারেন। কড়া কথায় বলতে গেলে আমি বরাদ্দের অবস্থানের চেয়ে বরাদ্দের আসল পদ্ধতিটি বোঝাতে স্ট্যাক বরাদ্দ গ্রহণ করি। যদি আপনি প্রকৃত প্রোগ্রাম স্ট্যাকের উপর প্রচুর পরিমাণে বরাদ্দ করেন তবে বিভিন্ন কারণে এটি খারাপ হতে পারে। অন্যদিকে, যখন সম্ভব হয় তখন স্তূপে বরাদ্দ দেওয়ার জন্য স্ট্যাক পদ্ধতি ব্যবহার করা আপনি বরাদ্দ পদ্ধতির জন্য সেরা পছন্দ choice

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


1

মন্তব্য করুন যে গাদা ও বরাদ্দের তুলনায় স্ট্যাক বেছে নেওয়ার সময় বিবেচনাগুলি সাধারণত গতি এবং কর্মক্ষমতা সম্পর্কে নয়। স্ট্যাকটি স্ট্যাকের মতো কাজ করে, যার অর্থ এটি ব্লকগুলি ধাক্কা দেওয়ার জন্য এবং এগুলি আবার পপিংয়ের জন্য ভালভাবে উপযুক্ত, শেষ অবধি, প্রথমে বাইরে out পদ্ধতির সম্পাদনও স্ট্যাকের মতো, সর্বশেষে প্রবেশ করা পদ্ধতিটি প্রথমে বেরিয়ে আসে। বেশিরভাগ প্রোগ্রামিং ভাষায়, কোনও পদ্ধতিতে প্রয়োজনীয় সমস্ত ভেরিয়েবলগুলি কেবল প্রক্রিয়া সম্পাদনের সময় দৃশ্যমান হবে, সুতরাং এগুলি একটি পদ্ধতিতে প্রবেশের সময় চাপ দেওয়া হয় এবং প্রস্থান বা ফিরে আসার পরে স্ট্যাকটি পপ করে।

এখন উদাহরণস্বরূপ যেখানে স্ট্যাকটি ব্যবহার করা যাবে না:

Proc P
{
  pointer x;
  Proc S
  {
    pointer y;
    y = allocate_some_data();
    x = y;
  }
}

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


0

অন্যান্য অ্যাপ্লিকেশন কোড এবং ব্যবহার আপনার ফাংশনকে প্রভাবিত করতে পারে বলে কখনই অকাল অনুমান করবেন না। সুতরাং ফাংশনটির দিকে তাকানো কোনও বিচ্ছিন্নতা নয়।

আপনি যদি অ্যাপ্লিকেশনে গুরুতর হন তবে এটি ভিটিউন করুন বা অনুরূপ কোনও প্রোফাইলিং সরঞ্জাম ব্যবহার করুন এবং হটস্পটগুলি দেখুন।

Ketan


-1

আমি বলতে চাই যে প্রকৃতপক্ষে জিসিসি কোড জেনারেট করে (আমি ভিএসও মনে করি) স্ট্যাক বরাদ্দ করার ওভারহেড নেই doesn't

নিম্নলিখিত ফাংশন জন্য বলুন:

  int f(int i)
  {
      if (i > 0)
      {   
          int array[1000];
      }   
  }

নিম্নলিখিত কোড উত্পন্ন হয়:

  __Z1fi:
  Leh_func_begin1:
      pushq   %rbp
  Ltmp0:
      movq    %rsp, %rbp
  Ltmp1:
      subq    $**3880**, %rsp <--- here we have the array allocated, even the if doesn't excited.
  Ltmp2:
      movl    %edi, -4(%rbp)
      movl    -8(%rbp), %eax
      addq    $3880, %rsp
      popq    %rbp
      ret 
  Leh_func_end1:

সুতরাং আপনার কত স্থানীয় ভেরিয়েবল রয়েছে (এমনকি ভিতরে থাকলে বা স্যুইচ করলে) কেবল 3838 অন্য মানটিতে পরিবর্তিত হবে। আপনার স্থানীয় ভেরিয়েবল না থাকলে এই নির্দেশের কেবলমাত্র কার্যকর করা দরকার। সুতরাং স্থানীয় ভেরিয়েবল বরাদ্দ ওভারহেড নেই।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.