Re: The removal of function environments: An opportunity for optimization?
[
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: 2010年5月24日 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;
}