আই + স্ট্রিমের জন্য সি ++ স্ট্যান্ডার্ড ম্যান্ডেটটি কি খারাপ অভিনয় করে, বা আমি কেবল একটি দুর্বল বাস্তবায়ন নিয়ে কাজ করছি?


196

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

সি ++ স্ট্যান্ডার্ড লাইব্রেরি কোন অতিরিক্ত কাজ করছে, এটি কি স্ট্যান্ডার্ডের দ্বারা প্রয়োজনীয় এবং এটি অনুশীলনে কার্যকর? অথবা কিছু সংকলকগুলি মায়োস্ট্রিমগুলির বাস্তবায়ন সরবরাহ করে যা ম্যানুয়াল বাফার পরিচালনার সাথে প্রতিযোগিতামূলক?

benchmarks

বিষয়গুলি সরানোর জন্য, আমি আইস্ট্রিমের অভ্যন্তরীণ বাফারিংয়ের জন্য কয়েকটি সংক্ষিপ্ত প্রোগ্রাম লিখেছি:

নোট করুন যে 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 গুণ কম ধীর হয়? এটি সাধারণ সরল মাইক্রো-বেঞ্চমার্কে বহুমাত্রিকভাবে ব্যবহৃত হচ্ছে না, যাতে এটি ব্যাখ্যা করে না।


24
আপনি একবারে মিলিয়ন অক্ষর লিখছেন, এবং ভাবছেন যে কেন এটি পূর্বনির্ধারিত বাফারে অনুলিপি করার চেয়ে ধীর?
আনন

19
@ অ্যান: আমি একসাথে চার মিলিয়ন বাইট বাফার করছি, এবং হ্যাঁ আমি কেন আস্তে আছি তা ভাবছি। যদি std::ostringstreamততক্ষণে তার বাফারের আকারটি তাত্ক্ষণিকভাবে বাড়ানোর পক্ষে যথেষ্ট স্মার্ট না হয় std::vectorতবে এটি (এ) বোকা এবং (খ) আই / ও পারফরম্যান্স সম্পর্কে লোকেদের কিছু চিন্তা করা উচিত। যাইহোক, বাফারটি পুনরায় ব্যবহৃত হয়, এটি প্রতিবার পুনরায় স্থানান্তরিত হয় না। এবং std::vectorএকটি গতিশীল বর্ধমান বাফার ব্যবহার করছে is আমি এখানে ন্যায্য হওয়ার চেষ্টা করছি।
বেন ভয়েগ্ট

14
আপনি আসলে কোন কাজটি বেঞ্চমার্ক করার চেষ্টা করছেন? আপনি যদি কোনও ফর্ম্যাট বৈশিষ্ট্য ব্যবহার না করে থাকেন ostringstreamএবং আপনি যত তাড়াতাড়ি দ্রুত পারফরম্যান্স চান তবে আপনার সরাসরি যাবার কথা বিবেচনা করা উচিত stringbufostreamক্লাস নমনীয় বাফার পছন্দ (ফাইল, স্ট্রিং, ইত্যাদি) মাধ্যমে একসাথে লোকেল সচেতন বিন্যাস কার্যকারিতা গিঁট অনুমান করা হয় rdbuf()এবং তার ভার্চুয়াল ফাংশন ইন্টারফেস। আপনি যদি কোনও ফর্ম্যাটিং না করে থাকেন তবে সেই অতিরিক্ত স্তরের ইন্ডিয়ারেশন অবশ্যই অন্যান্য পদ্ধতির তুলনায় আনুপাতিকভাবে ব্যয়বহুল দেখায়।
সিবি বেইলি

5
সত্য অপের জন্য +1। ডাবলস জড়িত লগিং তথ্য আউটপুট আউট ofstreamকরার fprintfসময় থেকে সরানোর মাধ্যমে আমরা অর্ডার বা মাত্রার গতি বাড়িয়েছি । উইনএক্সপিএস 3 তে এমএসভিসি 2008। iostreams কুকুর ধীর।
কিটসুনওয়াইএমজি

6
কমিটির সাইটে এখানে কিছু পরীক্ষা দেওয়া হয়েছে: open-std.org/jtc1/sc22/wg21/docs/D_5.cpp
জোহানেস

উত্তর:


49

আপনার প্রশ্নের সুনির্দিষ্ট বিবরণকে শিরোনামের মতো উত্তর দিচ্ছেন না: সি ++ পারফরম্যান্সের 2006 এর প্রযুক্তিগত প্রতিবেদনে আইওএসটিস্ট্রিমের একটি আকর্ষণীয় বিভাগ রয়েছে (p.68)। আপনার প্রশ্নের সাথে সর্বাধিক প্রাসঙ্গিক বিভাগ 6.1.2 ("মৃত্যুদণ্ডের গতি"):

যেহেতু আইওএসটিম স্ট্রিম প্রসেসিংয়ের নির্দিষ্ট দিকগুলি একাধিক দিকের উপর বিতরণ করা হয়েছে, এটি প্রদর্শিত হয় যে স্ট্যান্ডার্ডটি একটি অদক্ষ বাস্তবায়নকে আদেশ দেয়। তবে এটি নয় - কিছু প্রকার প্রিপ্রোসেসিং ব্যবহার করে বেশিরভাগ কাজ এড়ানো যায়। সাধারণত ব্যবহৃত হওয়ার চেয়ে সামান্য স্মার্ট লিঙ্কারের সাহায্যে এর মধ্যে কিছুটা অদক্ষতা অপসারণ করা সম্ভব। এটি §6.2.3 এবং .26.2.5 এ আলোচনা করা হয়েছে।

যেহেতু 2006 সালে প্রতিবেদনটি লেখা হয়েছিল, কেউ আশা করবে যে সুপারিশগুলির অনেকগুলি বর্তমান সংকলকগুলিতে সংযুক্ত করা হত, তবে সম্ভবত এটি তেমন হয় না।

যেমনটি আপনি উল্লেখ করেছেন, দিকগুলি এতে বৈশিষ্ট্যযুক্ত নাও হতে পারে write()(তবে আমি এটি অন্ধভাবে ধরে নেব না)। সুতরাং বৈশিষ্ট্য কি? আপনার কোডটিতে ostringstreamজি.সি.সি. দিয়ে সংকলিত জি.পি.আর.ফ. চালানো নিম্নলিখিত ব্রেকডাউন দেয়:

  • মধ্যে 44.23% std::basic_streambuf<char>::xsputn(char const*, int)
  • 34.62% ইন std::ostream::write(char const*, int)
  • 12.50% ইন main
  • 6.73% ইন std::ostream::sentry::sentry(std::ostream&)
  • 0.96% ইন std::string::_M_replace_safe(unsigned int, unsigned int, char const*, unsigned int)
  • 0.96% ইন std::basic_ostringstream<char>::basic_ostringstream(std::_Ios_Openmode)
  • 0.00% ইন std::fpos<int>::fpos(long long)

তাই বেশিরভাগ সময় ব্যয় করা হয় xsputn, যা শেষ পর্যন্ত std::copy()প্রচুর পরিমাণে কার্সার পজিশন এবং বাফারগুলি পরীক্ষা করে আপডেট করার পরে ফোন করে থাকে ( c++\bits\streambuf.tccবিশদটি দেখুন)।

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


আইওস্ট্রিমে ফর্ম্যাট সন্নিবেশ / নিষ্কাশন কর্মক্ষমতা সম্পর্কে ভবিষ্যতের প্রশ্নের জন্য দুর্দান্ত তথ্যের মতো মনে হচ্ছে যা আমি সম্ভবত শীঘ্রই জিজ্ঞাসা করব। তবে আমি বিশ্বাস করি না যে এর সাথে কোনও দিকই জড়িত রয়েছে ostream::write()
বেন ভয়েগ্ট

