better memory tracking

This commit is contained in:
Andreas Rumpf 2016-11-22 08:24:39 +01:00
commit 439f43fc52
2 changed files with 64 additions and 55 deletions

View file

@ -9,63 +9,70 @@
## Memory tracking support for Nim. ## Memory tracking support for Nim.
when isMainModule: when not defined(memTracker):
import db_sqlite {.error: "Memory tracking support is turned off!".}
var db = open("memtrack.db", "", "", "")
db.exec sql"""
create table if not exists Tracking(
id integer primary key,
op varchar not null,
address integer not null,
size integer not null,
file varchar not null,
line integer not null
)"""
db.close()
else:
when not defined(memTracker):
{.error: "Memory tracking support is turned off!".}
{.push memtracker: off.} {.push memtracker: off.}
# we import the low level wrapper and are careful not to use Nim's # we import the low level wrapper and are careful not to use Nim's
# memory manager for anything here. # memory manager for anything here.
import sqlite3 import sqlite3
var var
dbHandle: PSqlite3 dbHandle: PSqlite3
insertStmt: Pstmt insertStmt: Pstmt
template sbind(x: int; value) = template sbind(x: int; value) =
when value is cstring: when value is cstring:
let ret = insertStmt.bindText(x, value, value.len.int32, SQLITE_TRANSIENT) let ret = insertStmt.bindText(x, value, value.len.int32, SQLITE_TRANSIENT)
if ret != SQLITE_OK: if ret != SQLITE_OK:
quit "could not bind value" quit "could not bind value"
else: else:
let ret = insertStmt.bindInt64(x, value) let ret = insertStmt.bindInt64(x, value)
if ret != SQLITE_OK: if ret != SQLITE_OK:
quit "could not bind value" quit "could not bind value"
proc logEntries(log: TrackLog) {.nimcall.} = proc logEntries(log: TrackLog) {.nimcall.} =
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]
discard sqlite3.reset(insertStmt) discard sqlite3.reset(insertStmt)
discard clearBindings(insertStmt) discard clearBindings(insertStmt)
sbind 1, e.op sbind 1, e.op
sbind(2, cast[int](e.address)) sbind(2, cast[int](e.address))
sbind 3, e.size sbind 3, e.size
sbind 4, e.file sbind 4, e.file
sbind 5, e.line sbind 5, e.line
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!"
if sqlite3.open("memtrack.db", dbHandle) == SQLITE_OK: proc execQuery(q: string) =
const query = "INSERT INTO tracking(op, address, size, file, line) values (?, ?, ?, ?, ?)" var s: Pstmt
if prepare_v2(dbHandle, query, if prepare_v2(dbHandle, q, q.len.int32, s, nil) == SQLITE_OK:
query.len, insertStmt, nil) == SQLITE_OK: discard step(s)
setTrackLogger logEntries if finalize(s) != SQLITE_OK:
else: quit "could not finalize " & $sqlite3.errmsg(dbHandle)
quit "could not prepare statement" else:
{.pop.} quit "could not prepare statement " & $sqlite3.errmsg(dbHandle)
proc setupDb() =
execQuery """create table if not exists tracking(
id integer primary key,
op varchar not null,
address integer not null,
size integer not null,
file varchar not null,
line integer not null
)"""
execQuery "delete from tracking"
if sqlite3.open("memtrack.db", dbHandle) == SQLITE_OK:
setupDb()
const query = "INSERT INTO tracking(op, address, size, file, line) values (?, ?, ?, ?, ?)"
if prepare_v2(dbHandle, query,
query.len, insertStmt, nil) == SQLITE_OK:
setTrackLogger logEntries
else:
quit "could not prepare statement B " & $sqlite3.errmsg(dbHandle)
{.pop.}

View file

@ -1309,10 +1309,12 @@ proc join*[T: not string](a: openArray[T], sep: string = ""): string {.
type type
SkipTable = array[char, int] SkipTable = array[char, int]
{.push profiler: off.}
proc preprocessSub(sub: string, a: var SkipTable) = proc preprocessSub(sub: string, a: var SkipTable) =
var m = len(sub) var m = len(sub)
for i in 0..0xff: a[chr(i)] = m+1 for i in 0..0xff: a[chr(i)] = m+1
for i in 0..m-1: a[sub[i]] = m-i for i in 0..m-1: a[sub[i]] = m-i
{.pop.}
proc findAux(s, sub: string, start: int, a: SkipTable): int = proc findAux(s, sub: string, start: int, a: SkipTable): int =
# Fast "quick search" algorithm: # Fast "quick search" algorithm: