summary refs log tree commit diff stats
path: root/lib/system
diff options
context:
space:
mode:
authorAndreas Rumpf <rumpf_a@web.de>2019-01-19 12:46:49 +0100
committerAndreas Rumpf <rumpf_a@web.de>2019-01-19 12:48:39 +0100
commitf7c0360aba4e8ac2857adb85ff838d94cf30ff53 (patch)
treea14077770c2353680f3cdcaae335f68c2bfd7f6f /lib/system
parent86a91c1a4a38a669e9ed5409975936f64ad3e532 (diff)
downloadNim-f7c0360aba4e8ac2857adb85ff838d94cf30ff53.tar.gz
allocators: introduce --define:nimMinHeapPages for tuning mmap calls (omg they are slow on OSX...)
Diffstat (limited to 'lib/system')
-rw-r--r--lib/system/alloc.nim6
-rw-r--r--lib/system/gc_regions.nim29
2 files changed, 29 insertions, 6 deletions
diff --git a/lib/system/alloc.nim b/lib/system/alloc.nim
index b090117a9..e938dc475 100644
--- a/lib/system/alloc.nim
+++ b/lib/system/alloc.nim
@@ -20,7 +20,7 @@ template track(op, address, size) =
 # Each chunk starts at an address that is divisible by the page size.
 
 const
-  InitialMemoryRequest = 128 * PageSize # 0.5 MB
+  nimMinHeapPages {.intdefine.} = 128 # 0.5 MB
   SmallChunkSize = PageSize
   MaxFli = 30
   MaxLog2Sli = 5 # 32, this cannot be increased without changing 'uint32'
@@ -588,8 +588,8 @@ proc getBigChunk(a: var MemRegion, size: int): PBigChunk =
   sysAssert((size and PageMask) == 0, "getBigChunk: unaligned chunk")
   result = findSuitableBlock(a, fl, sl)
   if result == nil:
-    if size < InitialMemoryRequest:
-      result = requestOsChunks(a, InitialMemoryRequest)
+    if size < nimMinHeapPages * PageSize:
+      result = requestOsChunks(a, nimMinHeapPages * PageSize)
       splitChunk(a, result, size)
     else:
       result = requestOsChunks(a, size)
diff --git a/lib/system/gc_regions.nim b/lib/system/gc_regions.nim
index 8a1446944..3b908fb08 100644
--- a/lib/system/gc_regions.nim
+++ b/lib/system/gc_regions.nim
@@ -23,6 +23,21 @@ when defined(nimphpext):
   proc osDeallocPages(p: pointer, size: int) {.inline.} =
     efree(p)
 
+elif defined(useMalloc):
+  proc roundup(x, v: int): int {.inline.} =
+    result = (x + (v-1)) and not (v-1)
+  proc emalloc(size: int): pointer {.importc: "malloc", header: "<stdlib.h>".}
+  proc efree(mem: pointer) {.importc: "free", header: "<stdlib.h>".}
+
+  proc osAllocPages(size: int): pointer {.inline.} =
+    emalloc(size)
+
+  proc osTryAllocPages(size: int): pointer {.inline.} =
+    emalloc(size)
+
+  proc osDeallocPages(p: pointer, size: int) {.inline.} =
+    efree(p)
+
 else:
   include osalloc
 
@@ -108,6 +123,8 @@ template `+!`(p: pointer, s: int): pointer =
 template `-!`(p: pointer, s: int): pointer =
   cast[pointer](cast[int](p) -% s)
 
+const nimMinHeapPages {.intdefine.} = 4
+
 proc allocSlowPath(r: var MemRegion; size: int) =
   # we need to ensure that the underlying linked list
   # stays small. Say we want to grab 16GB of RAM with some
@@ -116,9 +133,8 @@ proc allocSlowPath(r: var MemRegion; size: int) =
   # 8MB, 16MB, 32MB, 64MB, 128MB, 512MB, 1GB, 2GB, 4GB, 8GB,
   # 16GB --> list contains only 20 elements! That's reasonable.
   if (r.totalSize and 1) == 0:
-    r.nextChunkSize =
-      if r.totalSize < 64 * 1024: PageSize*4
-      else: r.nextChunkSize*2
+    r.nextChunkSize = if r.totalSize < 64 * 1024: PageSize*nimMinHeapPages
+                      else: r.nextChunkSize*2
   var s = roundup(size+sizeof(BaseChunk), PageSize)
   var fresh: Chunk
   if s > r.nextChunkSize:
@@ -242,6 +258,13 @@ proc deallocAll*() = tlRegion.deallocAll()
 proc deallocOsPages(r: var MemRegion) = r.deallocAll()
 
 template withScratchRegion*(body: untyped) =
+  let obs = obstackPtr()
+  try:
+    body
+  finally:
+    setObstackPtr(obs)
+
+when false:
   var scratch: MemRegion
   let oldRegion = tlRegion
   tlRegion = scratch