4
প্রোফাইলিংয়ের জন্য +1 (এটি আমার মনে করা একটি লিনাক্স মেশিন?)। তবে, আমি প্রকৃতপক্ষে এক সাথে চারটি বাইট যুক্ত করছি (আসলে sizeof i, তবে সমস্ত সংকলকগুলির সাথে আমি 4-বাইট ব্যবহার করছি int)। এবং এটি আমার কাছে এতটা অবাস্তব বলে মনে হয় না, আপনি প্রতিটি কলটিতে xsputnসাধারণ কোডের মতো কোন আকারের পাস বলে মনে করেন stream << "VAR: " << var.x << ", " << var.y << endl;
বেন ভয়েগ্ট

39
@ বেলডাজ: এই "সাধারণ" কোড উদাহরণটি যা কেবল xsputnপাঁচ বার কল করে এটি একটি লুপের মধ্যে থাকতে পারে যা একটি 10 ​​মিলিয়ন লাইনের ফাইল লিখবে । বড় অংশগুলিতে আইওস্ট্রিমে ডেটা পাঠানো আমার বেঞ্চমার্ক কোডের চেয়ে বাস্তব জীবনের দৃশ্যের তুলনায় অনেক কম। সর্বনিম্ন কল সহ আমাকে কেন বাফার স্ট্রিমে লিখতে হবে ? যদি আমাকে নিজের বাফারিং করতে হয় তবে যাইহোক আইস্ট্রিমেসের কী লাভ? এবং বাইনারি ডেটা সহ, আমার নিজের এটি বাফার করার বিকল্প রয়েছে, যখন কোনও পাঠ্য ফাইলে কয়েক মিলিয়ন সংখ্যা লেখার সময়, বাল্ক বিকল্পটি কেবল উপস্থিত থাকে না, আমি operator <<প্রত্যেকটির জন্য কল করার দরকার নেই ।
বেন ভয়েগ্ট

1
@ বেলডাজ: সাধারণ হিসাবের মাধ্যমে আই / ও কখন আধিপত্য শুরু করবে তা অনুমান করতে পারে। 90 এমবি / সেকেন্ডের গড় লেখার হারে যা বর্তমান গ্রাহক গ্রেড হার্ড ডিস্কের সাধারণ, 4 এমবি বাফারটি ফ্লাশ করতে <45 মিমি লাগে (থ্রুপুট, ওএস রাইটিং ক্যাশের কারণে বিলম্বটি গুরুত্বহীন)। যদি অভ্যন্তরীণ লুপটি চালানো বাফার পূরণ করতে বেশি সময় নেয় তবে সিপিইউ সীমাবদ্ধকরণের কারণ হবে। যদি অভ্যন্তরীণ লুপটি দ্রুত সঞ্চালিত হয়, তবে আমি / ও সীমাবদ্ধ ফ্যাক্টর হব, বা আসল কাজটি করার জন্য কমপক্ষে কিছু সিপিইউ সময় বাকি আছে।
বেন ভয়েগ্ট

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

27

আমি বরং সেখানে ভিজ্যুয়াল স্টুডিও ব্যবহারকারীদের মধ্যে হতাশ, যার পরিবর্তে এটির একটি কৌতুক ছিল:

  • এর ভিজ্যুয়াল স্টুডিও বাস্তবায়নে ostream, sentryবস্তুটি (যা মানক দ্বারা প্রয়োজনীয়) একটি সমালোচনা বিভাগে প্রবেশ করে streambuf(যা প্রয়োজনীয় নয়)। এটি alচ্ছিক বলে মনে হচ্ছে না, সুতরাং আপনি একক থ্রেড দ্বারা ব্যবহৃত স্থানীয় স্ট্রিমের জন্য এমনকি থ্রেড সিঙ্ক্রোনাইজেশনের ব্যয়ও প্রদান করেন, যার জন্য সিঙ্ক্রোনাইজেশনের কোনও প্রয়োজন নেই।

এটি এমন কোডকে আঘাত করে যা ostringstreamবার্তাগুলি বেশ মারাত্মকভাবে ফর্ম্যাট করতে ব্যবহার করে। stringbufসরাসরি ব্যবহার করা ব্যবহার এড়ানো যায় sentryতবে ফর্ম্যাটযুক্ত সন্নিবেশ অপারেটরগুলি সরাসরি streambufএস এ কাজ করতে পারে না । ভিজ্যুয়াল সি ++ ২০১০ এর জন্য, সমালোচনা বিভাগটি ostringstream::writeঅন্তর্নিহিত stringbuf::sputnকলটির তুলনায় তিনটি ফ্যাক্টর দ্বারা ধীর হয়ে যাচ্ছে ।

এ খুঁজছি newlib উপর beldaz এর প্রোফাইলার তথ্য , এটা স্পষ্ট হচ্ছে যে জিসিসি এর sentryভালো পাগল কিছু না। ostringstream::writeজিসিসি এর অধীনে কেবল প্রায় 50% বেশি সময় লাগে stringbuf::sputnতবে stringbufভিসি ++ এর অধীনে এটি নিজেই অনেক ধীর হয়। এবং উভয়ই এখনও vector<char>I / O বাফারিংয়ের জন্য একটি ব্যবহার করার সাথে খুব অপ্রতিরোধ্য তুলনা করেন , যদিও ভিসি ++ এর অধীনে একই মার্জিন দ্বারা নয়।


এই তথ্য এখনও আপ টু ডেট? আফাইক, সি ++ 11 বাস্তবায়ন জিসিসির সাথে প্রেরণ করা এই 'ক্রেজি' লকটি সম্পাদন করে। অবশ্যই, ভিএস 2010 এখনও এটি করে। কেউ কি এই আচরণটি স্পষ্ট করে বলতে পারে এবং যদি 'যার প্রয়োজন নেই' এখনও সি ++ 11 এ ধারণ করে?
এম্লোসকোট

2
@ম্লোসকোট: আমি কোনও থ্রেড-সুরক্ষা প্রয়োজনীয়তা দেখতে পাচ্ছি না sentry... "ক্লাস সেন্ড্রি একটি শ্রেণিকে সংজ্ঞায়িত করে যা ব্যতিক্রম নিরাপদ উপসর্গ এবং প্রত্যয় ক্রিয়াকলাপগুলি করার জন্য দায়ী" " এবং একটি নোট "সেন্ড্রি কনস্ট্রাক্টর এবং ডেস্ট্রাক্টর অতিরিক্ত বাস্তবায়ন-নির্ভর অপারেশনগুলিও করতে পারে" " "আপনি যা ব্যবহার করেন না তার জন্য আপনাকে অর্থ প্রদান করেন না" এর সি ++ নীতিটি থেকেও কেউ বিবেচনা করতে পারে যে সি ++ কমিটি কখনও এইরকম অপ্রয়োজনীয় প্রয়োজনীয়তা অনুমোদন করে না। তবে নির্দ্বিধায় iostream থ্রেড সুরক্ষা সম্পর্কে একটি প্রশ্ন জিজ্ঞাসা করুন।
বেন ভয়েগট

8

আপনি যে সমস্যাটি দেখতে পাচ্ছেন তা লেখার জন্য প্রতিটি কলের চারপাশে ওভারহেড। বিমূর্তকরণের প্রতিটি স্তর যা আপনি যুক্ত করেন (চর [] -> ভেক্টর -> স্ট্রিং -> অস্ট্রিংস্ট্রিম) আরও কয়েকটি ফাংশন কল / রিটার্ন এবং অন্যান্য গৃহকর্মের গ্যাফ যোগ করে - যদি আপনি এটি মিলিয়ন বার কল করেন - যোগ করে।

আমি একবারে দশটি লেখার জন্য আদর্শের দুটি উদাহরণ সংশোধন করেছি। অস্ট্রিংস্ট্রিম সময়টি 53 থেকে 6 এমএসে (প্রায় 10 এক্স উন্নতি) চলে গিয়েছিল যখন চর লুপটি উন্নত হয়েছে (3.7 থেকে 1.5) - দরকারী, তবে কেবল দু'টির একটি কারণ দ্বারা।

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

