예제 #1
0
        async Task TestCollectStacksHelper(
            string strStacksToCollect,
            int nSizeSpecial,
            int NumFramesToCapture,
            int HeapAllocSizeMinValue,
            int StlAllocLimit,
            int nIter            = 10000,
            int nThreads         = 60,
            bool IsLimited       = false,
            bool WaitForDoCsLife = false)
        {
            using (var oInterop = new Interop())
            {
                var obj = GetTestHeapStacks(oInterop);
                obj.SetHeapCollectParams(strStacksToCollect, NumFramesToCapture, HeapAllocSizeMinValue, StlAllocLimit);
                obj.StartDetours(out var pDetours);
                var lstTasks = new List <Task>
                {
                    Task.Run(() => DoCSLife())
                };
                if (WaitForDoCsLife)
                {
                    await lstTasks[0];
                }
                var procHeap            = Heap.GetProcessHeap();
                var lstIntentionalLeaks = new List <IntPtr>();
                for (int iThread = 0; iThread < nThreads; iThread++)
                {
                    var task = Task.Run(() =>
                    {
                        DoSomeNativeAllocs(nIter, iThread, nSizeSpecial, lstIntentionalLeaks);
                    });
                    lstTasks.Add(task);
                }
                await Task.WhenAll(lstTasks);

                //                await Task.Delay(TimeSpan.FromSeconds(1)); // let things settle down before undetouring
                LogMessage($"Intentional Leaks {lstIntentionalLeaks.Count:n0}  TotAllocs={nIter * nThreads:n0}");
                obj.StopDetours(pDetours);
                //                await Task.Delay(TimeSpan.FromSeconds(1)); // let things settle down before undetouring
                var heapStats    = new HeapCollectStats(strStacksToCollect);
                var ptrHeapStats = heapStats.GetPointer();
                obj.GetStats(ptrHeapStats);

                heapStats = HeapCollectStats.FromPointer(ptrHeapStats);
                LogMessage($"Allocation stacks {heapStats}");
                Array.ForEach <HeapCollectStatDetail>(heapStats.details, (detail) =>
                {
                    LogMessage($"  {detail}");
                });
                Assert.IsTrue(heapStats.MyRtlAllocateHeapCount > nIter * nThreads, $"Expected > {nIter * nThreads}, got {heapStats.MyRtlAllocateHeapCount}");
                var det = heapStats.details.Where(s => s.AllocSize == nSizeSpecial).Single();
                if (IsLimited)
                {
                    Assert.IsTrue(heapStats.fReachedMemLimit, $"Test says limited memory, but didn't reach limit");
                }
                else
                {
                    Assert.IsFalse(heapStats.fReachedMemLimit, $"Test says not limited mem, but did reach limit");
                }
                if (!heapStats.fReachedMemLimit)
                {
                    Assert.IsTrue(det.NumStacksCollected >= nIter, $"Expected numstacks collected ({det.NumStacksCollected}) > {nIter}");
                }
                DumpCallStacksCollected(obj, heapStats, nSizeSpecial);

                foreach (var addr in lstIntentionalLeaks)
                {
                    Heap.HeapFree(procHeap, 0, addr);
                }
                heapStats.Dispose();
                obj.CollectStacksUninitialize();
                Marshal.FreeHGlobal(ptrHeapStats);
                Marshal.ReleaseComObject(obj);
                //                Assert.Fail($"#HeapAlloc={heapStats.MyRtlAllocateHeapCount}");
            }
        }
예제 #2
0
        public void TestCollectStackAddresses()
        {
            int nSizeSpecial       = 1027;
            var strStacksToCollect = $"{nSizeSpecial}:0";

            using (var oInterop = new Interop())
            {
                var obj = GetTestHeapStacks(oInterop);
                obj.SetHeapCollectParams(strStacksToCollect, NumFramesToCapture: 20, HeapAllocSizeMinValue: 1048576, StlAllocLimit: 65536 * 10);
                obj.StartDetours(out var pDetours);
                int nIter               = 100;
                int nThreads            = 1;
                var lstIntentionalLeaks = new List <IntPtr>();
                for (int iThread = 0; iThread < nThreads; iThread++)
                {
                    DoSomeNativeAllocs(nIter, iThread, nSizeSpecial, lstIntentionalLeaks);
                }
                LogMessage($"Intentional Leaks {lstIntentionalLeaks.Count:n0}  TotAllocs={nIter * nThreads:n0}");
                var heapStats = new HeapCollectStats(strStacksToCollect);
                obj.StopDetours(pDetours);
                var ptrHeapStats = heapStats.GetPointer();
                obj.GetStats(ptrHeapStats);

                heapStats = HeapCollectStats.FromPointer(ptrHeapStats);
                LogMessage($"Allocation stacks {heapStats}");
                Array.ForEach <HeapCollectStatDetail>(heapStats.details, (detail) =>
                {
                    LogMessage($"  {detail}");
                });
                Assert.IsTrue(heapStats.MyRtlAllocateHeapCount > nIter * nThreads, $"Expected > {nIter * nThreads}, got {heapStats.MyRtlAllocateHeapCount}");
                if (!heapStats.fReachedMemLimit)
                {
                    var det = heapStats.details.Where(s => s.AllocSize == nSizeSpecial).Single();
                    Assert.IsTrue(det.NumStacksCollected >= nIter, $"Expected numstacks collected ({det.NumStacksCollected}) > {nIter}");
                }
                {
                    DumpCallStacksCollected(obj, heapStats, nSizeSpecial);
                }
                {
                    var    lstLiveAllocs = new List <LiveHeapAllocation>();
                    int    numAllocs     = 0;
                    IntPtr ptrData       = IntPtr.Zero;
                    obj.GetAllocationAddresses(ref numAllocs, ref ptrData);
                    LogMessage($"# LiveAllocStacks (allocs that are still live)= {numAllocs}");
                    for (int i = 0; i < numAllocs; i++)
                    {
                        var allocdata = Marshal.PtrToStructure <LiveHeapAllocation>(ptrData + i * IntPtr.Size);
                        var str       = "Freed";
                        if (lstIntentionalLeaks.Contains(allocdata.addr))
                        {
                            str = Marshal.PtrToStringAnsi(allocdata.addr);
                            Assert.IsTrue(str.StartsWith("This is a test string"));
                        }
                        LogMessage($" {i}  addr={(uint)(allocdata.addr):x8} stackhash={allocdata.stackhash:x8} str={str}");
                    }
                    Marshal.FreeHGlobal(ptrData);
                }

                foreach (var addr in lstIntentionalLeaks)
                {
                    Heap.HeapFree(Heap.GetProcessHeap(), 0, addr);
                }
                heapStats.Dispose();
                obj.CollectStacksUninitialize();
                Marshal.FreeHGlobal(ptrHeapStats);
                Marshal.ReleaseComObject(obj);
                //                Assert.Fail($"#HeapAlloc={heapStats.MyRtlAllocateHeapCount}");
            }
        }