আমি যখনই সি ++ স্ট্যান্ডার্ড লাইব্রেরি আইস্ট্রিমের ধীর পারফরম্যান্সের কথা উল্লেখ করি তখন আমার অবিশ্বাসের একটি তরঙ্গে দেখা হয়। তবুও আমার কাছে প্রোফাইলার ফলাফল রয়েছে যা প্রচুর পরিমাণে iostream লাইব্রেরি কোড (সম্পূর্ণ সংকলক অপ্টিমাইজেশান) এ ব্যয় করে, এবং iostreams থেকে ওএস-নির্দিষ্ট আই / ও এপিআই এবং কাস্টম বাফার ম্যানেজমেন্টে পরিবর্তনের প্রবণতা বৃদ্ধির আদেশ দেয়।
সি ++ স্ট্যান্ডার্ড লাইব্রেরি কোন অতিরিক্ত কাজ করছে, এটি কি স্ট্যান্ডার্ডের দ্বারা প্রয়োজনীয় এবং এটি অনুশীলনে কার্যকর? অথবা কিছু সংকলকগুলি মায়োস্ট্রিমগুলির বাস্তবায়ন সরবরাহ করে যা ম্যানুয়াল বাফার পরিচালনার সাথে প্রতিযোগিতামূলক?
benchmarks
বিষয়গুলি সরানোর জন্য, আমি আইস্ট্রিমের অভ্যন্তরীণ বাফারিংয়ের জন্য কয়েকটি সংক্ষিপ্ত প্রোগ্রাম লিখেছি:
- বাইনারি ডেটা একটি http://ideone.com/2PPYw- এ স্থাপন করা
ostringstream
- বাইনারি ডেটা একটি
char[]
বাফার http://ideone.com/Ni5ct- এ রেখে - একটি http://ideone.com/Mj2Fi
vector<char>
ব্যবহার করে বাইনারি ডেটা স্থাপন করাback_inserter
- নতুন :
vector<char>
সাধারণ পুনরাবৃত্তকারী http://ideone.com/9iitv - নতুন : বাইনারি ডেটা সরাসরি http://ideone.com/qc9QA- এ স্থাপন করা
stringbuf
- নতুন :
vector<char>
সাধারণ পুনরাবৃত্তকারী প্লাস সীমা http://ideone.com/YyrKy চেক করুন
নোট করুন যে ostringstream
এবং stringbuf
সংস্করণগুলি কম পুনরাবৃত্তি চালায় কারণ এগুলি এত ধীর।
Ideone তারিখে, ostringstream
প্রায় 3 বার তুলনায় ধীর হয় std:copy
+ + back_inserter
+ + std::vector
, এবং 15 গুন তুলনায় ধীর memcpy
একটি কাঁচা বাফার মধ্যে। আমি যখন আমার আসল অ্যাপ্লিকেশনটি কাস্টম বাফারিংয়ে স্যুইচ করেছি তখন প্রোফাইলিংয়ের আগে এবং পরে সামঞ্জস্য বোধ করে।
এগুলি সমস্ত ইন-মেমোরি বাফার, সুতরাং আইওস্ট্রিমের স্বচ্ছলতা স্লো ডিস্ক আই / ও, খুব বেশি ফ্লাশিং, স্টডিওয়ের সাথে সিঙ্ক্রোনাইজেশন বা সি ++ স্ট্যান্ডার্ড লাইব্রেরির পর্যবেক্ষণে স্বচ্ছলতা বজায় রাখার জন্য ব্যবহার করা অন্য কোনও বিষয়কে দোষ দেওয়া যায় না can't iostream।
অন্যান্য সিস্টেমে বেঞ্চমার্ক এবং সাধারণ বাস্তবায়নগুলি (যেমন জিসিসির লিবিসি ++, ভিজ্যুয়াল সি ++, ইনটেল সি ++) এবং ওভারহেডের কতটুকু মান দ্বারা বাধ্যতামূলক করা হয়েছে সে সম্পর্কে মন্তব্যগুলি দেখে ভাল লাগবে।
এই পরীক্ষার জন্য যুক্তিযুক্ত
বেশিরভাগ লোক সঠিকভাবে উল্লেখ করেছেন যে ফর্ম্যাট করা আউটপুট জন্য আইস্ট্রিমেগুলি সাধারণত ব্যবহৃত হয়। তবে, বাইনারি ফাইল অ্যাক্সেসের জন্য সি ++ স্ট্যান্ডার্ড দ্বারা সরবরাহ করা একমাত্র আধুনিক এপিআই। তবে অভ্যন্তরীণ বাফারিংয়ে পারফরম্যান্স টেস্ট করার আসল কারণটি সাধারণত ফর্ম্যাট করা I / O- এর ক্ষেত্রে প্রযোজ্য: যদি আইস্ট্রিমেস ডিস্ক নিয়ন্ত্রণকারীকে কাঁচা ডেটা সরবরাহ করে না রাখতে পারে, তবে তারা ফর্ম্যাট করার ক্ষেত্রেও যখন দায়বদ্ধ থাকে তখন কীভাবে সম্ভব রাখে?
বেঞ্চমার্ক সময়
এগুলি সমস্ত বাইরের ( k
) লুপের পুনরাবৃত্তির জন্য ।
আইডিয়নে (জিসিসি-৪.৩.৪, অজানা ওএস এবং হার্ডওয়্যার):
ostringstream
: 53 মিলিসেকেন্ডstringbuf
: 27 এমএসvector<char>
এবংback_inserter
: 17.6 এমএসvector<char>
সাধারণ পুনরাবৃত্তকারী সহ: 10.6 এমএসvector<char>
পুনরুক্তি এবং সীমা পরীক্ষা করুন: 11.4 এমএসchar[]
: 3.7 এমএস
আমার ল্যাপটপে (ভিজ্যুয়াল সি ++ ২০১০ x86, cl /Ox /EHsc
উইন্ডোজ Ul আলটিমেট 64৪-বিট, ইন্টেল কোর আই,, ৮ জিবি র্যাম):
ostringstream
: 73.4 মিলিসেকেন্ড, 71.6 এমএসstringbuf
: 21.7 এমএস, 21.3 এমএসvector<char>
এবংback_inserter
: 34.6 এমএস, 34.4 এমএসvector<char>
সাধারণ পুনরাবৃত্তির সাথে: 1.10 এমএস, 1.04 এমএসvector<char>
পুনরুক্তি এবং সীমা পরীক্ষা করুন: 1.11 এমএস, 0.87 এমএস, 1.12 এমএস, 0.89 এমএস, 1.02 এমএস, 1.14 এমএসchar[]
: 1.48 এমএস, 1.57 এমএস
ভিসুয়াল সি ++ 2010 এক্স 86, প্রোফাইল-নির্দেশিত অপ্টিমাইজেশান সঙ্গে cl /Ox /EHsc /GL /c
, link /ltcg:pgi
, রান link /ltcg:pgo
, পরিমাপ:
ostringstream
: 61.2 এমএস, 60.5 এমএসvector<char>
সাধারণ পুনরাবৃত্তির সাথে: 1.04 এমএস, 1.03 এমএস
সাইগউইন জিসিসি ৪.৩.৪ ব্যবহার করে একই ল্যাপটপ, একই ওএস g++ -O3
:
ostringstream
: 62.7 এমএস, 60.5 এমএসstringbuf
: 44.4 এমএস, 44.5 এমএসvector<char>
এবংback_inserter
: 13.5 এমএস, 13.6 এমএসvector<char>
সাধারণ পুনরাবৃত্তির সাথে: 4.1 এমএস, 3.9 এমএসvector<char>
পুনরুক্তি এবং সীমা পরীক্ষা করুন: 4.0 এমএস, 4.0 এমএসchar[]
: 3.57 এমএস, 3.75 এমএস
একই ল্যাপটপ, ভিজ্যুয়াল সি ++ ২০০৮ এসপি 1 cl /Ox /EHsc
,:
ostringstream
: 88.7 এমএস, 87.6 এমএসstringbuf
: 23.3 এমএস, 23.4 এমএসvector<char>
এবংback_inserter
: 26.1 এমএস, 24.5 এমএসvector<char>
সাধারণ পুনরাবৃত্তির সাথে: 3.13 এমএস, 2.48 এমএসvector<char>
পুনরুক্তি এবং সীমা পরীক্ষা করুন: 2.97 এমএস, 2.53 এমএসchar[]
: 1.52 এমএস, 1.25 এমএস
একই ল্যাপটপ, ভিজ্যুয়াল সি ++ 2010 64-বিট সংকলক:
ostringstream
: 48.6 এমএস, 45.0 এমএসstringbuf
: 16.2 এমএস, 16.0 এমএসvector<char>
এবংback_inserter
: 26.3 এমএস, 26.5 এমএসvector<char>
সাধারণ পুনরাবৃত্তির সাথে: 0.87 এমএস, 0.89 এমএসvector<char>
পুনরুক্তি এবং সীমা পরীক্ষা করুন: 0.99 এমএস, 0.99 এমএসchar[]
: 1.25 এমএস, 1.24 এমএস
সম্পাদনা: ফলাফলগুলি কতটা ধারাবাহিক ছিল তা দেখতে দু'বার দৌড়ে যান। বেশ সুসংগত আইএমও
দ্রষ্টব্য: আমার ল্যাপটপে, যেহেতু আমি আইডিয়োন অনুমতি দেয় তার চেয়ে বেশি সিপিইউ সময় ব্যয় করতে পারি, তাই আমি সমস্ত পদ্ধতির জন্য পুনরাবৃত্তির সংখ্যা 1000 এ সেট করেছিলাম। এর অর্থ হ'ল ostringstream
এবং vector
পুনঃনির্ধারণ, যা কেবল প্রথম পাসে হয়, চূড়ান্ত ফলাফলগুলিতে খুব কম প্রভাব ফেলতে পারে।
সম্পাদনা: ওফস, vector
সাধারণ-পুনরাবৃত্তির সাথে একটি বাগ পাওয়া গেছে , পুনরুক্তিটি উন্নত হচ্ছে না এবং তাই অনেকগুলি ক্যাশে হিট ছিল। আমি ভাবছিলাম কিভাবে vector<char>
আউটফর্মিং ছিল char[]
। যদিও vector<char>
এটি char[]
ভিসি ++ ২০১০ এর অধীনে এখনও দ্রুত though
উপসংহার
প্রতিবার ডেটা সংযুক্ত করার পরে আউটপুট স্ট্রিমগুলির বাফারিংয়ের জন্য তিনটি পদক্ষেপ প্রয়োজন:
- ইনকামিং ব্লকটি উপলব্ধ বাফার জায়গার সাথে ফিট করে দেখুন।
- আগত ব্লকটি অনুলিপি করুন।
- ডেটা-এর শেষের পয়েন্টার আপডেট করুন।
আমি পোস্ট করা সর্বশেষ কোড স্নিপেট, " vector<char>
সাধারণ পুনরাবৃত্তকারী প্লাস বাউন্ডস চেক" কেবল এটিই করে না, এটি অতিরিক্ত স্থান বরাদ্দ করে এবং ইনকামিং ব্লকটি ফিট না হলে বিদ্যমান ডেটা সরিয়ে দেয়। ক্লিফোর্ড যেমন উল্লেখ করেছেন, ফাইল আই / ও ক্লাসে বাফারিংয়ের দরকার নেই, এটি কেবল বর্তমান বাফারটিকে ফ্লাশ করে পুনরায় ব্যবহার করবে। সুতরাং এটি বাফারিং আউটপুট ব্যয়ের উপর একটি উপরের আবদ্ধ হওয়া উচিত। ওয়ার্কিং ইন মেমোরি বাফার তৈরি করতে এটি ঠিক প্রয়োজন।
সুতরাং কেন stringbuf
আমি আদর্শ পরীক্ষা করে 2.5x আস্তে আস্তে কম এবং কমপক্ষে 10 গুণ কম ধীর হয়? এটি সাধারণ সরল মাইক্রো-বেঞ্চমার্কে বহুমাত্রিকভাবে ব্যবহৃত হচ্ছে না, যাতে এটি ব্যাখ্যা করে না।
std::ostringstream
ততক্ষণে তার বাফারের আকারটি তাত্ক্ষণিকভাবে বাড়ানোর পক্ষে যথেষ্ট স্মার্ট না হয় std::vector
তবে এটি (এ) বোকা এবং (খ) আই / ও পারফরম্যান্স সম্পর্কে লোকেদের কিছু চিন্তা করা উচিত। যাইহোক, বাফারটি পুনরায় ব্যবহৃত হয়, এটি প্রতিবার পুনরায় স্থানান্তরিত হয় না। এবং std::vector
একটি গতিশীল বর্ধমান বাফার ব্যবহার করছে is আমি এখানে ন্যায্য হওয়ার চেষ্টা করছি।
ostringstream
এবং আপনি যত তাড়াতাড়ি দ্রুত পারফরম্যান্স চান তবে আপনার সরাসরি যাবার কথা বিবেচনা করা উচিত stringbuf
। ostream
ক্লাস নমনীয় বাফার পছন্দ (ফাইল, স্ট্রিং, ইত্যাদি) মাধ্যমে একসাথে লোকেল সচেতন বিন্যাস কার্যকারিতা গিঁট অনুমান করা হয় rdbuf()
এবং তার ভার্চুয়াল ফাংশন ইন্টারফেস। আপনি যদি কোনও ফর্ম্যাটিং না করে থাকেন তবে সেই অতিরিক্ত স্তরের ইন্ডিয়ারেশন অবশ্যই অন্যান্য পদ্ধতির তুলনায় আনুপাতিকভাবে ব্যয়বহুল দেখায়।
ofstream
করার fprintf
সময় থেকে সরানোর মাধ্যমে আমরা অর্ডার বা মাত্রার গতি বাড়িয়েছি । উইনএক্সপিএস 3 তে এমএসভিসি 2008। iostreams কুকুর ধীর।