17 using System.Threading;
18 using System.Threading.Tasks;
58 public bool ExecuteWithTimeLimit(TimeSpan timeSpan, Func<IsolatorLimitResult> withinCustomLimits, Action codeBlock,
long memoryCap = 1024,
int sleepIntervalMillis = 1000,
WorkerThread workerThread =
null)
60 workerThread?.Add(codeBlock);
62 var task = workerThread ==
null
69 return MonitorTask(task, timeSpan, withinCustomLimits, memoryCap, sleepIntervalMillis);
73 if (!task.IsCompleted)
76 workerThread?.FinishedWorkItem.Set();
82 private bool MonitorTask(Task task,
84 Func<IsolatorLimitResult> withinCustomLimits,
85 long memoryCap = 1024,
86 int sleepIntervalMillis = 1000)
89 withinCustomLimits = withinCustomLimits ?? (() =>
new IsolatorLimitResult(TimeSpan.Zero,
string.Empty));
91 var message =
string.Empty;
94 var utcNow = DateTime.UtcNow;
95 var end = utcNow + timeSpan;
100 memoryCap *= 1024 * 1024;
101 var spikeLimit = memoryCap*2;
105 memoryCap =
int.MaxValue;
106 spikeLimit =
int.MaxValue;
112 var sample = Convert.ToDouble(GC.GetTotalMemory(memoryUsed > memoryCap * 0.8));
115 memoryUsed = Convert.ToInt64((emaPeriod-1)/emaPeriod * memoryUsed + (1/emaPeriod)*sample);
118 if (memoryUsed > memoryCap || sample > spikeLimit)
120 message = Messages.Isolator.MemoryUsageMaxedOut(PrettyFormatRam(memoryCap), PrettyFormatRam((
long)sample));
124 if (utcNow > memoryLogger)
126 if (memoryUsed > memoryCap * 0.8)
128 Log.
Error(Messages.Isolator.MemoryUsageOver80Percent(sample));
131 Log.
Trace(
"Isolator.ExecuteWithTimeLimit(): " +
132 Messages.Isolator.MemoryUsageInfo(
133 PrettyFormatRam(memoryUsed),
134 PrettyFormatRam((
long)sample),
135 PrettyFormatRam(OS.ApplicationMemoryUsed * 1024 * 1024),
136 isolatorLimitResult.CurrentTimeStepElapsed,
137 (
int)Math.Ceiling(OS.CpuUsage)));
139 memoryLogger = utcNow.AddMinutes(1);
143 isolatorLimitResult = withinCustomLimits();
144 if (!isolatorLimitResult.IsWithinCustomLimits)
146 message = isolatorLimitResult.ErrorMessage;
150 if (task.Wait(utcNow.GetSecondUnevenWait(sleepIntervalMillis)))
155 utcNow = DateTime.UtcNow;
158 if (task.IsCompleted ==
false)
162 Log.
Trace($
"Isolator.ExecuteWithTimeLimit(): Operation was canceled");
163 throw new OperationCanceledException(
"Operation was canceled");
165 else if (
string.IsNullOrEmpty(message))
167 message = Messages.Isolator.MemoryUsageMonitorTaskTimedOut(timeSpan);
168 Log.
Trace($
"Isolator.ExecuteWithTimeLimit(): {message}");
172 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();