[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: The removal of function environments: An opportunity for optimization?
- From: Mike Pall <mikelu-1005@...>
- Date: Mon, 24 May 2010 20:45:04 +0200
Roberto Ierusalimschy wrote:
> The bigest problem with this idea seems to be the "identification" of
> different functions into one. This seems rare, but may cause quite hard
> bugs. (Imagine the emulation of the old setfenv, using 'upvaluejoin',
> over such clones...)
I made an experimental patch for Lua 5.1 (since the idea works
there, too). And the setfenv() cases are exactly where it fails
the tests (it passes all other tests).
There is a significant speedup for the obvious test cases. E.g.
comparing a 100% cache miss vs. a 100% cache hit:
$ time lua-clc -e "local k; for i=1,1e7 do local function x() return i end end"
2.230
$ time lua-clc -e "local k; for i=1,1e7 do local function x() return k end end"
0.200
But ... I don't see any kind of speedup in real-world use cases.
Maybe that's because I carefully avoid creating closures in inner
loops. Anyway, I've attached the patch so others can play with it.
--Mike
--- lua-5.1.4/src/lobject.h 2008-08-06 15:29:48 +0200
+++ lua-5.1.4-clcache/src/lobject.h 2010-05-24 20:15:00 +0200
@@ -228,10 +228,12 @@
/*
** Function Prototypes
*/
+union Closure;
typedef struct Proto {
CommonHeader;
TValue *k; /* constants used by the function */
Instruction *code;
+ union Closure *clcache;
struct Proto **p; /* functions defined inside the function */
int *lineinfo; /* map from opcodes to source lines */
struct LocVar *locvars; /* information about local variables */
--- lua-5.1.4/src/lgc.c 2007-12-27 14:02:25 +0100
+++ lua-5.1.4-clcache/src/lgc.c 2010-05-24 20:15:00 +0200
@@ -202,6 +202,7 @@
*/
static void traverseproto (global_State *g, Proto *f) {
int i;
+ if (f->clcache && iswhite(obj2gco(f->clcache))) f->clcache = NULL;
if (f->source) stringmark(f->source);
for (i=0; i<f->sizek; i++) /* mark literals */
markvalue(g, &f->k[i]);
--- lua-5.1.4/src/lfunc.c 2007-12-28 15:58:43 +0100
+++ lua-5.1.4-clcache/src/lfunc.c 2010-05-24 20:15:00 +0200
@@ -123,6 +123,7 @@
f->sizecode = 0;
f->sizelineinfo = 0;
f->sizeupvalues = 0;
+ f->clcache = NULL;
f->nups = 0;
f->upvalues = NULL;
f->numparams = 0;
--- lua-5.1.4/src/lvm.c 2007-12-28 16:32:23 +0100
+++ lua-5.1.4-clcache/src/lvm.c 2010-05-24 20:15:00 +0200
@@ -722,6 +722,22 @@
int nup, j;
p = cl->p->p[GETARG_Bx(i)];
nup = p->nups;
+ if (p->clcache) {
+ UpVal **uv = p->clcache->l.upvals;
+ for (j=0; j<nup; j++) {
+ if (GET_OPCODE(pc[j]) == OP_GETUPVAL) {
+ if (uv[j] != cl->upvals[GETARG_B(pc[j])])
+ goto newcl;
+ } else {
+ lua_assert(GET_OPCODE(pc[j]) == OP_MOVE);
+ if (uv[j]->v != base + GETARG_B(pc[j]))
+ goto newcl;
+ }
+ }
+ setclvalue(L, ra, p->clcache);
+ continue;
+ }
+ newcl:
ncl = luaF_newLclosure(L, nup, cl->env);
ncl->l.p = p;
for (j=0; j<nup; j++, pc++) {
@@ -733,6 +749,8 @@
}
}
setclvalue(L, ra, ncl);
+ p->clcache = ncl;
+ if (isblack(obj2gco(p))) luaC_barrierf(L, obj2gco(p), obj2gco(ncl));
Protect(luaC_checkGC(L));
continue;
}