জিসি.কলেক্ট কল করা কখন গ্রহণযোগ্য?


166

সাধারণ পরামর্শটি হ'ল GC.Collectআপনার কোড থেকে কল করা উচিত নয় , তবে এই নিয়মের ব্যতিক্রমগুলি কী?

আমি কেবল কয়েকটি খুব সুনির্দিষ্ট ক্ষেত্রেই ভাবতে পারি যেখানে এটি কোনও জঞ্জাল সংগ্রহের জন্য জোর করে বোঝাতে পারে।

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

অন্য কোন মামলা আছে যেখানে কল করা গ্রহণযোগ্য GC.Collect?


উত্তর:


153

যদি আপনার বিশ্বাস করার উপযুক্ত কারণ থাকে তবে একটি উল্লেখযোগ্য সংখ্যক অবজেক্টস - বিশেষত যাদের আপনি 1 এবং 2 প্রজন্মের মধ্যে মনে করেন - তারা এখন আবর্জনা সংগ্রহের জন্য যোগ্য এবং এখন ছোট পারফরম্যান্স হিটের ক্ষেত্রে এটি সংগ্রহ করার উপযুক্ত সময় হবে ।

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

আপডেট 2.7.2018

নেট 4.5 হিসাবে - আছে GCLatencyMode.LowLatencyএবং GCLatencyMode.SustainedLowLatency। এই মোডগুলির মধ্যে যে কোনও একটিতে প্রবেশ এবং প্রস্থান করার সময়, আপনাকে একটি সম্পূর্ণ জিসি জোর করে দেওয়ার পরামর্শ দেওয়া হয় GC.Collect(2, GCCollectionMode.Forced)

.NET 4.6 হিসাবে - GC.TryStartNoGCRegionপদ্ধতি রয়েছে (কেবলমাত্র পঠনযোগ্য মান সেট করতে ব্যবহৃত হয় GCLatencyMode.NoGCRegion)। এটি নিজেই, পর্যাপ্ত স্মৃতি মুক্ত করার প্রয়াসে একটি সম্পূর্ণ অবরুদ্ধ আবর্জনা সংগ্রহ করতে পারে, তবে আমরা একটি সময়ের জন্য জিসিকে অস্বীকার করছি, আমি যুক্তি দেব যে এর আগে এবং পরে সম্পূর্ণ জিসি করা ভাল ধারণা perform

উত্স: মাইক্রোসফ্ট ইঞ্জিনিয়ার বেন ওয়াটসনের: উচ্চ-পারফরম্যান্স রাইটিং। নেট কোড , ২ য় এড। 2018।

দেখা:


8
এমএস সোর্স কোড অনুসারে জিসি.কলেক্টকে কল করুন (২) প্রতি 850 মিমি ঠিক আছে। বিশ্বাস করবেন না? তারপরে কেবল প্রেজেন্টেশনকোর.ডিল, এমএস.ইন্টার্নাল.মেমরিপ্রেস.প্রসেসএড () দেখুন। আমার কাছে বর্তমানে একটি চিত্র প্রক্রিয়াকরণ অ্যাপ্লিকেশন রয়েছে (ছোট চিত্রগুলি, সত্যিকারের মেমরির চাপের সাথে কিছুই নেই) যেখানে জিসি.ক্লোকটকে কল করা (2) 850ms এর চেয়ে বেশি সময় নেয় এবং তাই পুরো অ্যাপ্লিকেশনটি এটির দ্বারা হিমশীতল হয়ে যায় (অ্যাপ্লিকেশনটি জিসিতে 99.7% সময় ব্যয় করে)।
বসন্তের 76

36
@ বসন্ত 7676: মাইক্রোসফ্টের এক জায়গায় করা মানে এই নয় যে মাইক্রোসফ্টের পরামর্শ দেওয়া লোকেরা এটি একটি ভাল জিনিস হিসাবে বিবেচিত হবে ...
জন স্কিটি

