সেকেন্ডে উচ্চ সংখ্যার সন্নিবেশ সহ কোয়েরি করার জন্য কয়েক মিলিয়ন বস্তু সংরক্ষণের কার্যকর পদ্ধতি?


15

এটি মূলত একটি লগিং / কাউন্টিং অ্যাপ্লিকেশন যা প্যাকেটের সংখ্যা এবং প্যাকেটের প্রকার গণনা ইত্যাদি একটি পি 2 পি চ্যাট নেটওয়ার্কে রয়েছে। এটি 5 মিনিটের সময়কালে প্রায় 4-6 মিলিয়ন প্যাকেটের সমান হয়। এবং যেহেতু আমি কেবল এই তথ্যের একটি "স্ন্যাপশট" নিই, আমি প্রতি পাঁচ মিনিটে কেবল 5 মিনিটেরও বেশি পুরানো প্যাকেটগুলি সরাচ্ছি। সুতরাং এই সংগ্রহে থাকা আইটেমগুলির সর্বাধিক হ'ল 10 থেকে 12 মিলিয়ন।

যেহেতু আমার কাছে বিভিন্ন সুপারপিয়ারের সাথে 300 সংযোগ স্থাপন করা দরকার, এটি এমন একটি সম্ভাবনা যা প্রতিটি প্যাকেট কমপক্ষে 300 বার .োকানোর চেষ্টা করছে (যার কারণেই সম্ভবত এই ডেটা মেমোরিতে রাখা কেবল যুক্তিসঙ্গত বিকল্প)।

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

Dictionary<ulong, Packet>

public class Packet
{
    public ushort RequesterPort;
    public bool IsSearch;
    public string SearchText;
    public bool Flagged;
    public byte PacketType;
    public DateTime TimeStamp;
}

আমি মাইএসকিএল ব্যবহার করার চেষ্টা করেছি, তবে আমার যে পরিমাণ তথ্য সন্নিবেশ করতে হবে তা (এটি কোনও নকল ছিল না তা পরীক্ষা করার সময়) এবং এটি লেনদেনের সময় ব্যবহার করতে সক্ষম ছিল না।

আমি মঙ্গডব চেষ্টা করেছি, তবে এর জন্য সিপিইউ ব্যবহার উন্মাদ ছিল এবং তা রাখেনি।

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

অ্যাপ্লিকেশনটি বর্তমানে প্রায় 1.1 গিগাবাইট মেমরির ব্যবহারের উপরে ঘোরাফেরা করে এবং যখন কোনও স্ন্যাপশট বলা হয় তখন এটি ব্যবহারের দ্বিগুণ হতে পারে।

আমার কাছে একটি উন্মাদ পরিমাণ র‌্যাম থাকলে এখন এটি কোনও সমস্যা হবে না, তবে আমার যে ভিএম চলছে এটি এই মুহুর্তে 2 জিবি র‌্যামের মধ্যে সীমাবদ্ধ।

কোন সহজ সমাধান আছে?


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

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

4
আপনার প্রোফাইলার আপনাকে কী বলে?
জেসনক

আপনি স্থানীয় গাদা চেয়ে দ্রুত কিছু পাবেন না। আমার পরামর্শটি হ'ল শুকানোর পরে ম্যানুয়ালি ময়লা আবর্জনা সংগ্রহের অনুরোধ জানানো হবে।
ভের্টেক

@ ভার্টেক - প্রকৃতপক্ষে, জনপ্রিয় বিশ্বাসের বিপরীতে, ময়লা আবর্জনা সংগ্রাহককে ম্যানুয়ালি আহ্বান করা আসলে তাত্ক্ষণিকভাবে ভাল, আবর্জনা সংগ্রহের গ্যারান্টি দেয় না। জিসি নিজের জিসি অ্যালগরিদম অনুযায়ী পরবর্তী সময়ের জন্য অ্যাকশনটি পিছিয়ে দিতে পারে। প্রতি 5 মিনিটে এটিকে চালনা করা এটিকে স্বস্তির পরিবর্তে স্ট্রেনে আরও যুক্ত করতে পারে। কেবল বলছি;)
জেস

উত্তর:


12

