সি ++ এর সাধারণ পয়েন্টারগুলির তুলনায় স্মার্ট পয়েন্টারগুলির ওভারহেড কত?


107

সি ++ 11 এ সাধারণ পয়েন্টারগুলির তুলনায় স্মার্ট পয়েন্টারগুলির ওভারহেড কত? অন্য কথায়, আমি যদি স্মার্ট পয়েন্টার ব্যবহার করি তবে কি আমার কোডটি ধীর হতে চলেছে এবং যদি তাই হয় তবে কত ধীর?

বিশেষত, আমি সি ++ 11 std::shared_ptrএবং std::unique_ptr

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

উদাহরণস্বরূপ, আমি একটি সাধারণ পয়েন্টারের পরিবর্তে কোনও ফাংশন থেকে একটি স্মার্ট পয়েন্টার ফিরিয়ে দিই:

std::shared_ptr<const Value> getValue();
// versus
const Value *getValue();

অথবা, উদাহরণস্বরূপ, যখন আমার কোনও ফাংশন একটি সাধারণ পয়েন্টারের পরিবর্তে কোনও স্মার্ট পয়েন্টারটিকে প্যারামিটার হিসাবে গ্রহণ করে:

void setValue(std::shared_ptr<const Value> val);
// versus
void setValue(const Value *val);

9
জানার একমাত্র উপায় হ'ল আপনার কোড বেঞ্চমার্ক করা।
বেসিল স্টারিঙ্কেভিচ

আপনি কোনটি বোঝাতে চান? std::unique_ptrবা std::shared_ptr?
স্টিফান

11
উত্তর 42. (অন্য কথায়, কে জানে, আপনি আপনার কোড প্রোফাইল এবং আপনার টিপিক্যাল কাজের চাপের জন্য আপনার হার্ডওয়ার উপর বোঝা দরকার।) হল
নিম

আপনার অ্যাপ্লিকেশনটির স্মার্ট পয়েন্টারগুলির তাৎপর্যপূর্ণ হওয়ার জন্য চূড়ান্ত ব্যবহার করা দরকার।
ব্যবহারকারী2672165

একটি সাধারণ সেটার ফাংশনে একটি শেয়ার্ড_পিটার ব্যবহারের ব্যয়টি ভয়ানক এবং এটি একাধিক 100% ওভারহেড যুক্ত করবে।
লোথার

উত্তর:


186

std::unique_ptr মেমরির ওভারহেড কেবল তখনই থাকে যখন আপনি এটিকে কিছু অ-তুচ্ছ ডিফল্টর সরবরাহ করেন।

std::shared_ptr রেফারেন্স কাউন্টারটির জন্য সবসময় মেমরির ওভারহেড থাকে যদিও এটি খুব কম।

std::unique_ptr কেবল কনস্ট্রাক্টরের সময় সময় ওভারহেড থাকে (যদি এটি সরবরাহকৃত মুছে ফেলা কপি করতে হয় এবং / অথবা পয়েন্টারটি নাল-ইনিশিয়ালাইজ করতে হয়) এবং ডেস্ট্রাক্টরের সময় (মালিকানাধীন বস্তুটি ধ্বংস করতে) destroy

std::shared_ptrকনস্ট্রাক্টর (রেফারেন্স কাউন্টার তৈরি করতে), ডেস্ট্রাক্টর (রেফারেন্স কাউন্টারকে হ্রাস করতে এবং সম্ভবত অবজেক্টটি ধ্বংস করতে) এবং অ্যাসাইনমেন্ট অপারেটরে (রেফারেন্স কাউন্টারকে বাড়িয়ে তোলার) জন্য সময় ওভারহেড থাকে over থ্রেড-সুরক্ষার গ্যারান্টিগুলির কারণে std::shared_ptr, এই বৃদ্ধিগুলি / হ্রাসগুলি পারমাণবিক, এইভাবে আরও কিছু ওভারহেড যুক্ত হয়।

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

সংক্ষেপে, কিছু ওভারহেড রয়েছে, তবে আপনি অবিচ্ছিন্নভাবে স্মার্ট পয়েন্টার তৈরি এবং ধ্বংস না করে কোডটি ধীর করা উচিত নয়।


11
unique_ptrডেস্ট্রাক্টরের কোনও ওভারহেড নেই। এটি কাঁচা পয়েন্টার সহ ঠিক একই রকম করে।
আর মার্টিনহো ফার্নান্দেস

