Exemplo n.º 1
0
        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);
        }
Exemplo n.º 2
0
        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();
                    }
                }
            }
        }