Permalink
Browse files

skynet defined lua alloc

  • Loading branch information...
1 parent 331c800 commit 40281a8853a885428f3c2420ee6fc78718868d83 @cloudwu cloudwu committed Dec 19, 2013
Showing with 191 additions and 1 deletion.
  1. +1 −1 Makefile
  2. +161 −0 service-src/luaalloc.c
  3. +14 −0 service-src/luaalloc.h
  4. +15 −0 service-src/service_lua.c
View
@@ -71,7 +71,7 @@ service/harbor.so : service-src/service_harbor.c
service/logger.so : skynet-src/skynet_logger.c
gcc $(CFLAGS) $(SHARED) $^ -o $@ -Iskynet-src
-service/snlua.so : service-src/service_lua.c service-src/luacode_cache.c
+service/snlua.so : service-src/service_lua.c service-src/luacode_cache.c service-src/luaalloc.c
gcc $(CFLAGS) $(SHARED) -Iluacompat $^ -o $@ -Iskynet-src
service/gate.so : service-src/service_gate.c
View
@@ -0,0 +1,161 @@
+#include "luaalloc.h"
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define ALLOCCHUNK (16 * 1024 + sizeof(struct memchunk))
+
+struct freenode {
+ struct freenode * next;
+};
+
+struct memchunk {
+ struct memchunk * next;
+};
+
+struct skynet_lalloc {
+ // small memory list : 8,16,32,64,128,256,512
+ struct freenode * freelist[7];
+ struct memchunk * chunklist;
+ char * ptr;
+ char * end;
+};
+
+static void
+new_chunk(struct skynet_lalloc *lalloc) {
+ struct memchunk * mc = malloc(ALLOCCHUNK);
+ mc->next = lalloc->chunklist;
+ lalloc->ptr = (char *)(mc+1);
+ lalloc->end = ((char *)mc) + ALLOCCHUNK;
+ lalloc->chunklist = mc;
+}
+
+inline static int
+size_index(size_t sz) {
+ if (sz > 32) {
+ if (sz > 128) {
+ if (sz > 256)
+ return 6;
+ else
+ return 5;
+ } else {
+ if (sz > 64)
+ return 4;
+ else
+ return 3;
+ }
+ } else {
+ if (sz > 16)
+ return 2;
+ else if (sz > 8)
+ return 1;
+ else
+ return 0;
+ }
+}
+
+#define REALSIZE(idx) (1<<((idx)+3))
+
+static void *
+new_small_block(struct skynet_lalloc *lalloc, int idx) {
+ struct freenode * fn = lalloc->freelist[idx];
+ if (fn) {
+ lalloc->freelist[idx] = fn->next;
+ return fn;
+ } else {
+ int rsz = REALSIZE(idx);
+ if ((lalloc->end - lalloc->ptr) < rsz) {
+ new_chunk(lalloc);
+ }
+ void * ret = lalloc->ptr;
+ lalloc->ptr += rsz;
+ return ret;
+ }
+}
+
+static void
+delete_small_block(struct skynet_lalloc *lalloc, void * ptr, int idx) {
+ struct freenode * fn = lalloc->freelist[idx];
+ struct freenode * node = (struct freenode *)ptr;
+ node->next = fn;
+ lalloc->freelist[idx] = node;
+}
+
+static void *
+extend_small_block(struct skynet_lalloc *lalloc, void * ptr, size_t osize, size_t nsize) {
+ int oidx = size_index(osize);
+ int nidx = size_index(nsize);
+ if (oidx == nidx) {
+ return ptr;
+ }
+ void * ret = new_small_block(lalloc,nidx);
+ memcpy(ret, ptr, osize < nsize ? osize : nsize);
+ delete_small_block(lalloc, ptr, oidx);
+ return ret;
+}
+
+void *
+skynet_lua_alloc(void *ud, void *ptr, size_t osize, size_t nsize) {
+ struct skynet_lalloc *lalloc = ud;
+ if (ptr == NULL) {
+ if (nsize > 512) {
+ return malloc(nsize);
+ }
+ int idx = size_index(nsize);
+ return new_small_block(lalloc, idx);
+ } else if (nsize == 0) {
+ if (osize > 512) {
+ free(ptr);
+ return NULL;
+ }
+ int idx = size_index(osize);
+ delete_small_block(lalloc, ptr, idx);
+ return NULL;
+ } else {
+ if (osize > 512) {
+ if (nsize > 512) {
+ return realloc(ptr, nsize);
+ } else {
+ int idx = size_index(nsize);
+ void * ret = new_small_block(lalloc, idx);
+ memcpy(ret, ptr, nsize);
+ free(ptr);
+ return ret;
+ }
+ }
+ if (nsize > 512) {
+ void * buffer = malloc(nsize);
+ memcpy(buffer, ptr, osize);
+ int idx = size_index(osize);
+ delete_small_block(lalloc, ptr, idx);
+ return buffer;
+ } else {
+ return extend_small_block(lalloc, ptr, osize, nsize);
+ }
+ }
+}
+
+struct skynet_lalloc *
+skynet_lalloc_new(size_t prealloc) {
+ assert(prealloc > sizeof(struct skynet_lalloc));
+ struct skynet_lalloc * lalloc = malloc(prealloc);
+ int i;
+ for (i=0;i<sizeof(lalloc->freelist)/sizeof(lalloc->freelist[0]);i++) {
+ lalloc->freelist[i] = NULL;
+ }
+ lalloc->chunklist = NULL;
+ lalloc->ptr = (char *)(lalloc+1);
+ lalloc->end = ((char *)lalloc) + prealloc;
+ return lalloc;
+}
+
+void
+skynet_lalloc_delete(struct skynet_lalloc *lalloc) {
+ struct memchunk * mc = lalloc->chunklist;
+ while(mc) {
+ struct memchunk * tmp = mc;
+ mc = mc->next;
+ free(tmp);
+ }
+ free(lalloc);
+}
@@ -0,0 +1,14 @@
+#ifndef skynet_lua_alloc_h
+#define skynet_lua_alloc_h
+
+#include <lua.h>
+#include <stddef.h>
+
+struct skynet_lalloc;
+
+struct skynet_lalloc * skynet_lalloc_new(size_t prealloc);
+void skynet_lalloc_delete(struct skynet_lalloc *);
+
+void * skynet_lua_alloc(void *ud, void *ptr, size_t osize, size_t nsize);
+
+#endif
@@ -7,12 +7,15 @@
#include "luacompat52.h"
#include "service_lua.h"
#include "luacode_cache.h"
+#include "luaalloc.h"
#include <assert.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
+#define PREALLOCMEM (1024 * 1024)
+
// time
#include <time.h>
@@ -245,13 +248,25 @@ struct snlua *
snlua_create(void) {
struct snlua * l = malloc(sizeof(*l));
memset(l,0,sizeof(*l));
+#ifdef PREALLOCMEM
+ l->L = lua_newstate(skynet_lua_alloc, skynet_lalloc_new(PREALLOCMEM));
+#else
l->L = luaL_newstate();
+#endif
l->init = _init;
return l;
}
void
snlua_release(struct snlua *l) {
+ void * ud = NULL;
+#ifdef PREALLOCMEM
+ lua_Alloc lalloc = lua_getallocf(l->L, &ud);
+ assert(lalloc == skynet_lua_alloc);
lua_close(l->L);
+ skynet_lalloc_delete(ud);
+#else
+ lua_close(l->L);
+#endif
free(l);
}

0 comments on commit 40281a8

Please sign in to comment.