ইতিমধ্যে এখানে বেশ কয়েকটি ভাল উত্তর রয়েছে যেগুলি অনেকগুলি মূল বিষয়কে কভার করে, তাই আমি কেবলমাত্র দু'টি ইস্যু যুক্ত করব যা আমি সরাসরি উপরে দেখলাম না। অর্থাৎ, এই উত্তরটি উপকার এবং বিপরীতে একটি বিস্তৃত হিসাবে বিবেচনা করা উচিত নয়, বরং এখানে অন্যান্য উত্তরের একটি সংযোজন।
এমএমএপি ম্যাজিক মত মনে হচ্ছে
ফাইলটি ইতিমধ্যে 1 কে বেসলাইন 2 হিসাবে সম্পূর্ণরূপে ক্যাশে করা হয়েছে এমন কেসটি গ্রহণ করা , mmapসম্ভবত ম্যাজিকের মতো দেখতে বেশ সম্ভবত :
mmap পুরো ফাইলটি ম্যাপ করতে কেবলমাত্র 1 টি কম্পিউটার কল প্রয়োজন (সম্ভাব্য) ম্যাপ, এর পরে আর কোনও সিস্টেম কল প্রয়োজন হয় না।
mmap কার্নেল থেকে ব্যবহারকারী-স্পেসে ফাইলের একটি অনুলিপি প্রয়োজন হয় না।
mmapসংকলক স্বয়ং-ভেক্টরাইজেশন, সিমডি ইন্টারসিনিক্স, প্রিফেচিং, মেমরি পার্সিং রুটিনগুলি, ওপেনএমপি ইত্যাদির মতো যেকোনো উন্নত কৌশল দ্বারা এটি প্রক্রিয়াকরণ সহ আপনাকে "মেমরি হিসাবে" ফাইলটি অ্যাক্সেস করার অনুমতি দেয় including
ফাইলটি ইতিমধ্যে ক্যাশে রয়েছে এমন ক্ষেত্রে, এটি বীট করা অসম্ভব বলে মনে হচ্ছে: আপনি কেবল কার্নেল পৃষ্ঠা ক্যাশে মেমরি হিসাবে সরাসরি অ্যাক্সেস করেছেন এবং এটি এর চেয়ে দ্রুততর হতে পারে না।
ভাল, এটা করতে পারেন।
এমএমএপ আসলে যাদু নয় কারণ ...
এমএমএপ এখনও প্রতি পৃষ্ঠার কাজ করে
একটি প্রাথমিক লুকানো খরচ mmapবনাম read(2)(যা সত্যিই তুলনীয় অপারেটিং সিস্টেম-স্তরীয় প্রাপ্ত syscall হয় ব্লক পড়া ) সঙ্গে যে mmapআপনি ব্যবহারকারীর-স্পেস প্রতিটি 4K পৃষ্ঠার জন্য "কিছু কাজ" করতে যদিও এটি দ্বারা লুকানো করা যেতে পারে প্রয়োজন হবে, পৃষ্ঠা-ফল্ট প্রক্রিয়া
উদাহরণস্বরূপ একটি সাধারণ প্রয়োগ যা কেবলমাত্র mmapপুরো ফাইলটির জন্য একটি 100 জিবি ফাইল পড়তে 100 জিবি / 4 কে = 25 মিলিয়ন ত্রুটি করতে হবে fault এখন, এগুলি ছোটখাটো ত্রুটিযুক্ত হবে , তবে 25 বিলিয়ন পৃষ্ঠার ত্রুটিগুলি এখনও খুব দ্রুত গতিতে চলেছে না। একটি ছোটখাটো ত্রুটির ব্যয় সম্ভবত সেরা ক্ষেত্রে 100 এর দশকের ন্যানোর মধ্যে।
এমএএমএপ টিএলবির পারফরম্যান্সের উপর নির্ভর করে
এখন, আপনি পাস করতে পারেন MAP_POPULATEথেকে mmapএটা বলতে ফেরার আগে সব পেজ তালিকা সেট আপ করার জন্য, তাই যখন এটি অ্যাক্সেস কোন পাতা ফল্ট সেখানে উচিত। এখন, এতে সামান্য সমস্যা রয়েছে যে এটি পুরো ফাইলটি র্যামেও পড়ে, যা আপনি যদি 100 জিবি ফাইল ম্যাপ করার চেষ্টা করেন তবে এটি ফুরিয়ে যাবে - তবে আসুন এখনই 3 টি উপেক্ষা করুন । এই পৃষ্ঠা সারণীগুলি সেট করার জন্য কার্নেলকে প্রতি পৃষ্ঠার কাজ করতে হবে (কার্নেলের সময় হিসাবে প্রদর্শিত হবে)। এটি mmapপদ্ধতির একটি বড় ব্যয় হিসাবে শেষ হয় , এবং এটি ফাইল আকারের সমানুপাতিক (যেমন ফাইলের আকার বাড়ার সাথে তুলনামূলকভাবে কম গুরুত্বপূর্ণ হয় না) 4 ।
অবশেষে, এমনকি ব্যবহারকারী-স্পেসে এ জাতীয় ম্যাপিং অ্যাক্সেস করা ঠিক নিখরচায় নয় (বৃহত মেমোরি বাফারগুলির তুলনায় ফাইল-ভিত্তিক উত্স থেকে উদ্ভূত হয়নি mmap) - পৃষ্ঠাগুলি সারণিগুলি সেট আপ হয়ে গেলেও নতুন পৃষ্ঠায় প্রতিটি অ্যাক্সেস চলে যাচ্ছে, ধারণামূলকভাবে, একটি টিএলবি মিস লাগবে। যেহেতু mmapকোনও ফাইল ইঙ্গিত করার অর্থ পৃষ্ঠা ক্যাশে এবং এর 4K পৃষ্ঠাগুলি ব্যবহার করা হচ্ছে, আপনাকে আবার 100 জিবি ফাইলের জন্য 25 মিলিয়ন বার ব্যয় করতে হবে।
এখন, এই টিএলবি মিসের প্রকৃত ব্যয় আপনার হার্ডওয়ারের কমপক্ষে নিম্নলিখিত দিকগুলির উপর নির্ভর করে: (ক) আপনার কাছে কত 4K টিএলবি রয়েছে এবং বাকী অনুবাদ ক্যাশে কীভাবে কাজ করে (খ) হার্ডওয়্যার প্রিফেচ কতটা ভালভাবে কাজ করে? টিএলবি দিয়ে - উদাহরণস্বরূপ, একটি পৃষ্ঠা হাঁটাতে প্রিফেচ করতে পারে? (গ) পৃষ্ঠা ওয়াকিং হার্ডওয়্যারটি কত দ্রুত এবং কত সমান্তরাল। আধুনিক উচ্চ-প্রান্তের x86 ইন্টেল প্রসেসরগুলিতে, পৃষ্ঠা ওয়াকিং হার্ডওয়্যারটি সাধারণত খুব শক্তিশালী: কমপক্ষে 2 টি সমান্তরাল পৃষ্ঠার ওয়াকার থাকে, একটি পৃষ্ঠা ওয়াক একই সাথে কার্যকর হতে পারে এবং হার্ডওয়্যার প্রিফেচিং একটি পৃষ্ঠা ওয়াক ট্রিগার করতে পারে। সুতরাং স্ট্রিমিং রিড লোডের উপর টিএলবি প্রভাব মোটামুটি কম - এবং এমন লোড পৃষ্ঠার আকার নির্বিশেষে প্রায়শই একইভাবে সম্পাদন করবে। অন্যান্য হার্ডওয়্যার সাধারণত আরও খারাপ হয়, যদিও!
পড়ুন () এই সমস্যাগুলি এড়ায়
read()প্রাপ্ত syscall, যা কি সাধারণত ভিত্তি "ব্লক পড়া" টাইপ কল সি, সি ++ মধ্যে যেমন প্রদত্ত এবং অন্যান্য ভাষায় এক প্রাথমিক অসুবিধা আছে যা সবার ভালোভাবেই অবগত হল:
read()এন বাইটের প্রতিটি কল অবশ্যই কার্নেল থেকে ব্যবহারকারী স্পেসে এন বাইট অনুলিপি করতে হবে।
অন্যদিকে, এটি উপরের বেশিরভাগ ব্যয় এড়িয়ে চলে - আপনার 25 মিলিয়ন 4K পৃষ্ঠাগুলিতে ব্যবহারকারীর জায়গায় ম্যাপ করার দরকার নেই। আপনি mallocব্যবহারকারীর স্পেসে সাধারণত একটি একক বাফার ছোট বাফার করতে পারেন এবং আপনার সমস্ত readকলের জন্য বারবার ব্যবহার করতে পারেন । কার্নেলের পাশে, 4K পৃষ্ঠাগুলি বা টিএলবি মিস করা প্রায় কোনও সমস্যা নেই কারণ সমস্ত র্যাম সাধারণত কয়েকটি খুব বড় পৃষ্ঠাগুলি (যেমন, x86 এ 1 জিবি পৃষ্ঠাগুলি) ব্যবহার করে রৈখিকভাবে ম্যাপ করা হয়, সুতরাং পৃষ্ঠার ক্যাশে অন্তর্নিহিত পৃষ্ঠাগুলি areাকা থাকে কার্নেল স্পেসে খুব দক্ষতার সাথে।
সুতরাং মূলত কোনও বড় ফাইলের একক পঠনের জন্য কোনটি দ্রুত তা নির্ধারণ করার জন্য আপনার নীচের তুলনাটি রয়েছে:
mmapকার্নেল থেকে ব্যবহারকারীর জায়গায় ফাইলের বিষয়বস্তু অনুলিপি করার প্রতি-বাইট কাজের চেয়ে অতিরিক্ত প্রতি পৃষ্ঠার কাজটি কী পদ্ধতির দ্বারা নিহিত read()?
অনেক সিস্টেমে এগুলি আসলে প্রায় ভারসাম্যপূর্ণ। মনে রাখবেন যে হার্ডওয়্যার এবং ওএস স্ট্যাকের সম্পূর্ণ আলাদা বৈশিষ্ট্যযুক্ত প্রতিটি স্কেল করে।
বিশেষত, mmapপদ্ধতির তুলনামূলকভাবে দ্রুত হয় যখন:
- ওএসের দ্রুত গৌণ-ত্রুটি পরিচালনা এবং বিশেষত ছোট্ট-ত্রুটিযুক্ত বাল্ক অপ্টিমাইজেশান যেমন ফল্ট-এ্যভার্ড রয়েছে।
- ওএসের একটি
MAP_POPULATEকার্যকর বাস্তবায়ন রয়েছে যা উদাহরণস্বরূপ, অন্তর্নিহিত পৃষ্ঠাগুলি শারীরিক স্মৃতিতে সামঞ্জস্যপূর্ণ ক্ষেত্রে বড় ম্যাপগুলিকে দক্ষতার সাথে প্রক্রিয়া করতে পারে।
- হার্ডওয়ারটিতে পৃষ্ঠার অনুবাদ সম্পাদন শক্তিশালী রয়েছে যেমন বড় টিএলবি, দ্রুত দ্বিতীয় স্তরের টিএলবি, দ্রুত এবং সমান্তরাল পৃষ্ঠা-ওয়াকার্স, অনুবাদ সহ ভাল প্রিফেচ ইন্টারঅ্যাকশন ইত্যাদি।
... যখন read()পদ্ধতির তুলনামূলকভাবে দ্রুত হয় যখন:
read()প্রাপ্ত syscall ভাল কপি কর্মক্ষমতা আছে। উদাহরণস্বরূপ, copy_to_userকার্নেল দিকে ভাল পারফরম্যান্স।
- কার্নেলের মেমরি ম্যাপ করার জন্য একটি কার্যকর (ব্যবহারকারীর সাথে তুলনামূলক) উপায় রয়েছে, যেমন, হার্ডওয়্যার সমর্থন সহ কয়েকটি বড় পৃষ্ঠা ব্যবহার করা।
- কার্নেলের দ্রুত সিস্কল রয়েছে এবং সিস্টেল জুড়ে কার্নেল টিএলবি এন্ট্রি রাখার একটি উপায় রয়েছে।
উপরের হার্ডওয়্যার ফ্যাক্টরগুলি বিভিন্ন প্ল্যাটফর্মগুলিতে বন্যভাবে পরিবর্তিত হয় , এমনকি একই পরিবারের মধ্যে (যেমন, x86 প্রজন্মের মধ্যে এবং বিশেষত বাজারের অংশগুলির মধ্যে) এবং অবশ্যই আর্কিটেকচার জুড়ে (যেমন, এআরএম বনাম x86 বনাম পিপিসি)।
উভয় পক্ষের বিভিন্ন উন্নতির সাথে ওএসের উপাদানগুলিও একই সাথে পরিবর্তিত হয়, যার ফলে একটি পদ্ধতির বা অন্যটির জন্য আপেক্ষিক গতিতে বিশাল লাফ পড়ে। সাম্প্রতিক তালিকার মধ্যে রয়েছে:
- উপরে বর্ণিত দোষের চারপাশের সংযোজন, যা কেসটিকে সত্যই
mmapছাড়াই সহায়তা করে MAP_POPULATE।
- দ্রুতগতির
copy_to_userপদ্ধতিগুলির সংযোজন arch/x86/lib/copy_user_64.S, উদাহরণস্বরূপ, REP MOVQযখন দ্রুত হয় তখন ব্যবহার করা যা প্রকৃত পক্ষে কেসকে সহায়তা করে read()।
স্পেক্টর এবং মেল্টডাউন পরে আপডেট
স্পেক্টর এবং মেল্টডাউন দুর্বলতার জন্য প্রশমনগুলি সিস্টেম কলের ব্যয়কে যথেষ্ট পরিমাণে বাড়িয়ে তোলে। আমি যে সিস্টেমগুলি পরিমাপ করেছি সেগুলিতে, "ডুডিং কিছু না" সিস্টেম কলের দাম (যা কল দ্বারা করা কোনও আসল কাজ বাদে সিস্টেম কলের খাঁটি ওভারহেডের একটি অনুমান) প্রায় 100 এনএস থেকে সাধারণ আধুনিক লিনাক্স সিস্টেম প্রায় 700 এনএস। তদ্ব্যতীত, আপনার সিস্টেমের উপর নির্ভর করে, মেল্টডাউনের জন্য বিশেষত পৃষ্ঠা-সারণী বিচ্ছিন্নকরণের টিএলবি এন্ট্রিগুলি পুনরায় লোড করার প্রয়োজনীয়তার কারণে সরাসরি সিস্টেম কল ব্যয় ছাড়াও অতিরিক্ত প্রবাহের প্রভাব থাকতে পারে।
read()ভিত্তিক পদ্ধতির তুলনায় এগুলি সমস্ত ভিত্তিক পদ্ধতির তুলনামূলক অসুবিধা mmap, কারণ read()পদ্ধতিগুলি অবশ্যই প্রতিটি "বাফার আকার" মূল্যবান ডেটার জন্য একটি সিস্টেম কল করতে হবে। আপনি এই ব্যয়টি নির্বিঘ্ন করতে ইচ্ছামত বাফার আকারটি বাড়িয়ে তুলতে পারবেন না যেহেতু বড় বাফারগুলি সাধারণত L1 আকারের চেয়ে বেশি হয়ে থাকে এবং তাই আপনি ক্রমাগত ক্যাশে মিস করে যাচ্ছেন সেহেতু বড় বাফারগুলি ব্যবহার করা খারাপ হয়।
অন্যদিকে, এর সাহায্যে mmapআপনি MAP_POPULATEকেবলমাত্র একটি একক সিস্টেম কল ব্যয়ে মেমরির একটি বৃহত অঞ্চলে ম্যাপিং করতে এবং দক্ষতার সাথে অ্যাক্সেস করতে পারেন।
1 এটি কম-বেশি এমন ক্ষেত্রেও অন্তর্ভুক্ত রয়েছে যেখানে ফাইলটি শুরু করার জন্য পুরোপুরি ক্যাশে করা হয়নি, তবে ওএসের রিড-ফরোয়ার্ড যাতে এটি প্রদর্শিত হয় তার পক্ষে যথেষ্ট (যেমন, পৃষ্ঠাটি সাধারণত আপনার সময় অনুসারে ক্যাশে থাকে) এটি চান)। এটি একটি সূক্ষ্ম ইস্যু যদিও পঠন-পূর্বের কাজগুলি প্রায়শই mmapএবং readকলগুলির মধ্যে বেশ আলাদা হয় এবং 2 তে বর্ণিত হিসাবে "পরামর্শ" কলগুলি দিয়ে আরও সামঞ্জস্য করা যায় ।
2 ... কারণ যদি ফাইলটি ক্যাশে না করা হয় তবে আপনার আচরণটি আইও উদ্বেগের সাথে সম্পূর্ণরূপে আধিপত্য বয়ে চলেছে, সহ অন্তর্নিহিত হার্ডওয়্যারের সাথে আপনার অ্যাক্সেস প্যাটার্নটি কতটা সহানুভূতিশীল রয়েছে - এবং আপনার সমস্ত প্রচেষ্টা যেমন অ্যাক্সেস নিশ্চিত করতে হবে ততই সহানুভূতিশীল সম্ভব, উদাহরণস্বরূপ madviseবা fadviseকল ব্যবহারের মাধ্যমে (এবং অ্যাক্সেস প্যাটার্নগুলি উন্নত করতে আপনি যে কোনও অ্যাপ্লিকেশন স্তরের পরিবর্তন করতে পারেন)
3 আপনি এটির কাছাকাছি যেতে পারেন, উদাহরণস্বরূপ, mmapছোট আকারের উইন্ডোগুলিতে ধারাবাহিকভাবে ইনপুট করে 100 এমবি বলুন।
4 প্রকৃতপক্ষে, এটিটিMAP_POPULATE প্রমাণ করে যে (কমপক্ষে একটি হার্ডওয়ার / ওএসের সংমিশ্রণটি) এটি ব্যবহার না করার চেয়ে কিছুটা দ্রুত, সম্ভবত কার্নেলটি ফল্টআরন্ড ব্যবহার করছে - সুতরাং ছোটখাট ত্রুটির প্রকৃত সংখ্যা 16 এর ফ্যাক্টর দ্বারা হ্রাস পেয়েছে অথবা তাই.
mmap()ব্যবহারের চেয়ে 2-6 গুণ বেশি দ্রুত হয়, যেমনread()।