বাইটবফার.এলোকট () বনাম বাইটবফার.লোকটডাইরেক্ট ()


144

করতে allocate()বা allocateDirect()যে প্রশ্ন।

কয়েক বছর ধরে আমি কেবল এই চিন্তায় আটকে গিয়েছি যেহেতু DirectByteBufferগুলি ওএস স্তরে সরাসরি মেমরি ম্যাপিং, এটি এসের চেয়ে কল পেতে / কল করা দ্রুত সম্পাদন করবে HeapByteBuffer। আমি এখনও অবধি পরিস্থিতি সম্পর্কিত সঠিক বিবরণ সন্ধান করতে আগ্রহী ছিলাম না। আমি জানতে চাই যে দুটি ধরণের ByteBufferএসগুলির মধ্যে কোনটি দ্রুত এবং কোন পরিস্থিতিতে on


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

এগুলি পড়তে এবং SocketChannelঅবরুদ্ধকরণের জন্য কনফিগার করা আছে এমনগুলিতে লিখতে ব্যবহার করা হবে । সুতরাং @ বারমার্গুলিরা যা বলেছে সে সম্পর্কে, DirectByteBufferচ্যানেলগুলির পক্ষে দ্রুত সঞ্চালন করা হবে।

@ জারলি কমপক্ষে আমার উত্তরটির বর্তমান সংস্করণটি বলে যে চ্যানেলগুলি উপকৃত হবে বলে আশা করা হচ্ছে।
bmargulies

উত্তর:


150

রন হিচস তাঁর দুর্দান্ত বই জাভা এনআইও-তে মনে হয়েছে যা আপনার প্রশ্নের উত্তরের উত্তর হতে পারে বলে আমি মনে করি তা প্রদান করে:

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

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

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

  1. একটি অস্থায়ী সরাসরি বাইটবফার অবজেক্ট তৈরি করুন।
  2. অস্থায়ী বাফারে ননডাইরেক্ট বাফারের সামগ্রীটি অনুলিপি করুন।
  3. অস্থায়ী বাফারটি ব্যবহার করে নিম্ন-স্তরের আই / ও অপারেশন করুন।
  4. অস্থায়ী বাফার অবজেক্টটি সুযোগের বাইরে চলে যায় এবং অবশেষে আবর্জনা সংগ্রহ করা হয়।

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

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

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


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

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

@ রবার্টক্লেমে, +১, আমরা সবাই অনুমানকে ঘৃণা করি, তবে, সমস্ত বড় ওএসের জন্য পারফরম্যান্স পরিমাপ করা অসম্ভব হতে পারে, যেহেতু অনেকগুলি বড় ওএস রয়েছে way অন্য একটি পোস্ট সে চেষ্টা করেছিল, তবে "ওএসের উপর নির্ভর করে ফলাফলগুলি ব্যাপকভাবে ওঠানামা করে" শুরু করে আমরা এর বেঞ্চমার্ক নিয়ে অনেকগুলি সমস্যা দেখতে পাই । এছাড়াও, যদি কোনও কালো ভেড়া থাকে যা প্রতিটি আই / ও-তে বাফার অনুলিপি করার মতো ভয়ঙ্কর জিনিসগুলি করে? তারপরে sheep মেষের কারণে আমরা কেবল এই খারাপ পরিস্থিতিগুলি এড়াতে লিখিত কোডটি রোধ করতে বাধ্য হতে পারি otherwise
পেসারিয়ার

@ রবার্টক্লেমে আমি সম্মত এখানে অনেক অনুমানের কাজ রয়েছে। উদাহরণস্বরূপ, জেভিএম বাইট অ্যারে খুব কম বরাদ্দ করার সম্ভাবনা কম।
লার্নের মারকুইস

@ এডউইন ডালোরজো: বাস্তব বিশ্বে আমাদের কেন এই ধরনের বাইট বাফার দরকার? তারা প্রক্রিয়া মধ্যে স্মৃতি ভাগ করতে একটি হ্যাক হিসাবে উদ্ভাবিত হয়? উদাহরণস্বরূপ বলুন যে জেভিএম কোনও প্রক্রিয়াতে চলে এবং এটি এমন একটি প্রক্রিয়া হবে যা নেটওয়ার্ক বা ডেটা লিঙ্ক লেয়ারে চলে - যা তথ্য সংক্রমণ করার জন্য দায়ী - এই প্রসেসগুলির মধ্যে মেমরি ভাগ করার জন্য এই বাইট বাফারগুলি বরাদ্দ করা হয়? আমি ভুল হলে দয়া করে আমাকে সংশোধন করুন ..
টম টেলর

25

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


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

21

যেহেতু DirectByteBuffers ওএস স্তরে সরাসরি মেমরি ম্যাপিং

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

এটি পেতে / কল কল করে দ্রুত সম্পাদন করবে

উপসংহারটি প্রিমস থেকে অনুসরণ করে না; প্রথমটি মিথ্যা; এবং উপসংহারটিও মিথ্যা। আপনি একবার জেএনআই স্তরের ভিতরে প্রবেশের পরে এগুলি দ্রুত হয় এবং আপনি যদি একইভাবে পড়তে এবং লিখতে থাকেন DirectByteBufferতবে সেগুলি আরও দ্রুত হয় কারণ ডেটা কখনই জেএনআই সীমানা অতিক্রম করতে হয় না।


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

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

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

@ রবার্টক্লেমে আপনার এই বক্তব্য ভুল হয়েছে যে 'জাভা জমি থেকে সরাসরি বাফারের [কেবলমাত্র] সমস্ত কাজ অপারেশন করতে হবে' দিয়ে ভুল। উভয়ই পায় এবং রাখে পার করতে হয়।
লার্নের মারকুইস

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

18

আপনার নিজস্ব পরিমাপ করতে সেরা। দ্রুত উত্তর বলে মনে হয় যে allocateDirect()বাফার থেকে প্রেরণে allocate()আকারের উপর নির্ভর করে ভেরিয়েন্টের চেয়ে 25% থেকে 75% কম সময় লাগে (ফাইলের / dev / নালিতে অনুলিপি করা হয়), তবে বরাদ্দটি নিজেই উল্লেখযোগ্যভাবে হতে পারে ধীর (এমনকি 100x এর একটি ফ্যাক্টর)।

সূত্র:


ধন্যবাদ। আমি আপনার উত্তরটি গ্রহণ করব তবে আমি পারফরম্যান্সের পার্থক্য সম্পর্কে আরও কিছু নির্দিষ্ট বিশদ খুঁজছি।
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.