6
@ আর মার্টিনহো ফার্নান্দেস নিজেই কাঁচা পয়েন্টারের সাথে তুলনা করে, এটি ডেস্ট্রাক্টরে সময় ওভারহেড রাখে, যেহেতু কাঁচা পয়েন্টার ডেস্ট্রাক্টর কিছুই করেন না। কোনও কাঁচা পয়েন্টার সম্ভবত কীভাবে ব্যবহৃত হবে তার তুলনা করে এর অবশ্যই কোনও ওভারহেড নেই।
লিসিয়াস

4
ভাগ করা অংশ / নির্মাণ / অ্যাসাইনমেন্ট ব্যয়ের সেই অংশটি মূল্যহীন থ্রেড সুরক্ষার কারণে
জো

4
এছাড়াও, ডিফল্ট কনস্ট্রাক্টর সম্পর্কে কি std::unique_ptr? আপনি যদি এটি নির্মাণ করেন std::unique_ptr<int>তবে অভ্যন্তরীণটি আপনার পছন্দ হয় বা না int*پسند করে nullptrতা আরম্ভ করে ।
মার্টিন দ্রোজডিক

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

29

আমার উত্তর অন্যদের থেকে পৃথক এবং আমি সত্যিই ভাবছি যে তারা কখনও কোডটি প্রোফাইল করেছিলেন।

কন্ট্রোল ব্লকের জন্য মেমরি বরাদ্দ থাকার কারণে শেয়ারড_পিটারের একটি উল্লেখযোগ্য ওভারহেড রয়েছে (যা রেফার কাউন্টার এবং সমস্ত দুর্বল রেফারেন্সের জন্য একটি পয়েন্টার তালিকাকে রাখে)। এটির কারণে এবং std :: सामायिक_ptr সর্বদা একটি 2 পয়েন্টার টিপল থাকে (বস্তুর কাছে একটি, একটি নিয়ন্ত্রণ ব্লকের সাথে) এর কারণে এটির একটি বিশাল স্মৃতি ওভারহেড রয়েছে।

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

যদি ফাংশনটি মালিকানা পরিচালনার সাথে জড়িত না হয় তবে আপনার কেন এটি করা উচিত নয় ts অন্যথায় "শেয়ারড_পট্রেজেট ()" ব্যবহার করুন। এটি নিশ্চিত করার জন্য ডিজাইন করা হয়নি যে কোনও সাধারণ ফাংশন কল চলাকালীন আপনার অবজেক্টটি মারা যায় না।

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

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

আপনি যদি আরও জানতে চান আপনি নিকোলাই এম জোসুটিস "সি ++ তে শেয়ার্ড পয়েন্টারগুলির আসল দাম" সম্পর্কে ভাল আলোচনা দেখতে পারেন https://vimeo.com/131189627
এটি লেখার প্রতিবন্ধকতা, পারমাণবিকতার জন্য বাস্তবায়নের বিশদ এবং সিপিইউ আর্কিটেকচারের গভীরে যায় goes লকস ইত্যাদি একবার শুনলে আপনি কখনও এই বৈশিষ্ট্যটি সস্তা হওয়ার বিষয়ে কথা বলতে পারবেন না। আপনি যদি মাত্রার ধীরতার প্রমাণ চান তবে প্রথম ৪৮ মিনিট এড়িয়ে যান এবং সর্বত্র শেয়ার্ড পয়েন্টার ব্যবহার করার সময় তাকে চলমান উদাহরণ কোডটি দেখুন যা 180 গুণ ধীর (-O3 দিয়ে সংকলিত) অবধি চলে।


আপনার উত্তরের জন্য ধন্যবাদ! আপনি কোন প্ল্যাটফর্মে প্রোফাইল করেছেন? আপনি কিছু ডেটা দিয়ে আপনার দাবিগুলি ব্যাক আপ করতে পারেন?
ভেনেমো

আমি দেখানোর জন্য কোন নম্বর আছে, কিন্তু আপনি নিকো Josuttis আলাপ মধ্যে কিছু জানতে পারেন vimeo.com/131189627
লোথার

7
কখনও শুনেছেন std::make_shared()? এছাড়াও, আমি খারাপ একটু বিরক্তিকর হচ্ছে স্থূল অপব্যবহার বিক্ষোভ এটি ...
Deduplicator

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

26