4
আমি উদাহরণটি পছন্দ করি না। ফর্মটি বন্ধ হওয়ার পরে এটি করার জন্য কি ভঙ্গ করছেন? এক্সবক্স বা উইন্ডোজফোনে গেম স্তর লোড করার পরে আমি দেখতে পাচ্ছি তার একটি ভাল উদাহরণ। এই প্ল্যাটফর্মগুলিতে জিসি 1MB বা এর মতো বরাদ্দ দেওয়ার পরে চলে। সুতরাং স্তরটি লোড করার সময় আপনার যতটা সম্ভব বরাদ্দ করা ভাল (কিছু স্প্ল্যাশ স্ক্রিন দেখানোর সময়) এবং তারপরে গিসির সময় সংগ্রহগুলি এড়াতে চেষ্টা করার জন্য জিসি.ক্লোকলেট করুন।
পাইওটর পেরাক

8
@ পেরি: ফর্মটি বন্ধ হওয়ার পরে এটি করার বিষয়টি হ'ল আপনি আবর্জনা সংগ্রহের জন্য উপযুক্ত কিছু বস্তু (নিয়ন্ত্রণ, আপনি যে ডেটা প্রদর্শন করছেন) তৈরি করেছেন - তাই কল করে GC.Collectআপনি মূলত আবর্জনা সংগ্রহকারীকে বলছেন যে আপনি জানেন পরিবর্তনের জন্য এটির চেয়ে ভাল। আপনি উদাহরণটি পছন্দ করেন না কেন?
জন স্কিটি

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

50

আমি GC.Collectকেবল তখনই ব্যবহার করি যখন অপরিশোধিত পারফরম্যান্স / প্রোফাইলার টেস্ট রিগগুলি লিখি; উদাহরণস্বরূপ, আমার কাছে পরীক্ষার জন্য কোডের দুটি (বা আরও) ব্লক রয়েছে - এরকম কিছু:

GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
TestA(); // may allocate lots of transient objects
GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
TestB(); // may allocate lots of transient objects
GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
...

যাতে এটি TestA()এবং TestB()যথাসম্ভব অনুরূপ রাজ্যের সাথে চালান - অর্থাত্ টিপিং পয়েন্টের খুব কাছাকাছি রেখেছিল TestB()বলেই TestAএটি আঘাত করা হবে না।

একটি ক্লাসিক উদাহরণ হ'ল একটি সাধারণ কনসোল এক্স ( Mainউদাহরণস্বরূপ এখানে পোস্ট করার মতো একটি পদ্ধতি), এটি লুপযুক্ত স্ট্রিং কনটেনটেশন এবং এর মধ্যে পার্থক্য দেখায় StringBuilder

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

প্রোডাকশন কোড চলাকালীন? আমি এখনও এটি ব্যবহার করতে হবে ;-p


1
এবং আমি সম্ভবত এই ক্ষেত্রে "ওয়েটফরপেন্ডিংফাইনালাইজারস" (বা এটি যাই হোক না কেন) যুক্ত করব ;
মার্ক গ্র্যাভেল

29

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

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

তবে কিছু ব্যাচের প্রক্রিয়াকরণে আপনি আরও বেশি জানেন তবে জিসি। যেমন একটি অ্যাপ্লিকেশন বিবেচনা করুন।

  • কমান্ড লাইনে ফাইলের নামের একটি তালিকা দেওয়া হয়
  • একটি একক ফাইল প্রক্রিয়া করে তারপরে ফলাফলের ফাইলে ফলাফল লিখুন।
  • ফাইলটি প্রক্রিয়া করার সময়, প্রচুর আন্তঃসংযোগযুক্ত বস্তু তৈরি করে যা ফাইলের প্রসেসিং শেষ না হওয়া পর্যন্ত সংগ্রহ করা যায় না (যেমন একটি পার্স ট্রি)
  • এটি প্রক্রিয়া করা ফাইলগুলির মধ্যে ম্যাচের স্থিতি রাখে না

আপনি পারে একটি মামলা করতে হবে (সাবধান পর) পরীক্ষা আপনি প্রতিটি ফাইল প্রক্রিয়া আছে পরে যে আপনি একটি সম্পূর্ণ গার্বেজ কালেকশন বাধ্য করা উচিত সক্ষম হবেন।

অন্য কেস হ'ল এমন একটি পরিষেবা যা প্রতি কয়েক মিনিট পরে কিছু আইটেম প্রক্রিয়া করতে জেগে থাকে এবং ঘুমন্ত অবস্থায় কোনও রাজ্য রাখে না । তারপরে ঘুমাতে যাওয়ার ঠিক আগে পুরো সংগ্রহ জোর করা সার্থক হতে পারে।

আমি কেবল যখন সংগ্রহ করতে বাধ্য হব তখনই যখন আমি জানতাম যে সম্প্রতি প্রচুর অবজেক্ট তৈরি করা হয়েছিল এবং খুব কম বস্তু বর্তমানে রেফারেন্স করা হয়েছে।

আমি বরং কোনও জিসি আমার নিজের উপর চাপ না দিয়ে এই ধরণের জিনিস সম্পর্কে ইঙ্গিত দিতে পারলে আমি তার পরিবর্তে একটি আবর্জনা সংগ্রহের এপিআই করব।

" রিকো মারিয়ানির পারফরম্যান্স টিডবিটস " আরও দেখুন



11

বৃহত 24/7 বা 24/6 সিস্টেমে - সিস্টেমগুলি যা বার্তায় প্রতিক্রিয়া জানায়, RPC অনুরোধ করে বা একটি ডাটাবেস পোল করে বা ক্রমাগত প্রক্রিয়া করে - মেমরি ফাঁস চিহ্নিত করার উপায় রাখার জন্য এটি দরকারী। এর জন্য, আমি কোনও প্রক্রিয়াকরণ অস্থায়ীভাবে স্থগিত করার এবং তারপরে সম্পূর্ণ আবর্জনা সংগ্রহের জন্য অ্যাপ্লিকেশনটিতে একটি প্রক্রিয়া যুক্ত করার ঝোঁক করি। এটি সিস্টেমকে একটি নিরিবিলি অবস্থায় রাখে যেখানে বাকি মেমরিটি বৈধভাবে দীর্ঘস্থায়ী মেমরি (ক্যাশে, কনফিগারেশন, এবং সি।) হয় বা অন্যথায় 'ফাঁস' হয় (এমন বস্তু যা প্রত্যাশিত বা মূলীকরণের প্রত্যাশিত নয় তবে প্রকৃতপক্ষে)।

এই প্রক্রিয়াটি থাকা মেমরির ব্যবহারের প্রোফাইল তৈরি করা অনেক সহজ করে তোলে কারণ সক্রিয় প্রক্রিয়াকরণ থেকে শোনার সাথে রিপোর্টগুলি মেঘ হবে না।

আপনি সমস্ত আবর্জনা পেয়েছেন তা নিশ্চিত হতে আপনার দুটি সংগ্রহ করতে হবে:

GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();

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


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

1
@ জারহয়েট: দুটি সংগ্রহ কেন প্রয়োজন তা বোঝার মূল চাবিকাঠিটি চূড়ান্তকরণকারীগুলির সাথে বস্তুর কী ঘটে তা বোঝা with দুর্ভাগ্যবশত আমি আপনি ঠিক যা বলছি না, কিন্তু একটি পঠিত আছে এই নিবন্ধটি এবং তাই এই প্রশ্ন
পল রুয়ান

10

আবর্জনা সংগ্রহকারী যে অ্যাপ্লিকেশনটির প্রকৃতি সম্পর্কে কিছু জানেন তখন আপনি জিসি.কলেক্ট () কল করতে পারেন। এটা ভাবতে লোভনীয় যে, লেখক হিসাবে এটি সম্ভবত খুব সম্ভবত। তবে, সত্যটি হ'ল জিসি হ'ল একটি চমত্কারভাবে লিখিত এবং পরীক্ষিত বিশেষজ্ঞ সিস্টেমের জন্য, এবং এটি বিরল আপনি নিম্ন স্তরের কোড পাথগুলি সম্পর্কে কিছু জানবেন যা এটি নয়।

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

তবে, বেশিরভাগ সময় জিসি যেভাবেই এটি করার জন্য যথেষ্ট স্মার্ট।


8

