হাস্কেল প্রোগ্রামে আবর্জনা-কালেকটি বিরতির সময় হ্রাস করা


130

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

আমরা এই প্রোগ্রামটি বিলম্বের জন্য অনুকূল করতে চাই: একটি বার্তা প্রেরণ এবং গ্রহণের মধ্যে সময়টি 10 ​​মিলিসেকেন্ডের নীচে হওয়া আবশ্যক।

প্রোগ্রামটি হাস্কেল-এ লেখা এবং জিএইচসির সাথে সংকলিত। তবে আমরা দেখতে পেয়েছি যে আবর্জনা সংগ্রহের বিরতি আমাদের বিলম্বিত প্রয়োজনীয়তার জন্য অনেক দীর্ঘ: আমাদের বাস্তব-বিশ্ব প্রোগ্রামে 100 মিলিসেকেন্ডেরও বেশি।

নিম্নলিখিত প্রোগ্রামটি আমাদের আবেদনের একটি সহজ সংস্করণ ified এটি Data.Map.Strictবার্তা সংরক্ষণের জন্য একটি ব্যবহার করে। বার্তা ByteStringএকটি দ্বারা সনাক্ত করা হয় Int। সংখ্যা ক্রমবর্ধমান মধ্যে 1,000,000 বার্তা সন্নিবেশ করা হয়, এবং সর্বোচ্চ 200,000 বার্তায় ইতিহাস রাখার জন্য পুরানো বার্তাগুলি ক্রমাগত সরানো হয়।

module Main (main) where

import qualified Control.Exception as Exception
import qualified Control.Monad as Monad
import qualified Data.ByteString as ByteString
import qualified Data.Map.Strict as Map

data Msg = Msg !Int !ByteString.ByteString

type Chan = Map.Map Int ByteString.ByteString

message :: Int -> Msg
message n = Msg n (ByteString.replicate 1024 (fromIntegral n))

pushMsg :: Chan -> Msg -> IO Chan
pushMsg chan (Msg msgId msgContent) =
  Exception.evaluate $
    let
      inserted = Map.insert msgId msgContent chan
    in
      if 200000 < Map.size inserted
      then Map.deleteMin inserted
      else inserted

main :: IO ()
main = Monad.foldM_ pushMsg Map.empty (map message [1..1000000])

আমরা এই প্রোগ্রামটি ব্যবহার করে সংকলন ও পরিচালনা করেছি:

$ ghc --version
The Glorious Glasgow Haskell Compilation System, version 7.10.3
$ ghc -O2 -optc-O3 Main.hs
$ ./Main +RTS -s
   3,116,460,096 bytes allocated in the heap
     385,101,600 bytes copied during GC
     235,234,800 bytes maximum residency (14 sample(s))
     124,137,808 bytes maximum slop
             600 MB total memory in use (0 MB lost due to fragmentation)

                                     Tot time (elapsed)  Avg pause  Max pause
  Gen  0      6558 colls,     0 par    0.238s   0.280s     0.0000s    0.0012s
  Gen  1        14 colls,     0 par    0.179s   0.250s     0.0179s    0.0515s

  INIT    time    0.000s  (  0.000s elapsed)
  MUT     time    0.652s  (  0.745s elapsed)
  GC      time    0.417s  (  0.530s elapsed)
  EXIT    time    0.010s  (  0.052s elapsed)
  Total   time    1.079s  (  1.326s elapsed)

  %GC     time      38.6%  (40.0% elapsed)

  Alloc rate    4,780,213,353 bytes per MUT second

  Productivity  61.4% of total user, 49.9% of total elapsed

এখানে গুরুত্বপূর্ণ মেট্রিকটি 0.0515s বা 51 মিলিসেকেন্ডের "সর্বাধিক বিরতি"। আমরা কমপক্ষে একটি প্রস্থের অর্ডার দ্বারা এটি হ্রাস করতে চাই।