একটি অভিধান থাকার পরিবর্তে এবং খুব পুরানো এন্ট্রিগুলির জন্য সেই অভিধানটি অনুসন্ধান করার পরিবর্তে; 10 টি অভিধান প্রতি 30 সেকেন্ড বা তারপরে একটি নতুন "বর্তমান" অভিধান তৈরি করুন এবং কোনও অনুসন্ধান ছাড়াই প্রাচীনতম অভিধানটি বাতিল করুন।

এরপরে, আপনি যখন প্রাচীনতম অভিধানটি ত্যাগ করছেন তখন সমস্ত পুরানো অবজেক্টগুলিকে পরের জন্য একটি ফিলো কাতারে রাখুন এবং "নতুন" ব্যবহারের পরিবর্তে নতুন অবজেক্ট তৈরি করতে পুরানো অবজেক্টটি ফিলো সারি থেকে টানুন এবং পুরাতনটি পুনর্গঠনের জন্য একটি পদ্ধতি ব্যবহার করুন অবজেক্ট (পুরাতন বস্তুর সারি খালি না হলে)। এটি প্রচুর বরাদ্দ এবং প্রচুর আবর্জনা সংগ্রহ ওভারহেড এড়াতে পারে।


1
বিভাজন সময় অনুসারে! আমি কি পরামর্শ দিতে যাচ্ছি।
জেমস অ্যান্ডারসন

এটি হ'ল সমস্যাটি হ'ল, আমাকে গত পাঁচ মিনিটের মধ্যে তৈরি করা সমস্ত অভিধানকেই জিজ্ঞাসা করতে হবে। যেহেতু 300 সংযোগ রয়েছে, একই প্যাকেটটি প্রতিটি একবারে অন্তত একবার আসবে। সুতরাং একই প্যাকেটটি একাধিকবার হ্যান্ডেল না করার জন্য, আমি অবশ্যই এগুলি কমপক্ষে 5 মিনিটের জন্য রাখব।
জোশ

1
জেনেরিক স্ট্রাকচারগুলির সমস্যাটির অংশটি হ'ল এগুলি কোনও নির্দিষ্ট উদ্দেশ্যে কাস্টমাইজ করা হয়নি। আপনার প্যাকেট কাঠামোতে সম্ভবত "নেক্সটআইটেমফোরহ্যাশ" ফিল্ড এবং একটি "নেক্সটআইটেমফোরটাইমবুকিট" ফিল্ড যুক্ত করা উচিত এবং আপনার নিজের হ্যাশ টেবিলটি প্রয়োগ করা উচিত এবং অভিধান ব্যবহার বন্ধ করা উচিত। এইভাবে আপনি খুব বেশি পুরানো সমস্ত প্যাকেটগুলি দ্রুত খুঁজে পেতে পারেন এবং প্যাকেটটি sertedোকানো মাত্র একবার অনুসন্ধান করুন (যেমন আপনার পিষ্টকটি রাখুন এবং এটিও খান)। এটি মেমরি পরিচালনা ওভারহেডের জন্যও সহায়তা করবে ("অভিধান" হিসাবে অভিধান পরিচালনার জন্য অতিরিক্ত ডেটা স্ট্রাকচার বরাদ্দ / মুক্ত করা হবে না)।
ব্রেন্ডন 10

নির্ধারণ করার পূর্বে একটি হলে আপনি কিছু দেখা করেছি দ্রুততম উপায় @Josh hashset । সময়-কাটা হ্যাশ সেটগুলি দ্রুত হবে এবং পুরানো আইটেমগুলি উচ্ছেদ করার জন্য আপনাকে এখনও অনুসন্ধানের প্রয়োজন হবে না। আপনি যদি এটি আগে না দেখে থাকেন তবে আপনি এটি আপনার ডিক্টারে (y / ies) সংরক্ষণ করতে পারেন।
বেসিক


3

প্রথম চিন্তাটি মনে আসে যে আপনি কেন 5 মিনিট অপেক্ষা করেন। আপনি কি আরও প্রায়ই স্ন্যাপ-শট করতে পারেন এবং এভাবে 5 মিনিটের বাউন্ডারে আপনি যে বড় ওভারলোড দেখেন তা হ্রাস করতে পারেন?

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

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