সমস্ত কোডের পারফরম্যান্সের মতোই, হার্ড তথ্য পাওয়ার একমাত্র সত্যিকারের নির্ভরযোগ্য উপায় হ'ল মেশিন কোডটি পরিমাপ করা এবং / বা পরীক্ষা করা

যে বলেন, সহজ যুক্তি যে বলে

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

  • জন্য shared_ptrআপনি, প্রাথমিক সৃষ্টি মধ্যে কিছু উপরি আশা করতে পারেন যেহেতু যে একটি নিয়ন্ত্রণ ব্লক গতিশীল বরাদ্দ জড়িত থাকে, এবং গতিশীল বরাদ্দ খুব C ++ অন্য কোন মৌলিক অপারেশন তুলনায় ধীর হবে (ব্যবহার করবেন make_sharedযে ওভারহেড কমানোর জন্য যখন কার্যত সম্ভব)।

  • এছাড়াও shared_ptrরেফারেন্স গণনা বজায় রাখার ক্ষেত্রে কিছুটা ন্যূনতম ওভারহেড রয়েছে, উদাহরণস্বরূপ যখন shared_ptrমান অনুসারে পাস করার সময় , তবে এর জন্য কোনও ওভারহেড নেই unique_ptr

উপরের প্রথম পয়েন্টটি মাথায় রেখে, আপনি যখন পরিমাপ করেন, তখন ডিবাগ এবং রিলিজ উভয়ই তা তৈরি করে।

আন্তর্জাতিক সি ++ প্রমিতকরণ কমিটি একটি প্রকাশিত হয়েছে কর্মক্ষমতার উপর প্রযুক্তিগত রিপোর্ট , কিন্তু এই 2006 সালে ছিল, আগে unique_ptrএবং shared_ptrমান লাইব্রেরিতে যোগ করা হয়েছে। তবুও, স্মার্ট পয়েন্টারগুলি সেই সময়ে পুরানো টুপি ছিল, তাই প্রতিবেদনটিও এটি বিবেচনা করে considered প্রাসঙ্গিক অংশ উদ্ধৃত:

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

একটি বুদ্ধিমান অনুমান হিসাবে, "আর্টের রাজ্যের মধ্যেই ভাল" 2014 এর প্রথম দিকে, আজ সবচেয়ে জনপ্রিয় সংকলকগুলির সাথে অর্জন করা হয়েছে।


আমি দয়া করে আমার প্রশ্নের সাথে যুক্ত করা মামলাগুলি সম্পর্কে আপনার উত্তরে কিছু বিবরণ অন্তর্ভুক্ত করতে পারেন?
ভেনেমো

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

একটি সমস্যা আমি দেখেছি হ'ল একবার শেয়ার্ড_প্টার সার্ভারে ব্যবহার করা হয়, তারপরে শেয়ারড_প্টারগুলির ব্যবহার প্রসারিত হতে শুরু করে এবং শীঘ্রই শেয়ারড_প্টারগুলি ডিফল্ট মেমরি পরিচালনার কৌশলতে পরিণত হয়। সুতরাং এখন আপনি বার বার 1-3% বিমূর্ততা জরিমানা নিয়েছেন যা বারবার নেওয়া হয়।
নাথান ডরোমাল

আমি মনে করি একটি ডিবাগ বিল্ডমার্কিং চিহ্নিতকরণ একটি সম্পূর্ণ এবং সম্পূর্ণ সময় নষ্ট
পল চাইল্ডস

14

অন্য কথায়, আমি যদি স্মার্ট পয়েন্টার ব্যবহার করি তবে কি আমার কোডটি ধীর হতে চলেছে এবং যদি তাই হয় তবে কত ধীর?

ধীর? সম্ভবত না, যদি না আপনি শেয়ারড_প্টার্স ব্যবহার করে একটি বিশাল সূচক তৈরি না করে থাকেন এবং আপনার কম্পিউটারের পয়েন্টে এতক্ষণের স্মৃতি নেই যে কোনও বৃদ্ধ মহিলা যেমন দূর থেকে অসহনীয় শক্তিতে মাটিতে ডুবে যায় rable

আপনার কোডটি কী ধীর করে দেবে তা হ'ল আলস্য অনুসন্ধান, অপ্রয়োজনীয় লুপ প্রক্রিয়াজাতকরণ, ডেটার বিশাল কপি এবং ডিস্কে প্রচুর রাইটিং অপারেশন (শত শত) is

স্মার্ট পয়েন্টারের সুবিধাগুলি সবই পরিচালনার সাথে সম্পর্কিত। তবে ওভারহেড কি প্রয়োজনীয়? এটি আপনার বাস্তবায়নের উপর নির্ভর করে। ধরা যাক আপনি 3 টি ধাপের অ্যারেতে পুনরাবৃত্তি করছেন, প্রতিটি পর্বে 1024 টি উপাদানের অ্যারে রয়েছে। smart_ptrএই প্রক্রিয়াটির জন্য একটি তৈরি করা ওভারকিল হতে পারে, যেহেতু পুনরাবৃত্তিটি সম্পন্ন হওয়ার পরে আপনি জানবেন আপনাকে এটি মুছতে হবে। সুতরাং আপনি একটি ব্যবহার না করে অতিরিক্ত স্মৃতি অর্জন করতে পারেন smart_ptr...

তবে আপনি কি সত্যিই তা করতে চান?

একটি একক মেমরি ফাঁস আপনার পণ্যকে সময়মতো ব্যর্থ করে তুলতে পারে (আসুন বলি যে আপনার প্রোগ্রামটি প্রতি ঘন্টা 4 মেগাবাইট ফাঁস হয়, একটি কম্পিউটার ভাঙ্গতে কয়েক মাস সময় লাগবে, তবুও এটি ভেঙে যাবে, আপনি এটি জানেন কারণ ফাঁস রয়েছে) ।

"আপনার সফ্টওয়্যারটি 3 মাসের জন্য নিশ্চিত, তারপরে, আমাকে পরিষেবার জন্য কল করুন" বলার মতো like

সুতরাং শেষ পর্যন্ত এটি সত্যিই একটি বিষয় ... আপনি এই ঝুঁকি সামলাতে পারেন? শত শত বিভিন্ন বস্তুর উপর আপনার ইনডেক্সিং পরিচালনা করতে কোনও কাঁচা পয়েন্টার ব্যবহার করা মেমরির নিয়ন্ত্রণ হ্রাস করার পক্ষে মূল্যবান।

উত্তরটি যদি হ্যাঁ হয় তবে একটি কাঁচা পয়েন্টার ব্যবহার করুন।

আপনি যদি এটি বিবেচনা করতে নাও চান তবে এটি smart_ptrএকটি ভাল, কার্যকর এবং দুর্দান্ত সমাধান।


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

@ পালাদিন হ্যাঁ, আপনি যদি নিজের স্মৃতি পরিচালনা করতে পারেন তবে smart_ptrবড় দলগুলির পক্ষে সত্যই কার্যকর
ক্লাওর্ডর্ডজজ

4
আমি ইউনিক_পিটার ব্যবহার করি, এটি অনেক কিছু সহজ করে দেয় তবে শেয়ারড_পিটার পছন্দ করে না, রেফারেন্স গণনা খুব দক্ষ জিসি নয় এবং
এটিও

4
@ পালাদিন আমি যদি সমস্ত কিছু সজ্জিত করতে পারি তবে আমি কাঁচা পয়েন্টার ব্যবহার করার চেষ্টা করি। যদি এটি এমন কিছু হয় যা আমি যুক্তির মতো পুরো জায়গা জুড়ে চলে যাব তবে সম্ভবত আমি একটি স্মার্ট_পিটার বিবেচনা করব। আমার বেশিরভাগ অনন্য_পিটারগুলি মূল প্রয়োগ বা চলমান পদ্ধতির মতো বড় বাস্তবায়নে ব্যবহৃত হয়
ক্লাওর্ডর্ডজিজে

@ লোথার আমি দেখতে পেয়েছি যে আমি আপনার উত্তরে যা বলেছি তার মধ্যে Thats why you should not do this unless the function is really involved in ownership management
একটিকে প্যারাফ্রেস করা হয়েছে

-1

কেবল এক []ঝলকের জন্য এবং কেবল অপারেটরের জন্য, নিম্নলিখিত কোডটিতে প্রদর্শিত কাঁচা পয়েন্টারের তুলনায় এটি 5X ডলার ধীরে ধীরে, যা gcc -lstdc++ -std=c++14 -O0এই ফলাফলটি ব্যবহার করে সংকলিত এবং আউটপুট করা হয়েছিল:

malloc []:     414252610                                                 
unique []  is: 2062494135                                                
uq get []  is: 238801500                                                 
uq.get()[] is: 1505169542
new is:        241049490 