পরীক্ষায় দেখা যায় যে একটি জিসি বিরতির দৈর্ঘ্য ইতিহাসের বার্তাগুলির সংখ্যা দ্বারা নির্ধারিত হয়। সম্পর্কটি মোটামুটি লিনিয়ার, বা সম্ভবত সুপার-লিনিয়ার। নিম্নলিখিত সম্পর্কটি এই সম্পর্কটি দেখায়। ( আপনি আমাদের বেঞ্চমার্কিং পরীক্ষাগুলি এখানে এবং কিছু চার্ট দেখতে পারেন ))

msgs history length  max GC pause (ms)
===================  =================
12500                                3
25000                                6
50000                               13
100000                              30
200000                              56
400000                             104
800000                             199
1600000                            487
3200000                           1957
6400000                           5378

তারা এই বিলম্বকে কমিয়ে দিতে পারে কিনা সেগুলির জন্য আমরা আরও বেশ কয়েকটি ভেরিয়েবলের সাথে পরীক্ষা-নিরীক্ষা করেছি, যার কোনওটিতেই খুব বড় পার্থক্য নেই। এই গুরুত্বহীন পরিবর্তনশীলগুলির মধ্যে রয়েছে: অপ্টিমাইজেশন ( -O, -O2); আরটিএস জিসি অপশন ( -G, -H, -A, -c), কোর (সংখ্যা -N), বিভিন্ন ডাটা স্ট্রাকচার ( Data.Sequence), বার্তা মাপ, এবং উত্পন্ন স্বল্পস্থায়ী আবর্জনা পরিমাণ। অপ্রতিরোধ্য নির্ধারণকারী ফ্যাক্টর হ'ল ইতিহাসের বার্তাগুলির সংখ্যা।

আমাদের কাজের তত্ত্বটি হ'ল বিরতি দেওয়া বার্তাগুলির সংখ্যার ক্ষেত্রে লিনিয়ার কারণ প্রতিটি জিসি চক্রটি সমস্ত কার্যক্ষম অ্যাক্সেসযোগ্য মেমরির উপর দিয়ে যেতে হয় এবং এটি অনুলিপি করতে হয়, যা স্পষ্টতই রৈখিক ক্রিয়াকলাপ are

প্রশ্নাবলী:

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

1
@ বাকুরিউ: ঠিক আছে, তবে 10 এমএসে কোনও টুইট ছাড়াই আধুনিক কোনও ওএসের মাধ্যমে অর্জনযোগ্য হওয়া উচিত। আমি যখন সরল সি প্রোগ্রাম পরিচালনা করি, এমনকি আমার পুরানো রাস্পবেরি পাইতেও, তারা সহজেই 5 এমএসের পরিসরে বিলম্বিততা অর্জন করে বা কমপক্ষে নির্ভরযোগ্যভাবে 15 এমএসের মতো কিছু করে।
21'16

3
আপনি কি নিশ্চিত যে আপনার পরীক্ষা-কেস দরকারী (যেমন আপনি COntrol.Concurrent.Chanউদাহরণস্বরূপ ব্যবহার করছেন না ? পরিবর্তনীয় অবজেক্টগুলি সমীকরণ পরিবর্তন করে)? আপনি কোন আবর্জনা তৈরি করছেন তা নিশ্চিত করে এবং যতটা সম্ভব কম পরিমাণে তৈরি করে তা নিশ্চিত করে শুরু করার পরামর্শ দেব (উদাহরণস্বরূপ, ফিউশনটি ঘটেছে তা নিশ্চিত করুন, চেষ্টা করুন -funbox-strict)। সম্ভবত একটি স্ট্রিমিং লিব (আইওস্ট্রিমস, পাইপস, কন্ডুইট, স্ট্রিমিং) এবং performGCআরও ঘন ঘন বিরতিতে সরাসরি কল করার চেষ্টা করুন calling
jberryman

6
আপনি যা অর্জন করতে চাইছেন তা যদি স্থির জায়গায় করা যায় তবে তা ঘটানোর চেষ্টা MutableByteArray
করেই