1
একটি BitArray মত একটি স্ট্রিং / বাইট অ্যারের, ব্যবহার কিছু ব্যবহার করবেন না: msdn.microsoft.com/en-us/library/... ম্যানুয়ালি বিট-অলসভাবে ঘোরানো ফেরানো হচ্ছে এড়ানো। অন্যথায়, এটি একটি ভাল উত্তর, ভাল অ্যালগরিদম, আরও হার্ডওয়ার বা ভাল হার্ডওয়্যার ব্যতীত সত্যিকারের সহজ বিকল্প নেই।
এড জেমস

1
পাঁচ মিনিটের জিনিসটি এই 300 সংযোগগুলি একই প্যাকেটটি গ্রহণ করতে পারে তার কারণেই। সুতরাং আমি ইতিমধ্যে যা পরিচালনা করেছি তার ট্র্যাক রাখতে হবে এবং এই নির্দিষ্ট নেটওয়ার্কের সমস্ত নোডে প্যাকেটগুলি পুরোপুরি প্রচার করতে 5 মিনিট সময় লাগে।
জোশ

3

সাধারণ পদ্ধতির: মেমক্যাচ করে দেখুন

  • এটি এই জাতীয় কাজ চালানোর জন্য অনুকূলিত।
  • এটি কেবল আপনার উত্সর্গীকৃত বাক্সে নয়, কম ব্যস্ত বাক্সগুলিতে অতিরিক্ত মেমরির পুনঃব্যবহার করতে পারে।
  • এটিতে অন্তর্নির্মিত ক্যাশে মেয়াদোত্তীর্ণ প্রক্রিয়া রয়েছে যা অলস তাই কোনও হিচাপ নেই।

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

আরো জটিল পদ্ধতির: চেষ্টা Redis

খারাপ দিকটি হ'ল এটি কিছুটা জটিল।


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

1

আপনার উল্লেখ করা প্রশ্নের জন্য আপনাকে সমস্ত প্যাকেজ সংরক্ষণ করতে হবে না। উদাহরণস্বরূপ - প্যাকেজ টাইপ কাউন্টার:

আপনার দুটি অ্যারে দরকার:

int[] packageCounters = new int[NumberOfTotalTypes];
int[,] counterDifferencePerMinute = new int[6, NumberOfTotalTypes];

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

সুতরাং প্রতিটি প্যাকেজের জন্য, নিম্নলিখিত অপারেশনগুলি সম্পাদন করা হয়:

packageCounters[packageType] += 1;
counterDifferencePerMinute[current, packageType] += 1;
if (oneMinutePassed) {
  current = (current + 1) % 6;
  for (int i = 0; i < NumberOfTotalTypes; i++) {
    packageCounters[i] -= counterDifferencePerMinute[current, i];
    counterDifferencePerMinute[current, i] = 0;
}

যে কোনও সময়ে, প্যাকেজ কাউন্টারগুলি তাত্ক্ষণিকভাবে সূচি দ্বারা পুনরুদ্ধার করা যেতে পারে এবং আমরা সমস্ত প্যাকেজ সংরক্ষণ করি না।


আমি যে ডেটা করি তা সঞ্চয় করার মূল কারণ হ'ল এই 300 সংযোগগুলি একই সঠিক প্যাকেটটি গ্রহণ করতে পারে। সুতরাং আমি একবারে আরও বেশি বার হ্যান্ডেল / গণনা করছি না তা নিশ্চিত করার জন্য আমার প্রতিটি দেখা প্যাকেট কমপক্ষে পাঁচ মিনিটের জন্য রাখা প্রয়োজন। অভিধান কীটির জন্য উলং কোনটি।
জোশ

1

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

আপনার ডেটা জন্য ক্লাসের পরিবর্তে একটি কাঠামো ব্যবহার করুন (তবে মনে রাখবেন এটি পাস-বাই-কপি সিম্যান্টিকস সহ একটি মান হিসাবে বিবেচিত হবে)। এটি জিসি প্রতিটি স্তরের পাস পাসে অনুসন্ধানের একটি স্তর খুঁজে বের করে।

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

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

স্ট্রাক্ট এবং তালিকার সংমিশ্রণ মেমরির ব্যবহার এবং আবর্জনা সংগ্রহকারীর আকার উভয়কে হ্রাস করে।


আমার একটি সাম্প্রতিক পরীক্ষা রয়েছে, যা স্কিলাইট github.com/modma/Persistance
ModMa
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.