From 249fd5e56b60899b7ee2a7551f643307796247bc Mon Sep 17 00:00:00 2001 From: Andreas Rumpf Date: Thu, 24 Nov 2016 08:27:09 +0100 Subject: further memtracking improvements --- lib/pure/nimtracker.nim | 2 +- lib/system/alloc.nim | 6 ++++++ lib/system/gc.nim | 7 +++++++ lib/system/memtracker.nim | 20 ++++++++++++++------ lib/wrappers/sqlite3.nim | 2 +- 5 files changed, 29 insertions(+), 8 deletions(-) diff --git a/lib/pure/nimtracker.nim b/lib/pure/nimtracker.nim index db29b4252..52fa9da77 100644 --- a/lib/pure/nimtracker.nim +++ b/lib/pure/nimtracker.nim @@ -32,7 +32,7 @@ template sbind(x: int; value) = quit "could not bind value" when defined(memTracker): - proc logEntries(log: TrackLog) {.nimcall.} = + proc logEntries(log: TrackLog) {.nimcall, locks: 0, tags: [].} = for i in 0..log.count-1: var success = false let e = log.data[i] diff --git a/lib/system/alloc.nim b/lib/system/alloc.nim index 745bbbf62..3a8e8a1b6 100644 --- a/lib/system/alloc.nim +++ b/lib/system/alloc.nim @@ -15,6 +15,10 @@ include osalloc +template track(op, address, size) = + when defined(memTracker): + memTrackerOp(op, address, size) + # We manage *chunks* of memory. Each chunk is a multiple of the page size. # Each chunk starts at an address that is divisible by the page size. Chunks # that are bigger than ``ChunkOsReturn`` are returned back to the operating @@ -645,6 +649,7 @@ proc alloc(allocator: var MemRegion, size: Natural): pointer = cast[ptr FreeCell](result).zeroField = 1 # mark it as used sysAssert(not isAllocatedPtr(allocator, result), "alloc") result = cast[pointer](cast[ByteAddress](result) +% sizeof(FreeCell)) + track("alloc", result, size) proc alloc0(allocator: var MemRegion, size: Natural): pointer = result = alloc(allocator, size) @@ -658,6 +663,7 @@ proc dealloc(allocator: var MemRegion, p: pointer) = sysAssert(cast[ptr FreeCell](x).zeroField == 1, "dealloc 2") rawDealloc(allocator, x) sysAssert(not isAllocatedPtr(allocator, x), "dealloc 3") + track("dealloc", p, 0) proc realloc(allocator: var MemRegion, p: pointer, newsize: Natural): pointer = if newsize > 0: diff --git a/lib/system/gc.nim b/lib/system/gc.nim index 11897ce80..3bb0f62ff 100644 --- a/lib/system/gc.nim +++ b/lib/system/gc.nim @@ -468,6 +468,7 @@ proc rawNewObj(typ: PNimType, size: int, gch: var GcHeap): pointer = # its refcount is zero, so add it to the ZCT: addNewObjToZCT(res, gch) when logGC: writeCell("new cell", res) + track("rawNewObj", res, size) gcTrace(res, csAllocated) release(gch) when useCellIds: @@ -519,6 +520,7 @@ proc newObjRC1(typ: PNimType, size: int): pointer {.compilerRtl.} = res.refcount = rcIncrement # refcount is 1 sysAssert(isAllocatedPtr(gch.region, res), "newObj: 3") when logGC: writeCell("new cell", res) + track("newObjRC1", res, size) gcTrace(res, csAllocated) release(gch) when useCellIds: @@ -561,6 +563,8 @@ proc growObj(old: pointer, newsize: int, gch: var GcHeap): pointer = writeCell("growObj new cell", res) gcTrace(ol, csZctFreed) gcTrace(res, csAllocated) + track("growObj old", ol, 0) + track("growObj new", res, newsize) when reallyDealloc: sysAssert(allocInv(gch.region), "growObj before dealloc") if ol.refcount shr rcShift <=% 1: @@ -604,6 +608,7 @@ proc growObj(old: pointer, newsize: int): pointer {.rtl.} = proc freeCyclicCell(gch: var GcHeap, c: PCell) = prepareDealloc(c) gcTrace(c, csCycFreed) + track("cycle collector dealloc cell", c, 0) when logGC: writeCell("cycle collector dealloc cell", c) when reallyDealloc: sysAssert(allocInv(gch.region), "free cyclic cell") @@ -673,6 +678,7 @@ proc doOperation(p: pointer, op: WalkOp) = gcAssert(c.refcount >=% rcIncrement, "doOperation 2") #c.refcount = c.refcount -% rcIncrement when logGC: writeCell("decref (from doOperation)", c) + track("waZctDecref", p, 0) decRef(c) #if c.refcount <% rcIncrement: addZCT(gch.zct, c) of waPush: @@ -765,6 +771,7 @@ proc collectZCT(gch: var GcHeap): bool = # In any case, it should be removed from the ZCT. But not # freed. **KEEP THIS IN MIND WHEN MAKING THIS INCREMENTAL!** when logGC: writeCell("zct dealloc cell", c) + track("zct dealloc cell", c, 0) gcTrace(c, csZctFreed) # We are about to free the object, call the finalizer BEFORE its # children are deleted as well, because otherwise the finalizer may diff --git a/lib/system/memtracker.nim b/lib/system/memtracker.nim index b4a5460fa..a9767bbca 100644 --- a/lib/system/memtracker.nim +++ b/lib/system/memtracker.nim @@ -27,8 +27,9 @@ type line*: int TrackLog* = object count*: int + disabled: bool data*: array[4000, LogEntry] - TrackLogger* = proc (log: TrackLog) {.nimcall.} + TrackLogger* = proc (log: TrackLog) {.nimcall, tags: [], locks: 0.} var gLog*: TrackLog @@ -38,11 +39,12 @@ proc setTrackLogger*(logger: TrackLogger) = gLogger = logger proc addEntry(entry: LogEntry) = - if gLog.count > high(gLog.data): - gLogger(gLog) - gLog.count = 0 - gLog.data[gLog.count] = entry - inc gLog.count + if not gLog.disabled: + if gLog.count > high(gLog.data): + gLogger(gLog) + gLog.count = 0 + gLog.data[gLog.count] = entry + inc gLog.count proc memTrackerWrite(address: pointer; size: int; file: cstring; line: int) {.compilerProc.} = addEntry LogEntry(op: "write", address: address, @@ -52,6 +54,12 @@ proc memTrackerOp*(op: cstring; address: pointer; size: int) = addEntry LogEntry(op: op, address: address, size: size, file: "", line: 0) +proc memTrackerDisable*() = + gLog.disabled = true + +proc memTrackerEnable*() = + gLog.disabled = false + proc logPendingOps() {.noconv.} = # forward declared and called from Nim's signal handler. gLogger(gLog) diff --git a/lib/wrappers/sqlite3.nim b/lib/wrappers/sqlite3.nim index 4970a6155..d2b70df8d 100644 --- a/lib/wrappers/sqlite3.nim +++ b/lib/wrappers/sqlite3.nim @@ -110,7 +110,7 @@ type Callback* = proc (para1: pointer, para2: int32, para3, para4: cstringArray): int32{.cdecl.} - Tbind_destructor_func* = proc (para1: pointer){.cdecl.} + Tbind_destructor_func* = proc (para1: pointer){.cdecl, locks: 0, tags: [].} Create_function_step_func* = proc (para1: Pcontext, para2: int32, para3: PValueArg){.cdecl.} Create_function_func_func* = proc (para1: Pcontext, para2: int32, -- cgit 1.4.1-2-gfad0