আমি সি ++ শিখতে শুরু করি, আমি এটি মনে মনে জাগিয়েছি: আপনি সর্বদা আপনার কি করা উচিত তা জানতে হবে এবং আপনার সি ++ এ অন্যেরা কী করেছে তা জানতে আপনার আরও সময় নেওয়া উচিত।

সম্পাদনা

@ মোহন কুমার দ্বারা গণিত হিসাবে, আমি আরও বিশদ সরবরাহ করেছি। জিসিসি সংস্করণটি হ'ল 7.4.0 (Ubuntu 7.4.0-1ubuntu1~14.04~ppa1), উপরের ফলাফলটি যখন -O0ব্যবহৃত হয় তখনই পাওয়া যায় , তবে আমি যখন '-O2' পতাকা ব্যবহার করি তখন আমি এটি পেয়েছিলাম:

malloc []:     223
unique []  is: 105586217
uq get []  is: 71129461
uq.get()[] is: 69246502
new is:        9683

তারপর স্থানান্তরিত clang version 3.9.0, -O0ছিল:

malloc []:     409765889
unique []  is: 1351714189
uq get []  is: 256090843
uq.get()[] is: 1026846852
new is:        255421307

-O2 ছিল:

malloc []:     150
unique []  is: 124
uq get []  is: 83
uq.get()[] is: 83
new is:        54

ঝাঁকুনির -O2ফল আশ্চর্যজনক।

#include <memory>
#include <iostream>
#include <chrono>
#include <thread>

uint32_t n = 100000000;
void t_m(void){
    auto a  = (char*) malloc(n*sizeof(char));
    for(uint32_t i=0; i<n; i++) a[i] = 'A';
}
void t_u(void){
    auto a = std::unique_ptr<char[]>(new char[n]);
    for(uint32_t i=0; i<n; i++) a[i] = 'A';
}

void t_u2(void){
    auto a = std::unique_ptr<char[]>(new char[n]);
    auto tmp = a.get();
    for(uint32_t i=0; i<n; i++) tmp[i] = 'A';
}
void t_u3(void){
    auto a = std::unique_ptr<char[]>(new char[n]);
    for(uint32_t i=0; i<n; i++) a.get()[i] = 'A';
}
void t_new(void){
    auto a = new char[n];
    for(uint32_t i=0; i<n; i++) a[i] = 'A';
}

int main(){
    auto start = std::chrono::high_resolution_clock::now();
    t_m();
    auto end1 = std::chrono::high_resolution_clock::now();
    t_u();
    auto end2 = std::chrono::high_resolution_clock::now();
    t_u2();
    auto end3 = std::chrono::high_resolution_clock::now();
    t_u3();
    auto end4 = std::chrono::high_resolution_clock::now();
    t_new();
    auto end5 = std::chrono::high_resolution_clock::now();
    std::cout << "malloc []:     " <<  (end1 - start).count() << std::endl;
    std::cout << "unique []  is: " << (end2 - end1).count() << std::endl;
    std::cout << "uq get []  is: " << (end3 - end2).count() << std::endl;
    std::cout << "uq.get()[] is: " << (end4 - end3).count() << std::endl;
    std::cout << "new is:        " << (end5 - end4).count() << std::endl;
}


আমি এখনই কোডটি পরীক্ষা করেছি, অনন্য পয়েন্টার ব্যবহার করার সময় এটি কেবলমাত্র 10% ধীর।
মোহন কুমার

8
কখনও কখনও -O0কোড সহ বা ডিবাগ বেনমার্ক। আউটপুট চূড়ান্তভাবে অক্ষম হবে । সর্বদা কমপক্ষে -O2(বা -O3আজকাল কিছু ভেক্টরাইজেশন করা হয়নি বলে -O2) ব্যবহার করুন
ফুলচলভি

4
আপনার কাছে যদি সময় থাকে এবং লিংক সময় অপ্টিমাইজেশন পেতে একটি কফি ব্রেক নিতে -O4 নিতে চান এবং সমস্ত ছোট ছোট বিমূর্ত ফাংশনগুলি ইনলাইন হয়ে যায় এবং বিলুপ্ত হয়।
লোথার

freeআপনার ম্যালোক পরীক্ষায় একটি কল অন্তর্ভুক্ত করা উচিত , এবং delete[]নতুন (বা ভেরিয়েবল aস্ট্যাটিক করা) এর জন্য, কারণ এসগুলি তাদের ধ্বংসকারীদের মধ্যে হুডের নীচে unique_ptrকল delete[]করছে।
আরএনএমএস
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.