সংক্ষেপে, অস্ট্রিং স্ট্রিমটি ভাঙা হয়নি, তবে যত দ্রুত আপনি ধাতব কাছে পৌঁছবেন ততই দ্রুত আপনার কোড চলবে। অ্যাসেমব্লারের এখনও কিছু লোকের জন্য সুবিধা রয়েছে।


8
কি ostringstream::write()করতে হবে যে vector::push_back()না? যদি কিছু হয় তবে তা দ্রুত হওয়া উচিত কারণ এটি চারটি পৃথক উপাদানের পরিবর্তে একটি ব্লক সরবরাহ করেছে। কোনও অতিরিক্ত বৈশিষ্ট্য সরবরাহ না করে যদি ostringstreamধীর হয় std::vectorতবে হ্যাঁ আমি এটিকে ভাঙ্গা বলব।
বেন ভয়েগ্ট

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

2
@ বেন ভয়েগ্ট: stringbufসরাসরি ব্যবহার করা সমস্ত ফাংশন কলগুলি সরিয়ে ফেলবে না কারণ stringbufএর সার্বজনীন ইন্টারফেসটি বেস শ্রেণীর পাবলিক অ-ভার্চুয়াল ফাংশনগুলি নিয়ে থাকে যা পরে প্রাপ্ত উপায়ে শ্রেণীর সুরক্ষিত ভার্চুয়াল ফাংশনে প্রেরণ করে।
সিবি বেইলি

2
@ চার্লস: যে কোনও শালীন সংকলকটিতে এটি হওয়া উচিত, যেহেতু পাবলিক ফাংশন কল একটি প্রসঙ্গে জড়িত হবে যেখানে ডায়ামিক টাইপটি সংকলকটির কাছে পরিচিত, এটি নির্দেশকে সরাতে পারে এবং এমনকি সেই কলগুলিকে ইনলাইন করতে পারে।
বেন ভয়েগ্ট

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

1

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

স্টাডি :: ভেক্টরের সাথে ভ্যাক্টরের আকার চূড়ান্ত আকারে শুরু করার সাথে সাথে আপনি চর অ্যারের মতো করে সহজেই সমাধান করা হয়েছে; পরিবর্তে আপনি শূন্যের আকার পরিবর্তন করে অন্যায়ভাবে পারফরম্যান্সকে পঙ্গু করে দিন! এটি খুব কমই তুলনা হয়।

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

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


1
বরাদ্দ অস্ট্রিং স্ট্রিমের সমস্যা বলে মনে হচ্ছে না। তিনি কেবল পরবর্তী পুনরাবৃত্তির জন্য শূন্যের দিকে ফিরে যান। কোনও কাটা কাটা হয়নি। এছাড়াও আমি চেষ্টা করেছিলাম ostringstream.str.reserve(4000000)এবং এতে কোনও পার্থক্য হয়নি।
রডি

আমি মনে করি ostringstream, আপনি করতে পারে একটি ডামি স্ট্রিং ক্ষণস্থায়ী দ্বারা "রিজার্ভ", অর্থাৎ, ostringstream str(string(1000000 * sizeof(int), '\0'));সঙ্গে vector, resizeকোনো স্থান ডি-এলোকেট করে না, এটি শুধুমাত্র বিস্তৃতি যদি এটা করতে হবে।
নিম

1
"ভেক্টর .. বাফার ওভাররন থেকে সুরক্ষা"। একটি সাধারণ ভুল ধারণা - vector[]অপারেটর সাধারণত সীমা ত্রুটিগুলি ডিফল্টরূপে পরীক্ষা করা হয় না। vector.at()তবে।
রডি

2
vector<T>::resize(0)মেমরিটি সাধারণত
পুনঃবিবর্তিত

2
@ রডি: ব্যবহার করছেন না operator[], তবে push_back()(উপায় দ্বারা back_inserter) যা অবশ্যই প্রবাহের জন্য পরীক্ষা করে। ব্যবহার না করে এমন আরও একটি সংস্করণ যুক্ত করা হয়েছে push_back
বেন ভয়েগ্ট
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.