একটি স্মৃতি বিভাজন সমাধান হিসাবে। মেমরি স্ট্রিমে প্রচুর ডেটা লেখার সময় আমি একটি মেমোরি ব্যতিক্রম ছাড়ছিলাম (একটি নেটওয়ার্ক স্ট্রিম থেকে পড়া) reading ডেটা 8K খণ্ডে লেখা ছিল 128M পৌঁছানোর পরে প্রচুর স্মৃতি উপলব্ধ থাকলেও ব্যতিক্রম ছিল (তবে এটি খণ্ডিত হয়েছিল)। জিসি.কোলেক্টকে () কল করে সমস্যার সমাধান হয়েছে। আমি ঠিক করার পরে 1 জি ওভার পরিচালনা করতে সক্ষম হয়েছি।


7

রিকো মারিয়ানির এই নিবন্ধটি একবার দেখুন। জিসি.কলেক্টকে কল করার সময় তিনি দুটি নিয়ম দেন (নিয়ম 1 হ'ল: "করবেন না):

কখন জিসি কলেক্ট কল করুন ()


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

5

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

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

GC.Collect()
GC.WaitForPendingFinalizers()
GC.Collect()

আমার ব্যক্তিগত অভিজ্ঞতায়, রিলিজকমঅবজেক্টের সংমিশ্রণটি ব্যবহার করে এবং ময়লা থেকে আবর্জনা সংগ্রহের কল করা অফিস পণ্যগুলির বিশেষত এক্সেলের মেমরির ব্যবহারকে খুব হ্রাস করে।


হ্যাঁ আমি। নেট অ্যাক্সেসিং এক্সেল দিয়ে কম objects অবজেক্টের মাধ্যমেও কাজ করে ran এটি লক্ষণীয় গুরুত্বপূর্ণ, এটি ডিইবিইউজি মোডে ভাল কাজ করবে না কারণ সেখানে সিসি অপারেশনগুলি সীমাবদ্ধ। এটি কেবল রিলেস মোডে উদ্দেশ্য হিসাবে কাজ করবে। প্রাসঙ্গিক লিঙ্ক: stackoverflow.com/questions/17130382/...
Blechdose

5

আমি অ্যারে এবং তালিকায় কিছু পারফরম্যান্স টেস্ট করছিলাম

private static int count = 100000000;
private static List<int> GetSomeNumbers_List_int()
{
    var lstNumbers = new List<int>();
    for(var i = 1; i <= count; i++)
    {
        lstNumbers.Add(i);
    }
    return lstNumbers;
}
private static int[] GetSomeNumbers_Array()
{
    var lstNumbers = new int[count];
    for (var i = 1; i <= count; i++)
    {
        lstNumbers[i-1] = i + 1;
    }
    return lstNumbers;
}
private static int[] GetSomeNumbers_Enumerable_Range()
{
    return  Enumerable.Range(1, count).ToArray();
}

static void performance_100_Million()
{
    var sw = new Stopwatch();

    sw.Start();
    var numbers1 = GetSomeNumbers_List_int();
    sw.Stop();
    //numbers1 = null;
    //GC.Collect();
    Console.WriteLine(String.Format("\"List<int>\" took {0} milliseconds", sw.ElapsedMilliseconds));

    sw.Reset();
    sw.Start();
    var numbers2 = GetSomeNumbers_Array();
    sw.Stop();
    //numbers2 = null;
    //GC.Collect();
    Console.WriteLine(String.Format("\"int[]\" took {0} milliseconds", sw.ElapsedMilliseconds));

    sw.Reset();
    sw.Start();
//getting System.OutOfMemoryException in GetSomeNumbers_Enumerable_Range method
    var numbers3 = GetSomeNumbers_Enumerable_Range();
    sw.Stop();
    //numbers3 = null;
    //GC.Collect();

    Console.WriteLine(String.Format("\"int[]\" Enumerable.Range took {0} milliseconds", sw.ElapsedMilliseconds));
}

এবং আমি OutOfMemoryExceptiongetSomeNumbers_Neumerable_Range পদ্ধতিতে পেয়েছি মেমরিটি হ্রাস করার জন্য একমাত্র কর্মফল ound

numbers = null;
GC.Collect();

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

4

আপনার উদাহরণে, আমি মনে করি যে জিসি.কলেক্টকে কল করা সমস্যা নয়, বরং একটি ডিজাইনের সমস্যা রয়েছে।

যদি আপনি বিরতিতে জেগে উঠতে চলেছেন, (সময় নির্ধারিত) তবে আপনার প্রোগ্রামটি একক সম্পাদনের জন্য তৈরি করা উচিত (একবার টাস্কটি সম্পাদন করুন) এবং তারপরে সমাপ্ত হবে। তারপরে, আপনি নির্ধারিত বিরতিতে চালানোর জন্য প্রোগ্রামটিকে একটি নির্ধারিত টাস্ক হিসাবে সেট আপ করেছেন।

এইভাবে, আপনাকে জিসি.কলেক্ট কল করার সাথে নিজেকে উদ্বেগ করতে হবে না, (যা আপনাকে খুব কমই করা উচিত যদি কখনও করতে হয়)।

বলা হচ্ছে, এই বিষয়টিতে রিকো মারিয়ানির একটি দুর্দান্ত ব্লগ পোস্ট রয়েছে, যা এখানে পাওয়া যাবে:

http://blogs.msdn.com/ricom/archive/2004/11/29/271829.aspx


3

আপনি যখন মেমরি ফাঁস তৈরি করছেন না তা যাচাই করতে চাইলে জিসি.কলেক্ট () কল করার জন্য একটি দরকারী জায়গা একটি ইউনিট পরীক্ষায় রয়েছে (উদাহরণস্বরূপ আপনি যদি উইক রেফারেন্স বা শর্তসাপেক্ষে উইক টেবিল, গতিশীলভাবে উত্পন্ন কোড, ইত্যাদি দিয়ে কিছু করছেন)।

উদাহরণস্বরূপ, আমার কয়েকটি পরীক্ষা রয়েছে যেমন:

WeakReference w = CodeThatShouldNotMemoryLeak();
Assert.IsTrue(w.IsAlive);
GC.Collect();
GC.WaitForPendingFinalizers();
Assert.IsFalse(w.IsAlive);

এটি যুক্তিযুক্ত হতে পারে যে WeakReferences ব্যবহার করা নিজের এবং নিজেই একটি সমস্যা, তবে মনে হচ্ছে আপনি যদি এমন একটি সিস্টেম তৈরি করছেন যা এই ধরনের আচরণের উপর নির্ভর করে তবে GC. Collect () কল করা এই কোডটি যাচাই করার একটি ভাল উপায়।


3

স্কট হোল্ডেনের ব্লগ এন্ট্রি কখন (এবং কখন না করা) কল করা হয়েছিল জি.সি.কলেক্ট .NET কমপ্যাক্ট ফ্রেমওয়ার্কের সাথে সুনির্দিষ্ট , তবে নিয়মগুলি সাধারণত সমস্ত পরিচালিত বিকাশের ক্ষেত্রে প্রযোজ্য।



2
using(var stream = new MemoryStream())
{
   bitmap.Save(stream, ImageFormat.Png);
   techObject.Last().Image = Image.FromStream(stream);
   bitmap.Dispose();

   // Without this code, I had an OutOfMemory exception.
   GC.Collect();
   GC.WaitForPendingFinalizers();
   //
}

2

কিছু পরিস্থিতি রয়েছে যেখানে দুঃখিতের চেয়ে এটি নিরাপদ।

এখানে একটি অবস্থা।

এটি একটি লেখকের করা সম্ভব অপরিচালিতআই এল পুনর্লিখনগুলি ব্যবহার করে সি # তে ডিএলএল রচনা (কারণ এমন পরিস্থিতিতে রয়েছে যেখানে এটি প্রয়োজনীয়)।

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

দুঃখিত চেয়ে ভাল নিরাপদ.


2

আমি এখনও এই সম্পর্কে বেশ অনিশ্চিত। আমি একটি অ্যাপ্লিকেশন সার্ভারে 7 বছর ধরে কাজ করছি। আমাদের বড় ইনস্টলেশন 24 গিগাবাইট রাম ব্যবহার করে। এটির বহুবিধ বহুবিশেষ এবং জিসি.কলেক্ট () এর জন্য সমস্ত কল সত্যই ভয়ানক পারফরম্যান্স সমস্যার সমাধান করেছে।

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

জিসি.কালেক্ট () কলগুলি সরাতে আমাদের তৃতীয় পক্ষের সমস্ত উপাদানগুলি রিফ্যাক্টর করতে হয়েছিল এবং এটি করার পরে সকলেই ভাল কাজ করেছে।

তবে আমি উইন 32 এ সার্ভারগুলিও চালিয়ে যাচ্ছি এবং এখানে আমি আউটআফমিউরিএক্সেপশন পাওয়ার পরে জিসি.ক্ল্যাক্ট () ব্যবহার করে ভারী ব্যবহার শুরু করি।

তবে আমি এটি সম্পর্কে বেশ অনিশ্চিত, কারণ আমি প্রায়শই লক্ষ্য করেছি যে, আমি যখন 32 বিট-তে একটি ওওএম পাই এবং আমি আবারও একই অপারেশন চালানোর চেষ্টা করি, জিসি.ক্ল্যাক্ট () না কল করে, এটি ঠিক কাজ করেছিল।

একটা জিনিস আমি অবাক করেছিলাম ওম ব্যতিক্রম নিজেই ... আমি যদি নেট নেট ফ্রেমওয়ার্কটি লিখে থাকতাম এবং আমি কোনও মেমরি ব্লক বরাদ্দ করতে না পারি, তবে আমি জিসি.ক্ল্যাক্ট (), ডিফ্র্যাগ মেমরি (??) ব্যবহার করতাম, আবার চেষ্টা করুন , এবং যদি আমি এখনও একটি নিখরচায় মেমোরি ব্লকটি খুঁজে না পাই তবে আমি ওওএম-ব্যতিক্রম নষ্ট করব।

বা কমপক্ষে এই আচরণটিকে কনফিগারযোগ্য বিকল্প হিসাবে তৈরি করুন, জিসি.কলেক্টের সাথে পারফরম্যান্স ইস্যুটির ত্রুটিগুলি।

সমস্যাটি "সমাধান" করতে এখন আমার অ্যাপ্লিকেশনটিতে এর মতো প্রচুর কোড রয়েছে:

public static TResult ExecuteOOMAware<T1, T2, TResult>(Func<T1,T2 ,TResult> func, T1 a1, T2 a2)
{

    int oomCounter = 0;
    int maxOOMRetries = 10;
    do
    {
        try
        {
            return func(a1, a2);
        }
        catch (OutOfMemoryException)
        {
            oomCounter++;
            if (maxOOMRetries > 10)
            {
                throw;
            }
            else
            {
                Log.Info("OutOfMemory-Exception caught, Trying to fix. Counter: " + oomCounter.ToString());
                System.Threading.Thread.Sleep(TimeSpan.FromSeconds(oomCounter * 10));
                GC.Collect();
            }
        }
    } while (oomCounter < maxOOMRetries);

    // never gets hitted.
    return default(TResult);
}

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


একটি উপাদান কল করা উচিত নয় GC.Collect। যেহেতু এটির প্রয়োগের ব্যাপক প্রভাব রয়েছে কেবলমাত্র অ্যাপ্লিকেশনটিতে এটি করা উচিত (যদি আদৌ থাকে)।
কোডসইনচাউস

If i would have written the .Net Framework, and i can't alloc a memory block, i would use GC.Collect(),- আমি মনে করি তারা ইতিমধ্যে এটি করছে - আমি ইঙ্গিতগুলি দেখেছি যে অভ্যন্তরীণ জিসি ট্রিগারগুলির মধ্যে একটি হ'ল মেমরি বরাদ্দকরণে কিছু ব্যর্থতা।
জি স্টোনেভ

2

আপনার খুব বেশি ব্যয়বহুল হওয়ার কারণে GC. Collect () ব্যবহার এড়াতে চেষ্টা করা উচিত। এখানে একটি উদাহরণ:

        public void ClearFrame(ulong timeStamp)
    {
        if (RecordSet.Count <= 0) return;
        if (Limit == false)
        {
            var seconds = (timeStamp - RecordSet[0].TimeStamp)/1000;
            if (seconds <= _preFramesTime) return;
            Limit = true;
            do
            {
                RecordSet.Remove(RecordSet[0]);
            } while (((timeStamp - RecordSet[0].TimeStamp) / 1000) > _preFramesTime);
        }
        else
        {
            RecordSet.Remove(RecordSet[0]);

        }
        GC.Collect(); // AVOID
    }

পরীক্ষার ফলাফল: সিপিইউ ব্যবহার 12%

আপনি যখন এতে পরিবর্তন করেন:

        public void ClearFrame(ulong timeStamp)
    {
        if (RecordSet.Count <= 0) return;
        if (Limit == false)
        {
            var seconds = (timeStamp - RecordSet[0].TimeStamp)/1000;
            if (seconds <= _preFramesTime) return;
            Limit = true;
            do
            {
                RecordSet[0].Dispose(); //  Bitmap destroyed!
                RecordSet.Remove(RecordSet[0]);
            } while (((timeStamp - RecordSet[0].TimeStamp) / 1000) > _preFramesTime);
        }
        else
        {
            RecordSet[0].Dispose(); //  Bitmap destroyed!
            RecordSet.Remove(RecordSet[0]);

        }
        //GC.Collect();
    }

পরীক্ষার ফলাফল: সিপিইউ ব্যবহারের 2-3%


1

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

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

Https://stackoverflow.com/a/58810699/8685342 থেকে :

try
{
    if (port != null)
        port.Close(); //this will throw an exception if the port was unplugged
}
catch (Exception ex) //of type 'System.IO.IOException'
{
    System.GC.Collect();
    System.GC.WaitForPendingFinalizers();
}

port = null;

0

এটি প্রশ্নের সাথে প্রাসঙ্গিক নয়, তবে এক্সএসএলটির জন্য। নেট (এক্সএসএলকম্পিল্ড ট্রান্সফর্ম) রূপান্তরিত হয় তবে আপনার কোনও বিকল্প নাও থাকতে পারে। অন্য প্রার্থী হলেন এমএসএইচটিএমএল নিয়ন্ত্রণ।


0

আপনি যদি 4.5 এর চেয়ে কম নেট সংস্করণ ব্যবহার করেন তবে ম্যানুয়াল সংগ্রহ অনিবার্য হতে পারে (বিশেষত যদি আপনি অনেকগুলি 'বৃহত অবজেক্ট' নিয়ে কাজ করে থাকেন)।

এই লিঙ্কটি কেন বর্ণনা করে:

https://blogs.msdn.microsoft.com/dotnet/2011/10/03/large-object-heap-improvements-in-net-4-5/


0

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

আর একটি ভাল সমাধান হ'ল বস্তুগুলি যখন আর প্রয়োজন হয় না তখন তা নিষ্পত্তি করে দেওয়া। দুর্ভাগ্যক্রমে অনেক ক্ষেত্রে এটি এত সহজ নয়।


0

যেহেতু ছোট অবজেক্ট হিপ (এসওএইচ) এবং লার্জ অবজেক্ট হিপ (এলওএইচ) রয়েছে

আমরা এসপিতে ডি-রেফারেন্স অবজেক্টটি সাফ করতে জিসি.ক্লোকটকে () কল করতে পারি এবং জীবিত অবজেক্টটিকে পরবর্তী প্রজন্মের দিকে নিয়ে যেতে পারি।

.NET4.5-এ, আমরা লজবজেক্টহ্যাপ কমপ্যাকশনমোড ব্যবহার করেও লোহকে কমপ্যাক্ট করতে পারি


0

যদি আপনি প্রচুর নতুন System.Drawing.Bitmapঅবজেক্ট তৈরি করে থাকেন তবে আবর্জনা সংগ্রাহক সেগুলি সাফ করবেন না। অবশেষে জিডিআই + ভাববে যে আপনি মেমরির বাইরে চলেছেন এবং একটি "প্যারামিটারটি বৈধ নয়" ব্যতিক্রম নিক্ষেপ করবে। GC.Collect()প্রতিবার প্রায়শই কল করা (খুব বেশি ঘন ঘন নয়!) মনে হয় এই সমস্যার সমাধান হচ্ছে।

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