]> Cypherpunks repositories - gostls13.git/commitdiff
malloc fixes.
authorRuss Cox <rsc@golang.org>
Fri, 5 Dec 2008 05:04:26 +0000 (21:04 -0800)
committerRuss Cox <rsc@golang.org>
Fri, 5 Dec 2008 05:04:26 +0000 (21:04 -0800)
can run peano 10 in 100 MB (instead of 1+ GB) of memory
when linking against this.
can run peano 11 in 1 GB of memory now.

R=r
DELTA=100  (44 added, 44 deleted, 12 changed)
OCL=20504
CL=20553

usr/rsc/mem/Makefile
usr/rsc/mem/allocator.go
usr/rsc/mem/malloc.c
usr/rsc/mem/malloc.h
usr/rsc/mem/stack.c [new file with mode: 0644]
usr/rsc/mem/triv.c

index 8f2eace2483c7eb9f2f1f43dee8ac48aa12a6f16..0bfb89b512b6e69c2477e33fe84980cbbaf82b77 100644 (file)
@@ -31,3 +31,7 @@ test%: test%.$O $(OFILES)
 
 clean:
        rm -f *.$O $(TARG)
+
+runtime: allocator.$O malloc.$O pagemap.$O triv.$O stack.$O
+       6ar grc $(GOROOT)/lib/lib_$(GOARCH)_$(GOOS).a $^
+
index da624fcd5c5a1503b2115c16be3d37d88ea0e17f..a0d95e77c815a1e9972eebe8981f06a8ffa37e1f 100644 (file)
@@ -10,3 +10,4 @@ export func memset(*byte, int, int)
 export var footprint int64
 export var frozen bool
 export func testsizetoclass()
+export var allocated int64
index f5461cddf7126bdec92b6abee6086f6f3daee919..02fe40bd3dd870005f3a9dc477767d0d7f136a33 100644 (file)
@@ -107,13 +107,7 @@ allocspan(int32 npage)
                if(s->length >= npage) {
                        *l = s->next;
                        s->next = nil;
-if(s->length > npage) {
-prints("Chop span");
-sys·printint(s->length);
-prints(" for ");
-sys·printint(npage);
-prints("\n");
-}
+//if(s->length > npage) printf("Chop span %D for %d\n", s->length, npage);
                        goto havespan;
                }
        }
@@ -125,11 +119,7 @@ prints("\n");
        if(allocnpage < (1<<20>>PageShift))     // TODO: Tune
                allocnpage = (1<<20>>PageShift);
        s->length = allocnpage;
-prints("New span ");
-sys·printint(allocnpage);
-prints(" for ");
-sys·printint(npage);
-prints("\n");
+//printf("New span %d for %d\n", allocnpage, npage);
        s->base = trivalloc(allocnpage<<PageShift);
        insertspan(s);
 
@@ -237,21 +227,13 @@ allocator·testsizetoclass(void)
        for(i=0; i<nelem(classtosize); i++) {
                for(; n <= classtosize[i]; n++) {
                        if(sizetoclass(n) != i) {
-                               prints("sizetoclass ");
-                               sys·printint(n);
-                               prints(" = ");
-                               sys·printint(sizetoclass(n));
-                               prints(" want ");
-                               sys·printint(i);
-                               prints("\n");
+                               printf("sizetoclass %d = %d want %d\n", n, sizetoclass(n), i);
                                throw("testsizetoclass");
                        }
                }
        }
        if (n != 32768+1) {
-               prints("testsizetoclass stopped at ");
-               sys·printint(n);
-               prints("\n");
+               printf("testsizetoclass stopped at %d\n", n);
                throw("testsizetoclass");
        }
 }
@@ -274,20 +256,19 @@ centralgrab(int32 cl, int32 *pn)
        }
        chunk = (chunk+PageMask) & ~PageMask;
        s = allocspan(chunk>>PageShift);
-prints("New Class ");
-sys·printint(cl);
-prints("\n");
+//printf("New class %d\n", cl);
        s->state = SpanInUse;
        s->cl = cl;
        siz = classtosize[cl];
        n = chunk/siz;
        p = s->base;
+//printf("centralgrab cl=%d siz=%d n=%d\n", cl, siz, n);
        for(i=0; i<n-1; i++) {
                *(void**)p = p+siz;
                p += siz;
        }
        *pn = n;
-       return p;
+       return s->base;
 }
 
 // Allocate a small object of size class cl.
@@ -305,11 +286,13 @@ allocsmall(int32 cl)
        if(p == nil) {
                // otherwise grab some blocks from central cache.
                lock(&central);
+//printf("centralgrab for %d\n", cl);
                p = centralgrab(cl, &n);
                // TODO: update local counters using n
                unlock(&central);
        }
 
+//printf("alloc from cl %d\n", cl);
        // advance linked list.
        m->freelist[cl] = *p;
 
