/// <summary> /// 申请一个Page /// </summary> /// <param name="elemSize">page元素的尺寸</param> /// <param name="size">实际申请的内存尺寸</param> /// <returns></returns> public PoolPage AllocPage(int elemSize, int size) { //如果可用的字节数不足则返回null if (this.Availables < size) { return(null); } //计算申请内存尺寸在memoryMap中的深度 AllocInfo alloc = CalcAllocDepth(size); //通过深度获得节点编号 int id = AllocHandle(alloc.Depth); int tableId = PageIdx(id); PoolPage page = subpages[tableId]; if (page == null) { page = new PoolPage(this, id, alloc.PageCapacity, elemSize); subpages[tableId] = page; } else if (!page.Allocated) { //找到一个被重置过的Page则重新进行分配 page.ReAlloc(alloc.PageCapacity, elemSize); } usedables += pageSize; return(page); }
public void InitAllocationPoints(List <MemOperation> memOps) { MemBlockTree tree = new MemBlockTree(); uint totalMem = 0; foreach (MemOperation op in memOps) { if (op.OpType == MemOperation.Type.Alloc) { MemBlock block = op.UserData as MemBlock; tree.AddMemBlock(block); totalMem += block.m_size; } } foreach (MemOperation op in memOps) { if (op.OpType == MemOperation.Type.Alloc) { AddAllocationPoint(op.UserData as MemBlock, tree); } } for (int i = 0; i < dataGridAllocs.Rows.Count; ++i) { AllocInfo allocInfo = dataGridAllocs.Rows[i].Tag as AllocInfo; float percentage = allocInfo.numBytes * 100.0f / totalMem; String[] rowData = { allocInfo.symbol.functionName, allocInfo.numBytes.ToString(), allocInfo.numBlocks.ToString(), percentage.ToString() }; dataGridAllocs.Rows[i].SetValues(rowData); } }
public void poolchunk_CalcAllocDepth_Test() { int size1 = 10; int size2 = 8193; int size3 = 8192 * 2 + 1; int size4 = 8192 * 10000; var chunk = new PoolChunk(); AllocInfo ai1 = chunk.CalcAllocDepth(size1); AllocInfo ai2 = chunk.CalcAllocDepth(size2); AllocInfo ai3 = chunk.CalcAllocDepth(size3); Assert.AreEqual(ai1.Depth, 11); Assert.AreEqual(ai2.Depth, 10); Assert.AreEqual(ai3.Depth, 9); try { AllocInfo ai4 = chunk.CalcAllocDepth(size4); Assert.Fail(); } catch (IndexOutOfRangeException ex) { Assert.IsTrue(true); Console.WriteLine(ex.Message); } }
public static void DbgOnAlloc(IntPtr ptr, IntPtr size) { Monitor.Enter(lockable); if (handles.ContainsKey(ptr)) { if (handles[ptr].allocated == false) { // previous handle was successfully freed handles[ptr] = new AllocInfo() { size = size, lastUse = new StackTrace() }; } else { Console.WriteLine(handles[ptr].lastUse); Monitor.Exit(lockable); throw new Exception("MDL [Alloc]: handle " + ptr + " was already allocated!"); } } else { handles.Add(ptr, new AllocInfo() { size = size, lastUse = new StackTrace() }); } Monitor.Exit(lockable); for (int i = 0; i < 4; ++i) { Marshal.WriteInt32(ptr, i * 4, 0x5facade7); Marshal.WriteInt32(ptr, size.ToInt32() + 16 + i * 4, 0x5facade7); } }
private void Dump(AllocInfo[] records, int?errorLine) { for (int i = 0; i < records.Length; i++) { AllocInfo record = records[i]; WriteInfoLine(record.count.ToString(), record.bytes.ToString(), record.typeName, errorLine.HasValue && (errorLine.Value == i)); } }
private void dataGridAllocs_CellDoubleClick(object sender, DataGridViewCellEventArgs e) { if (e.ColumnIndex >= 0 && e.RowIndex >= 0) { DataGridViewCell cell = dataGridAllocs.Rows[e.RowIndex].Cells[e.ColumnIndex]; AllocInfo info = dataGridAllocs.Rows[e.RowIndex].Tag as AllocInfo; OpenSourceFile(info.symbol); } }
void AddAllocationPoint(MemBlock block, MemBlockTree tree) { int rootIndex = block.FindFirstValidSymbolIndex(); if (rootIndex < 0) { return; } ulong[] callStack = CallstackTab.GetCallStack(block.m_callStackCRC); for (int i = rootIndex; i < callStack.Length; ++i) { IStackTracer.Symbol symbol = MemTracerForm.ms_MainForm.StackTracer.GetSymbolForAddress(callStack[i]); if (symbol.functionName == null) { continue; } int rowIndex = FindRowIndexForCallerAddress(callStack[i]); if (rowIndex >= 0) { //AllocInfo allocInfo = dataGridAllocs.Rows[rowIndex].Tag as AllocInfo; //allocInfo.numBytes += (int)block.m_size; //++allocInfo.numBlocks; } else { //MemBlockTree.Node node = tree.Root.FindChildByCallAddress(callStack[i], true); List <MemBlockTree.Node> nodes = new List <MemBlockTree.Node>(); tree.Root.CollectChildrenByCallAddress(callStack[i], true, nodes); AllocInfo allocInfo = new AllocInfo(); allocInfo.symbol = symbol; allocInfo.address = callStack[i]; foreach (MemBlockTree.Node node in nodes) { allocInfo.numBytes += (int)node.GetAllocatedSize(); allocInfo.numBlocks += node.GetNumAllocatedBlocks(); } String[] rowData = { symbol.functionName, allocInfo.numBytes.ToString(), allocInfo.numBlocks.ToString(), "" }; dataGridAllocs.Rows.Add(rowData); //allocInfo.numBytes = (int)node.GetAllocatedSize(); //allocInfo.numBlocks = node.GetNumAllocatedBlocks(); dataGridAllocs.Rows[dataGridAllocs.Rows.Count - 1].Tag = allocInfo; } } }
private void dataGridAllocs_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e) { if (e.ColumnIndex >= 0 && e.RowIndex >= 0) { DataGridViewCell cell = dataGridAllocs.Rows[e.RowIndex].Cells[e.ColumnIndex]; AllocInfo info = dataGridAllocs.Rows[e.RowIndex].Tag as AllocInfo; if (info.symbol.functionName != null) { cell.ToolTipText = info.symbol.functionName + "@" + info.symbol.line; } else { cell.ToolTipText = ""; } } }
public static void CheckGuardBytes(IntPtr ptr, AllocInfo info) { for (int i = 0; i < 4; ++i) { if (Marshal.ReadInt32(ptr, i * 4) != 0x5facade7) { Console.WriteLine(info.lastUse); throw new Exception("MDL [Free]: memory of handle " + ptr + " was modified (at beginning)!"); } if (Marshal.ReadInt32(ptr, info.size.ToInt32() + 16 + i * 4) != 0x5facade7) { Console.WriteLine(info.lastUse); throw new Exception("MDL [Free]: memory of handle " + ptr + " was modified (at end)!"); } } }
private static int Compare(AllocInfo left, AllocInfo right) { int c; c = -left.count.CompareTo(right.count); if ((c == 0) && left.bytes.HasValue && right.bytes.HasValue) { c = -left.bytes.Value.CompareTo(right.bytes.Value); } if (c == 0) { c = String.Compare(left.typeName, right.typeName); } return(c); }
/// <summary> /// This was originally CALL_MMAP and is used to get more memory from /// the system. It's similar to CALL_MMAP, but can adjust the size to /// return more memory than requested (must be in units of page size). /// Returns null when out of memory or any kind of error. /// </summary> unsafe protected override void *CallMoreCore(ref ulong size) { mGrowSize = Math.Min(MaxGrowSize, Math.Max(mGrowSize, MIN_GRANULARITY / 2) * 2); size = Math.Max(size, mGrowSize); if (size > int.MaxValue) { throw new DlMallocException("Request for too much memory, size=" + size); } var array = new byte[size]; var handle = GCHandle.Alloc(array, GCHandleType.Pinned); var address = (void *)handle.AddrOfPinnedObject(); mAllocations[(ulong)address] = new AllocInfo() { Array = array, Length = (ulong)array.Length, Handle = handle }; return(address); }
public static void DbgOnFree(IntPtr ptr) { Monitor.Enter(lockable); if (handles.ContainsKey(ptr) == false) { Monitor.Exit(lockable); throw new Exception("MDL [Free]: handle " + ptr + " was never allocated!"); } AllocInfo oldinfo = handles[ptr]; if (oldinfo.allocated == false) { Console.WriteLine(oldinfo.lastUse); Monitor.Exit(lockable); throw new Exception("MDL [Free]: handle " + ptr + " was already freed!"); } handles[ptr] = new AllocInfo() { size = (IntPtr)(-1), lastUse = new StackTrace() }; Monitor.Exit(lockable); CheckGuardBytes(ptr, oldinfo); }