1
পরিবর্তনীয় কাঠামোর পরামর্শ দিচ্ছেন এবং ন্যূনতম আবর্জনা তৈরির জন্য যত্ন নিচ্ছেন তাদের জন্য নোট করুন যে এটি ধরে রাখা আকার, সংগ্রহ করা আবর্জনার পরিমাণ নয় যা বিরতির সময় নির্ধারিত বলে মনে হয়। প্রায়শই একই সংগ্রহের আরও বিরতিতে আরও ঘন ঘন সংগ্রহের ফলাফল জোর করে। সম্পাদনা করুন: পরিবর্তনীয় অফ হিপ স্ট্রাকচারগুলি আকর্ষণীয় হতে পারে তবে বেশিরভাগ ক্ষেত্রেই কাজ করতে এত মজাদার নয়!
মাইক 15

6
এই বিবরণটি অবশ্যই সুপারিশ করে যে জিসি সময় সমস্ত প্রজন্মের জন্য গাদা আকারে রৈখিক হবে, বজায় রাখা বস্তুর আকার (অনুলিপি করার জন্য) এবং তাদের বিদ্যমান পয়েন্টারগুলির সংখ্যা (স্ক্যাভেঞ্জিংয়ের জন্য): জিসিসি.হেসেল gh org / trac / ghc / wiki / ভাষ্য / আরটিএস / স্টোরেজ / GC / অনুলিপি
মাইকে

উত্তর:


96

200Mb লাইভ ডেটা সহ 51 মাইল বিরতি দেওয়ার জন্য আপনি আসলে বেশ ভাল করছেন। আমি যে সিস্টেমে কাজ করি তার অর্ধেক লাইভ ডেটা সহ বৃহত্তর সর্বোচ্চ বিরতি সময় থাকে।

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

ভবিষ্যতে এইটির জন্য একটি জিনিস যা আমরা প্রত্যাশা করব তা হ'ল কমপ্যাক্ট অঞ্চলগুলি: https://phabricator.haskell.org/D1264 । এটি এক ধরণের ম্যানুয়াল মেমরি পরিচালনা যেখানে আপনি গাদা একটি কাঠামো কমপ্যাক্ট করেন এবং জিসিকে এটি পাস করতে হবে না। এটি দীর্ঘস্থায়ী ডেটার জন্য সবচেয়ে ভাল কাজ করে তবে সম্ভবত আপনার সেটিংসে পৃথক বার্তাগুলির জন্য এটি ব্যবহার করা যথেষ্ট ভাল। আমরা এটি জিএইচসি 8.2.0 এ রাখার লক্ষ্য রাখছি।

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


13
হাই সাইমন, আপনার বিস্তারিত উত্তরের জন্য আপনাকে অনেক ধন্যবাদ! এটি খারাপ সংবাদ, তবে বন্ধ হওয়া ভাল। আমরা বর্তমানে একমাত্র উপযুক্ত বিকল্প হিসাবে পরিবর্তিত পরিবর্তন বাস্তবায়নের দিকে এগিয়ে যাচ্ছি। কয়েকটি জিনিস যা আমরা বুঝতে পারি না: (1) লোড ব্যালেন্সিং স্কিমের সাথে যুক্ত কৌশলগুলি কী কী - সেগুলিতে কী ম্যানুয়াল জড়িত performGC? (২) কেন কমপ্যাক্টিংয়ের সাথে -cআরও খারাপ অভিনয় করা যায় - আমরা মনে করি কারণ এটি অনেক জায়গায় খুঁজে পাওয়া যায় না কারণ এটি জায়গায় রেখে যেতে পারে? (3) কমপ্যাক্ট সম্পর্কে আরও কিছু বিবরণ আছে? এটি খুব আকর্ষণীয় মনে হলেও দুর্ভাগ্যক্রমে ভবিষ্যতে আমাদের বিবেচনার জন্য এটি কিছুটা দূরে।
জামেশফিশার

2
@ এমএলজিআরজি আপনি ভাল- টাইপড.ব্লগ
আলফ্রেডো দি নেপোলি

@ অ্যালফ্রেডো ডি নেপোলি আপনাকে ধন্যবাদ!
mljrg

9