@@ -327,9 +310,7 @@ alloclarge(int32 np)
        Span *s;
 
        lock(&central);
-//prints("Alloc span ");
-//sys·printint(np);
-//prints("\n");
+//printf("Alloc span %d\n", np);
        s = allocspan(np);
        unlock(&central);
        s->state = SpanInUse;
@@ -346,17 +327,16 @@ alloc(int32 n)
        if(n < LargeSize) {
                cl = sizetoclass(n);
                if(cl < 0 || cl >= SmallFreeClasses) {
-                       sys·printint(n);
-                       prints(" -> ");
-                       sys·printint(cl);
-                       prints("\n");
+                       printf("%d -> %d\n", n, cl);
                        throw("alloc - logic error");
                }
-               return allocsmall(sizetoclass(n));
+               allocator·allocated += classtosize[cl];
+               return allocsmall(cl);
        }
 
        // count number of pages; careful about overflow for big n.
        np = (n>>PageShift) + (((n&PageMask)+PageMask)>>PageShift);
+       allocator·allocated += (uint64)np<<PageShift;
        return alloclarge(np);
 }
 
@@ -386,9 +366,8 @@ free(void *v)
                // TODO: For large spans, maybe just return the
                // memory to the operating system and let it zero it.
                sys·memclr(s->base, s->length << PageShift);
-//prints("Free big ");
-//sys·printint(s->length);
-//prints("\n");
+//printf("Free big %D\n", s->length);
+               allocator·allocated -= s->length << PageShift;
                lock(&central);
                freespan(s);
                unlock(&central);
@@ -403,9 +382,11 @@ free(void *v)
 
        // Zero and add to free list.
        sys·memclr(v, siz);
+       allocator·allocated -= siz;
        p = v;
        *p = m->freelist[s->cl];
        m->freelist[s->cl] = p;
+//printf("Free siz %d cl %d\n", siz, s->cl);
 }
 
 void
@@ -423,21 +404,3 @@ allocator·memset(byte *v, int32 c, int32 n)
                v[i] = c;
 }
 
-// Allocate stack segment.
-// Must be done without holding locks, because
-// calling any function might trigger another stack segment allocation.
-void*
-allocstack(int32 n)
-{
-       // TODO
-       USED(n);
-       return nil;
-}
-
-void
-freestack(void *v)
-{
-       // TODO
-       USED(v);
-}
-
index aa3bed2c6b36f9c4373cc08ce2ec7a10ac91e0f4..dd51e49b24d253930f25313a072b1598dc57f923 100644 (file)
@@ -24,9 +24,13 @@ struct PageMap
        void *level0[PMLevelSize];
 };
 
+extern int64 allocator·allocated;
 extern int64 allocator·footprint;
 extern bool allocator·frozen;
 
 void* trivalloc(int32);
 void* pmlookup(PageMap*, uintptr);
 void* pminsert(PageMap*, uintptr, void*);
+
+void*  alloc(int32);
+void   free(void*);
diff --git a/usr/rsc/mem/stack.c b/usr/rsc/mem/stack.c
new file mode 100644 (file)
index 0000000..295e709
--- /dev/null
@@ -0,0 +1,22 @@
+// Copyright 2009 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "malloc.h"
+
+void*
+stackalloc(uint32 n)
+{
+       void *v;
+
+       v = alloc(n);
+//printf("stackalloc %d = %p\n", n, v);
+       return v;
+}
+
+void
+stackfree(void *v)
+{
+//printf("stackfree %p\n", v);
+       free(v);
+}
index 631e93a09405b5576f7a5feb52413d81a8b16816..935cb9fc081794afcc212d6827bd2d49f7484aa4 100644 (file)
@@ -36,6 +36,7 @@ trivalloc(int32 size)
        static byte *p;
        static int32 n;
        byte *v;
+       uint64 oldfoot;
 
        if(allocator·frozen)
                throw("allocator frozen");
@@ -44,6 +45,7 @@ trivalloc(int32 size)
 //sys·printint(size);
 //prints("\n");
 
+       oldfoot = allocator·footprint;
        if(size < 4096) {       // TODO: Tune constant.
                size = (size + Round) & ~Round;
                if(size > n) {
@@ -53,12 +55,20 @@ trivalloc(int32 size)
                }
                v = p;
                p += size;
-               return v;
+               goto out;
        }
        if(size & PageMask)
                size += (1<<PageShift) - (size & PageMask);
        v = sys·mmap(nil, size, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, 0, 0);
        allocator·footprint += size;
+
+out:
+       if((oldfoot>>24) != (allocator·footprint>>24))
+               printf("memory footprint = %D MB for %D MB\n", allocator·footprint>>20, allocator·allocated>>20);
+       if(allocator·footprint >= 2LL<<30) {
+               prints("out of memory\n");
+               sys·exit(1);
+       }
        return v;
 }