17 using System.Threading;
18 using System.Threading.Tasks;
75 public bool ExecuteWithTimeLimit(TimeSpan timeSpan, Func<IsolatorLimitResult> withinCustomLimits, Action codeBlock,
long memoryCap = 1024,
int sleepIntervalMillis = 1000,
WorkerThread workerThread =
null)
77 workerThread?.Add(codeBlock);
79 var task = workerThread ==
null
86 return MonitorTask(task, timeSpan, withinCustomLimits, memoryCap, sleepIntervalMillis);
90 if (!task.IsCompleted)
93 workerThread?.FinishedWorkItem.Set();
99 private bool MonitorTask(Task task,
101 Func<IsolatorLimitResult> withinCustomLimits,
102 long memoryCap = 1024,
103 int sleepIntervalMillis = 1000)
106 withinCustomLimits = withinCustomLimits ?? (() =>
new IsolatorLimitResult(TimeSpan.Zero,
string.Empty));
108 var message =
string.Empty;
111 var utcNow = DateTime.UtcNow;
112 var end = utcNow + timeSpan;
117 memoryCap *= 1024 * 1024;
118 var spikeLimit = memoryCap*2;
120 while (!task.IsCompleted && utcNow < end)
123 var sample = Convert.ToDouble(GC.GetTotalMemory(memoryUsed > memoryCap * 0.8));
126 memoryUsed = Convert.ToInt64((emaPeriod-1)/emaPeriod * memoryUsed + (1/emaPeriod)*sample);
129 if (memoryUsed > memoryCap || sample > spikeLimit)
131 message =
Messages.
Isolator.MemoryUsageMaxedOut(PrettyFormatRam(memoryCap), PrettyFormatRam((
long)sample));
135 if (utcNow > memoryLogger)
137 if (memoryUsed > memoryCap * 0.8)
139 Log.
Error(Messages.Isolator.MemoryUsageOver80Percent(sample));
142 Log.
Trace(
"Isolator.ExecuteWithTimeLimit(): " +
143 Messages.Isolator.MemoryUsageInfo(
144 PrettyFormatRam(memoryUsed),
145 PrettyFormatRam((
long)sample),
146 PrettyFormatRam(OS.ApplicationMemoryUsed * 1024 * 1024),
147 isolatorLimitResult.CurrentTimeStepElapsed,
148 (
int)Math.Ceiling(OS.CpuUsage)));
150 memoryLogger = utcNow.AddMinutes(1);
154 isolatorLimitResult = withinCustomLimits();
155 if (!isolatorLimitResult.IsWithinCustomLimits)
157 message = isolatorLimitResult.ErrorMessage;
161 if (task.Wait(utcNow.GetSecondUnevenWait(sleepIntervalMillis)))
166 utcNow = DateTime.UtcNow;
169 if (task.IsCompleted ==
false &&
string.IsNullOrEmpty(message))
171 message = Messages.Isolator.MemoryUsageMonitorTaskTimedOut(timeSpan);
172 Log.
Trace($
"Isolator.ExecuteWithTimeLimit(): {message}");
175 if (!
string.IsNullOrEmpty(message))
178 Log.
Error($
"Security.ExecuteWithTimeLimit(): {message}");
179 throw new TimeoutException(message);
181 return task.IsCompleted;
196 return ExecuteWithTimeLimit(timeSpan,
null, codeBlock, memoryCap, sleepIntervalMillis, workerThread);
204 private static string PrettyFormatRam(
long ramInBytes)
206 return Math.Round(Convert.ToDouble(ramInBytes/(1024*1024))).ToStringInvariant();