ฉันยังค่อนข้างไม่แน่ใจเกี่ยวกับเรื่องนี้ ฉันทำงานมาแล้ว 7 ปีใน Application Server การติดตั้งที่ใหญ่กว่าของเราใช้ประโยชน์จาก 24 GB Ram Multithreaded อย่างสูงและทุกสายเรียกร้องให้ GC.Collect () พบปัญหาประสิทธิภาพที่แย่มาก
คอมโพเนนต์ของบุคคลที่สามหลายแห่งใช้ GC.Collect () เมื่อพวกเขาคิดว่ามันฉลาดที่จะทำสิ่งนี้ในตอนนี้ ดังนั้นรายงาน Excel ที่เรียบง่ายจึงบล็อก App Server สำหรับเธรดทั้งหมดหลายครั้งต่อนาที
เราต้องปรับโครงสร้างองค์ประกอบบุคคลที่สามทั้งหมดเพื่อที่จะลบการเรียก GC.Collect () และทำงานได้ดีหลังจากทำเช่นนี้
แต่ฉันใช้เซิร์ฟเวอร์บน Win32 เช่นกันและที่นี่ฉันเริ่มใช้ GC.Collect () อย่างหนักหลังจากได้รับ OutOfMemoryException
แต่ฉันก็ค่อนข้างไม่แน่ใจเกี่ยวกับเรื่องนี้เพราะฉันมักจะสังเกตเห็นว่าเมื่อฉันได้รับ OOM ใน 32 บิตและฉันพยายามที่จะเรียกใช้การดำเนินงานเดียวกันอีกครั้งโดยไม่ต้องโทร GC.Collect () มันใช้งานได้ดี
สิ่งหนึ่งที่ฉันสงสัยคือ OOM Exception นั้น ... ถ้าฉันจะเขียน. Net Framework และฉันไม่สามารถจัดสรรบล็อกหน่วยความจำฉันจะใช้ GC.Collect (), หน่วยความจำ Defrag (??) ลองอีกครั้ง และถ้าฉันยังหาบล็อกหน่วยความจำว่างไม่ได้ฉันก็จะโยน OOM-Exception
หรืออย่างน้อยก็ทำให้พฤติกรรมนี้เป็นตัวเลือกที่กำหนดค่าได้เนื่องจากข้อเสียของปัญหาประสิทธิภาพด้วย GC.Collect
ตอนนี้ฉันมีรหัสจำนวนมากเช่นนี้ในแอปของฉันเพื่อ "แก้ปัญหา" ปัญหา:
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);
}
(โปรดทราบว่าลักษณะการทำงานของ Thread.Sleep () เป็นลักษณะการทำงาน apecific จริง ๆ เนื่องจากเรากำลังเรียกใช้บริการแคช ORM และบริการใช้เวลาในการปล่อยวัตถุแคชทั้งหมดถ้า RAM มีค่าที่กำหนดไว้ล่วงหน้าดังนั้นจึงรอ ไม่กี่วินาทีในครั้งแรกและเพิ่มเวลาการรอแต่ละครั้งที่เกิดขึ้นของ OOM)