memory tracker is aware of threads (still not threadsafe though)
This commit is contained in:
parent
5421ec8dae
commit
303c49b9f3
2 changed files with 45 additions and 12 deletions
|
|
@ -19,7 +19,15 @@ import sqlite3
|
||||||
|
|
||||||
var
|
var
|
||||||
dbHandle: PSqlite3
|
dbHandle: PSqlite3
|
||||||
insertStmt: Pstmt
|
insertStmt {.threadvar.}: Pstmt
|
||||||
|
|
||||||
|
const insertQuery = "INSERT INTO tracking(op, address, size, file, line) values (?, ?, ?, ?, ?)"
|
||||||
|
|
||||||
|
when compileOption("threads"):
|
||||||
|
onThreadCreation do():
|
||||||
|
if prepare_v2(dbHandle, insertQuery,
|
||||||
|
insertQuery.len, insertStmt, nil) != SQLITE_OK:
|
||||||
|
quit "could not bind query to insertStmt " & $sqlite3.errmsg(dbHandle)
|
||||||
|
|
||||||
template sbind(x: int; value) =
|
template sbind(x: int; value) =
|
||||||
when value is cstring:
|
when value is cstring:
|
||||||
|
|
@ -32,7 +40,7 @@ template sbind(x: int; value) =
|
||||||
quit "could not bind value"
|
quit "could not bind value"
|
||||||
|
|
||||||
when defined(memTracker):
|
when defined(memTracker):
|
||||||
proc logEntries(log: TrackLog) {.nimcall, locks: 0, tags: [].} =
|
proc logEntries(log: TrackLog) {.nimcall, locks: 0, tags: [], gcsafe.} =
|
||||||
for i in 0..log.count-1:
|
for i in 0..log.count-1:
|
||||||
var success = false
|
var success = false
|
||||||
let e = log.data[i]
|
let e = log.data[i]
|
||||||
|
|
@ -46,7 +54,7 @@ when defined(memTracker):
|
||||||
if step(insertStmt) == SQLITE_DONE:
|
if step(insertStmt) == SQLITE_DONE:
|
||||||
success = true
|
success = true
|
||||||
if not success:
|
if not success:
|
||||||
quit "could not write to database!"
|
quit "could not write to database! " & $sqlite3.errmsg(dbHandle)
|
||||||
|
|
||||||
proc execQuery(q: string) =
|
proc execQuery(q: string) =
|
||||||
var s: Pstmt
|
var s: Pstmt
|
||||||
|
|
@ -71,10 +79,12 @@ proc setupDb() =
|
||||||
if sqlite3.open("memtrack.db", dbHandle) == SQLITE_OK:
|
if sqlite3.open("memtrack.db", dbHandle) == SQLITE_OK:
|
||||||
setupDb()
|
setupDb()
|
||||||
const query = "INSERT INTO tracking(op, address, size, file, line) values (?, ?, ?, ?, ?)"
|
const query = "INSERT INTO tracking(op, address, size, file, line) values (?, ?, ?, ?, ?)"
|
||||||
if prepare_v2(dbHandle, query,
|
if prepare_v2(dbHandle, insertQuery,
|
||||||
query.len, insertStmt, nil) == SQLITE_OK:
|
insertQuery.len, insertStmt, nil) == SQLITE_OK:
|
||||||
when defined(memTracker):
|
when defined(memTracker):
|
||||||
setTrackLogger logEntries
|
setTrackLogger logEntries
|
||||||
else:
|
else:
|
||||||
quit "could not prepare statement B " & $sqlite3.errmsg(dbHandle)
|
quit "could not prepare statement B " & $sqlite3.errmsg(dbHandle)
|
||||||
|
else:
|
||||||
|
quit "could not setup sqlite " & $sqlite3.errmsg(dbHandle)
|
||||||
{.pop.}
|
{.pop.}
|
||||||
|
|
|
||||||
|
|
@ -28,18 +28,41 @@ type
|
||||||
TrackLog* = object
|
TrackLog* = object
|
||||||
count*: int
|
count*: int
|
||||||
disabled: bool
|
disabled: bool
|
||||||
data*: array[4000, LogEntry]
|
data*: array[400, LogEntry]
|
||||||
TrackLogger* = proc (log: TrackLog) {.nimcall, tags: [], locks: 0.}
|
TrackLogger* = proc (log: TrackLog) {.nimcall, tags: [], locks: 0, gcsafe.}
|
||||||
|
|
||||||
var
|
var
|
||||||
gLog*: TrackLog
|
gLog*: TrackLog
|
||||||
gLogger*: TrackLogger = proc (log: TrackLog) = discard
|
gLogger*: TrackLogger = proc (log: TrackLog) = discard
|
||||||
|
ilocs: array[4000, (int, int)]
|
||||||
|
ilocn: int
|
||||||
|
|
||||||
|
proc trackLocation*(p: pointer; size: int) =
|
||||||
|
let x = (cast[int](p), size)
|
||||||
|
for i in 0..ilocn-1:
|
||||||
|
# already known?
|
||||||
|
if ilocs[i] == x: return
|
||||||
|
ilocs[ilocn] = x
|
||||||
|
inc ilocn
|
||||||
|
|
||||||
proc setTrackLogger*(logger: TrackLogger) =
|
proc setTrackLogger*(logger: TrackLogger) =
|
||||||
gLogger = logger
|
gLogger = logger
|
||||||
|
|
||||||
proc addEntry(entry: LogEntry) =
|
proc addEntry(entry: LogEntry) =
|
||||||
if not gLog.disabled:
|
if not gLog.disabled:
|
||||||
|
var interesting = false
|
||||||
|
for i in 0..ilocn-1:
|
||||||
|
let p = ilocs[i]
|
||||||
|
# X..Y and C..D overlap iff (X <= D and C <= Y)
|
||||||
|
let x = p[0]
|
||||||
|
let y = p[0]+p[1]-1
|
||||||
|
let c = cast[int](entry.address)
|
||||||
|
let d = c + entry.size-1
|
||||||
|
if x <= d and c <= y:
|
||||||
|
interesting = true
|
||||||
|
break
|
||||||
|
if interesting:
|
||||||
|
cprintf("interesting %s:%ld\n", entry.file, entry.line)
|
||||||
if gLog.count > high(gLog.data):
|
if gLog.count > high(gLog.data):
|
||||||
gLogger(gLog)
|
gLogger(gLog)
|
||||||
gLog.count = 0
|
gLog.count = 0
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue