#c# #.net-core #garbage-collection
Вопрос:
Я пытаюсь создать ногрегион. Прежде чем я это сделаю, я проверяю, находится ли GC уже в регионе NOGC. Мой отладчик говорит, что это еще не так, он все еще выдает, как если бы это было так.
А вот окружающий код для контекста:
var firstTurn = true;
GCSettings.LatencyMode = GCLatencyMode.LowLatency;
while (state0.Round < Constants.MAX_ROUNDS amp;amp; state1.Round < Constants.MAX_ROUNDS)
{
Log($"GC Mode at begining: {GCSettings.LatencyMode}");
if (GCSettings.LatencyMode != GCLatencyMode.NoGCRegion) GC.TryStartNoGCRegion(15728640, true);
var time = firstTurn ? 900 : 90;
var action0 = mcts0.GetBest(state0, time);
var action1 = mcts1.GetBest(state1, time);
state0.Players[0].Action = action0;
state0.Players[1].Action = action1;
state1.Players[0].Action = action1;
state1.Players[1].Action = action0;
state0 = actionApplyer.ApplyActions(state0);
state1 = actionApplyer.ApplyActions(state1);
firstTurn = false;
Log($"GC Mode at end: {GCSettings.LatencyMode}");
if (GCSettings.LatencyMode == GCLatencyMode.NoGCRegion) GC.EndNoGCRegion();
}
Что я делаю не так? И почему среда выполнения говорит, что режим NoCGRegion выполняется, когда я проверяю, что это не так раньше.
Комментарии:
1. Вы пробовали войти
NoCGRegion
один раз, прежде чем войти в цикл во время выполнения работы, связанной с GC?GC.TryStartNoGCRegion
не любит, когда его вызывают вложенным или близко друг к другу.
Ответ №1:
Проблема в том, что код вызывает TryStartNoGCRegion несколько раз вложенным способом, против которого рекомендуют документы (примечания) :
Вы не можете вложить вызовы в метод TryStartNoGCRegion, и вы должны вызывать метод EndNoGCRegion только в том случае, если среда выполнения в настоящее время не находится в режиме задержки в регионе GC. Другими словами, вы не должны вызывать TryStartNoGCRegion несколько раз (после первого вызова метода последующие вызовы не будут успешными), и вы не должны ожидать, что вызовы в EndNoGCRegion будут успешными только потому, что первый вызов в TryStartNoGCRegion удался.
Вызов EndNoGCRegion не происходит, потому что GC находится в режиме с низкой задержкой:
если (GCSettings.LatencyMode == GCLatencyMode.NoGCRegion) GC.EndNoGCRegion();
Таким образом, на следующей итерации цикла код снова пытается войти в NoGCRegion и отключается:
если (GCSettings.LatencyMode != GCLatencyMode.NoGCRegion) GC.TriStartNoGCRegion(15728640, верно);
Стоит отметить, что замечания в документах содержат ряд предостережений об этом типе функциональности и о том, что она может вообще не работать, даже если код вызывает ее правильно. Лично я бы попытался найти решение, которое вообще не требует взаимодействия с GC; на ум приходит mempool.