IOVectorঅন্তর্নিহিত ডেটা স্ট্রাকচার হিসাবে ব্যবহার করে একটি রিংবফার পদ্ধতির সাহায্যে আমি আপনার কোড স্নিপেট চেষ্টা করেছি । আমার সিস্টেমে (জিএইচসি 7.10.3, একই সংকলনের বিকল্পগুলি) এর ফলে সর্বাধিক সময় হ্রাস পেয়েছে (আপনি নিজের ওপিতে যে মেট্রিকটি উল্লেখ করেছেন) mentioned 22% হ্রাস পেয়েছে।

বিশেষ দ্রষ্টব্য। আমি এখানে দুটি অনুমান করেছি:

  1. একটি পরিবর্তনীয় ডেটা কাঠামো সমস্যার জন্য ঠিকঠাক ফিট (আমার ধারণা ম্যাসেজটি পাস করার ফলে যেভাবেই IO বোঝায়)
  2. আপনার বার্তাটি ধারাবাহিক are

কিছু অতিরিক্ত Intপ্যারামিটার এবং পাটিগণিতের সাথে (যেমন বার্তা আইডিকে 0 বা পুনরায় সেট করা হয় minBound) এরপরে কোনও নির্দিষ্ট বার্তা এখনও ইতিহাসে রয়েছে কিনা তা নির্ধারণ করা এবং এটি রিংবফারের সাথে সম্পর্কিত সূচকটি পুনরুদ্ধার করা সহজবোধ্য হওয়া উচিত।

আপনার পরীক্ষার আনন্দের জন্য:

import qualified Control.Exception as Exception
import qualified Control.Monad as Monad
import qualified Data.ByteString as ByteString
import qualified Data.Map.Strict as Map

import qualified Data.Vector.Mutable as Vector

data Msg = Msg !Int !ByteString.ByteString

type Chan = Map.Map Int ByteString.ByteString

data Chan2 = Chan2
    { next          :: !Int
    , maxId         :: !Int
    , ringBuffer    :: !(Vector.IOVector ByteString.ByteString)
    }

chanSize :: Int
chanSize = 200000

message :: Int -> Msg
message n = Msg n (ByteString.replicate 1024 (fromIntegral n))


newChan2 :: IO Chan2
newChan2 = Chan2 0 0 <$> Vector.unsafeNew chanSize

pushMsg2 :: Chan2 -> Msg -> IO Chan2
pushMsg2 (Chan2 ix _ store) (Msg msgId msgContent) =
    let ix' = if ix == chanSize then 0 else ix + 1
    in Vector.unsafeWrite store ix' msgContent >> return (Chan2 ix' msgId store)

pushMsg :: Chan -> Msg -> IO Chan
pushMsg chan (Msg msgId msgContent) =
  Exception.evaluate $
    let
      inserted = Map.insert msgId msgContent chan
    in
      if chanSize < Map.size inserted
      then Map.deleteMin inserted
      else inserted

main, main1, main2 :: IO ()

main = main2

main1 = Monad.foldM_ pushMsg Map.empty (map message [1..1000000])

main2 = newChan2 >>= \c -> Monad.foldM_ pushMsg2 c (map message [1..1000000])

2
ওহে! চমৎকার উত্তর. আমি সন্দেহ করি যে এটি কেবলমাত্র 22% স্পিডআপ হওয়ার কারণ হ'ল জিসি এখনও IOVectorপ্রতিটি সূচকে চলমান এবং (অপরিবর্তনীয়, জিসি'ডি) মানগুলি অনুসরণ করতে পারে। আমরা বর্তমানে পরিবর্তনীয় কাঠামো ব্যবহার করে পুনরায় বাস্তবায়নের বিকল্পগুলি অনুসন্ধান করছি। এটি আপনার রিং বাফার সিস্টেমের মতো হতে পারে। তবে আমরা আমাদের নিজস্ব ম্যানুয়াল মেমরি পরিচালনা করতে এটি পুরোপুরি হাস্কেল মেমরি স্পেসের বাইরে নিয়ে চলেছি।
জামেসফিশার

