public IEnumerator<object> LoadDiff(string filename) { var progress = new CallbackProgressListener { OnSetStatus = (status) => { LoadingPanel.Text = status; }, OnSetMaximum = (maximum) => { if (LoadingProgress.Maximum != maximum) LoadingProgress.Maximum = maximum; }, OnSetProgress = (value) => { if (value.HasValue) { var v = value.Value; if (LoadingProgress.Style != ProgressBarStyle.Continuous) LoadingProgress.Style = ProgressBarStyle.Continuous; LoadingProgress.Value = Math.Min(v + 1, LoadingProgress.Maximum); LoadingProgress.Value = v; } else { if (LoadingProgress.Style != ProgressBarStyle.Marquee) LoadingProgress.Style = ProgressBarStyle.Marquee; } } }; var rtc = new RunToCompletion<HeapDiff>( HeapDiff.FromFile(filename, progress) ); using (rtc) yield return rtc; DiffLoaded(rtc.Result, filename); }
protected IEnumerator<object> SymbolResolverTask() { var batch = new List<UInt32>(); var nullProgress = new CallbackProgressListener(); ActivityIndicator.CountedItem progress = null; while (true) { var count = SymbolResolveBatchSize - batch.Count; SymbolResolveQueue.DequeueMultiple(batch, count); if (batch.Count == 0) { if (progress != null) { progress.Decrement(); progress = null; } if (!SymbolResolveState.Progress.Active && (SymbolResolveQueue.Count <= 0)) { SymbolResolveState.Count = 0; OnSymbolCacheUpdated(); } var f = SymbolResolveQueue.Dequeue(); using (f) yield return f; batch.Add(f.Result); } else { if (progress == null) progress = SymbolResolveState.Progress.Increment(); var maximum = SymbolResolveState.Count + Math.Max(0, SymbolResolveQueue.Count) + 1; progress.Maximum = maximum; progress.Progress = Math.Min(maximum, SymbolResolveState.Count); string infile = Path.GetTempFileName(), outfile = Path.GetTempFileName(); var padNumberRight = (Func<uint, int, string>)((num, length) => { var result = String.Format("{0:X}", num); if (result.Length < length) result = new String(' ', length - result.Length) + result; return result; }); var symbolModules = SymbolModules.ToArray(); yield return Future.RunInThread(() => { using (var sw = new StreamWriter(infile, false, Encoding.ASCII)) { sw.WriteLine("// Loaded modules:"); sw.WriteLine("// Base Size Module"); foreach (var module in symbolModules) sw.WriteLine( "// {0} {1} {2}", padNumberRight(module.BaseAddress, 8), padNumberRight(module.Size, 8), Path.GetFullPath(module.Filename) ); sw.WriteLine("//"); sw.WriteLine("// Process modules enumerated."); sw.WriteLine(); sw.WriteLine("*- - - - - - - - - - Heap 0 Hogs - - - - - - - - - -"); sw.WriteLine(); for (int i = 0; i < batch.Count; i++) { sw.WriteLine( "{0:X8} bytes + {1:X8} at {2:X8} by BackTrace{3:X8}", 1, 0, i + 1, i + 1 ); sw.WriteLine("\t{0:X8}", batch[i]); sw.WriteLine(); } } }); IDictionary<string, string> environment = null; yield return GetEnvironment().Bind(() => environment); var psi = new ProcessStartInfo( Settings.UmdhPath, String.Format( "\"{0}\" -f:\"{1}\"", infile, outfile ) ); using (var rp = Scheduler.Start( Program.RunProcess( psi, ProcessPriorityClass.Idle, environment ), TaskExecutionPolicy.RunAsBackgroundTask )) yield return rp; using (Finally.Do(() => { try { File.Delete(infile); } catch { } try { File.Delete(outfile); } catch { } })) { var rtc = new RunToCompletion<HeapDiff>( HeapDiff.FromFile(outfile, nullProgress) ); using (rtc) yield return rtc; var fProcess = Future.RunInThread(() => { var cacheBatch = Database.SymbolCache.CreateBatch(batch.Count); DecisionUpdateCallback<HashSet<UInt32>> updateCallback = (ref HashSet<UInt32> oldValue, ref HashSet<UInt32> newValue) => { newValue.UnionWith(oldValue); return true; }; foreach (var traceback in rtc.Result.Tracebacks) { var index = (int)(traceback.Key) - 1; var key = batch[index]; var frame = traceback.Value.Frames.Array[traceback.Value.Frames.Offset]; lock (SymbolResolveLock) { ResolvedSymbolCache[key] = frame; PendingSymbolResolves.Remove(key); } cacheBatch.Add(key, frame); if (frame.Function != null) { var tempHash = new HashSet<uint>(); tempHash.Add(key); } } foreach (var frame in batch) { if (!PendingSymbolResolves.Contains(frame)) continue; Interlocked.Increment(ref TotalFrameResolveFailures); var tf = new TracebackFrame(frame); lock (SymbolResolveLock) { ResolvedSymbolCache[frame] = tf; PendingSymbolResolves.Remove(frame); } cacheBatch.Add(frame, tf); // Console.WriteLine("Could not resolve: {0:X8}", frame.Frame); } return new IBatch[] { cacheBatch }; }); yield return fProcess; foreach (var manglerBatch in fProcess.Result) yield return manglerBatch.Execute(); Interlocked.Add(ref SymbolResolveState.Count, batch.Count); batch.Clear(); } } } }