11
@ জামেসফিশার: আমি আসলে একই ধরণের সমস্যার মুখোমুখি হয়েছি, তবে হাস্কেলের পক্ষে মেম্ব পরিচালনা করার সিদ্ধান্ত নিয়েছি। সমাধানটি আসলে একটি রিং বাফার ছিল, যা মেমরির একক, অবিচ্ছিন্ন ব্লকে মূল ডেটার বাইটওয়াইস অনুলিপি রাখে, ফলে একক হাস্কেলের মান হয় in এই রিংবফার.এএস সংক্ষেপে এটি একবার দেখুন । আমি এটি আপনার নমুনা কোডের বিপরীতে পরীক্ষা করেছি এবং সমালোচনামূলক মেট্রিকের প্রায় 90% গতি ছিল। আপনার সুবিধার্থে নিখরচায় কোডটি ব্যবহার করুন।
এমজিএমইয়ার

8

আমাকে অন্যের সাথে একমত হতে হবে - আপনার যদি সত্যিকারের সময়সীমাবদ্ধতা থাকে তবে জিসি ভাষা ব্যবহার করা আদর্শ নয়।

তবে, আপনি কেবল ডেটা ম্যাপের পরিবর্তে অন্যান্য উপলভ্য ডেটা স্ট্রাকচার নিয়ে পরীক্ষা-নিরীক্ষা বিবেচনা করতে পারেন।

আমি ডেটা ব্যবহার করে এটি পুনরায় লিখেছি eঅগ্রহ এবং কিছু আশাব্যঞ্জক উন্নতি পেয়েছি:

msgs history length  max GC pause (ms)
===================  =================
12500                              0.7
25000                              1.4
50000                              2.8
100000                             5.4
200000                            10.9
400000                            21.8
800000                            46
1600000                           87
3200000                          175
6400000                          350

যদিও আপনি বিলম্বের জন্য অপ্টিমাইজ করছেন, আমি অন্যান্য মেট্রিকগুলিতেও উন্নতি লক্ষ্য করেছি। 200000 ক্ষেত্রে, মৃত্যুর সময় 1.5s থেকে 0.2 এ নেমে আসে এবং মোট মেমরির ব্যবহার 600MB থেকে 27MB এ নেমে যায়।

আমার মনে রাখা উচিত যে আমি ডিজাইনটি টুইট করে প্রতারণা করেছি:

  • আমি মুছে Intথেকে Msg, তাই এটি দুই জায়গায় নয়।
  • থেকে একটি মানচিত্র ব্যবহার করার পরিবর্তে Intগুলি ByteStringগুলি, আমি একটি ব্যবহৃত Sequenceএর ByteStrings, এবং পরিবর্তে এক Intবার্তা অনুযায়ী, আমি মনে করি এটা এক সঙ্গে কাজ করা যেতে পারে Intপুরো জন্য Sequence। ধরে নেওয়া বার্তাগুলি পুনরায় সাজানো যাবে না, আপনি কোন বার্তাটি কাতারে বসেছেন তা কোন অনুবাদ করতে চান তা অনুবাদ করতে আপনি একটি একক অফসেট ব্যবহার করতে পারেন।

(আমি getMsgএটি প্রদর্শনের জন্য একটি অতিরিক্ত ফাংশন অন্তর্ভুক্ত করেছি ))

{-# LANGUAGE BangPatterns #-}

import qualified Control.Exception as Exception
import qualified Control.Monad as Monad
import qualified Data.ByteString as ByteString
import Data.Sequence as S

newtype Msg = Msg ByteString.ByteString

data Chan = Chan Int (Seq ByteString.ByteString)

message :: Int -> Msg
message n = Msg (ByteString.replicate 1024 (fromIntegral n))

maxSize :: Int
maxSize = 200000

pushMsg :: Chan -> Msg -> IO Chan
pushMsg (Chan !offset sq) (Msg msgContent) =
    Exception.evaluate $
        let newSize = 1 + S.length sq
            newSq = sq |> msgContent
        in
        if newSize <= maxSize
            then Chan offset newSq
            else
                case S.viewl newSq of
                    (_ :< newSq') -> Chan (offset+1) newSq'
                    S.EmptyL -> error "Can't happen"

getMsg :: Chan -> Int -> Maybe Msg
getMsg (Chan offset sq) i_ = getMsg' (i_ - offset)
    where
    getMsg' i
        | i < 0            = Nothing
        | i >= S.length sq = Nothing
        | otherwise        = Just (Msg (S.index sq i))

main :: IO ()
main = Monad.foldM_ pushMsg (Chan 0 S.empty) (map message [1..5 * maxSize])

4
ওহে! আপনার উত্তরের জন্য ধন্যবাদ. আপনার ফলাফলগুলি অবশ্যই লিনিয়ার মন্দাকে দেখায়, তবে এটির থেকে আকর্ষণীয় যে আপনি এর থেকে একটি স্পিডআপ পেয়েছিলেন Data.Sequence- আমরা এটি পরীক্ষা করেছি এবং এটি ডেটা ম্যাপের চেয়ে খারাপ হতে দেখেছি! পার্থক্য কী তা আমি নিশ্চিত নই, সুতরাং আমাকে তদন্ত করতে হবে ...
জামেশফিশার

8

অন্যান্য উত্তরে উল্লিখিত হিসাবে, জিএইচসির আবর্জনা সংগ্রহকারী লাইভ ডেটা অতিক্রম করে, যার অর্থ আপনি মেমরিতে যত বেশি দীর্ঘজীবী ডেটা সঞ্চয় করেন, তত বেশি সময় ধরে জিসি বিরতি দেওয়া হবে।

জিএইচসি 8.2

আংশিকভাবে এই সমস্যাটি কাটিয়ে উঠতে, জিএইচসি -৮.২ এ কমপ্যাক্ট অঞ্চল নামে একটি বৈশিষ্ট্য চালু করা হয়েছিল। এটি উভয়ই জিএইচসি রানটাইম সিস্টেমের বৈশিষ্ট্য এবং একটি লাইব্রেরি যা কাজ করার জন্য সুবিধাজনক ইন্টারফেসকে প্রকাশ করে। কমপ্যাক্ট অঞ্চল বৈশিষ্ট্য আপনার ডেটা মেমরির পৃথক স্থানে রাখার অনুমতি দেয় এবং জিসি আবর্জনা সংগ্রহের পর্যায়ে এটি অতিক্রম করবে না। সুতরাং আপনার যদি একটি বড় কাঠামো থাকে যা আপনি স্মৃতিতে রাখতে চান তবে কমপ্যাক্ট অঞ্চলগুলি ব্যবহার করে বিবেচনা করুন। তবে, কম্প্যাক্ট অঞ্চল নিজেই নেই মিনি আবর্জনা সংগ্রাহক ভিতরে, তার জন্য ভাল কাজ করে পরিশেষে যোগ কেবল- ডাটা স্ট্রাকচার, না ভালো কিছু HashMapযেখানে আপনি ডিলিট কাপড় চাই। যদিও আপনি এই সমস্যাটি কাটিয়ে উঠতে পারেন। বিস্তারিত জানার জন্য নিম্নলিখিত ব্লগ পোস্ট দেখুন:

জিএইচসি 8.10

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


3

ভাল আপনি জিসির সাথে ভাষার সীমাবদ্ধতা খুঁজে পেয়েছেন: এগুলি হার্ড রিয়েল-টাইম সিস্টেমগুলির জন্য উপযুক্ত নয়।

আপনার কাছে দুটি বিকল্প রয়েছে:

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

২ য় প্রোগ্রাম যা 'সি' ব্যবহার করে সমাধান করে এবং এফএফআই এর সাথে হেক্সেলের সাথে ইন্টারফেস করে। এইভাবে আপনি নিজের মেমরি পরিচালনা করতে পারেন। আপনি নিজের দ্বারা প্রয়োজনীয় মেমরিটি নিয়ন্ত্রণ করতে পারবেন এটি সেরা বিকল্প।


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