execatidle() is called when there is nothing to do. it runs the
garbage collector, which walks all memory. that can be cpu-intensive.
it shows especially when moving the mouse over a inferno window:
the garbage collector is run after each mouse event.
this diff only runs the gc at execatidle() when the last idle gc
run was 10 seconds ago, or immediately when the memory allocation
has changed (up or down) by at least "heapmem->chunk/8" (512k/8=64k
at the moment).
this should be done for os/port/ too probably.
http://code.google.com/p/inferno-npe/source/detail?r=167f86761e
Modified:
/emu/port/alloc.c
/emu/port/dis.c
=======================================
--- /emu/port/alloc.c Fri Dec 22 09:07:39 2006
+++ /emu/port/alloc.c Fri Jan 29 04:39:08 2010
@@ -90,6 +90,18 @@
#define CKLEAK 0
int ckleak;
#define ML(v, sz, pc) if(CKLEAK && ckleak && v){ if(sz)
fprint(2, "%lux %lux %lux\n", (ulong)v, (ulong)sz, (ulong)pc); else
fprint(2, "%lux\n", (ulong)v); }
+
+int
+heapneedgc(ulong osize)
+{
+ return heapmem->cursize-osize > heapmem->chunk/8;
+}
+
+ulong
+heapcursize(void)
+{
+ return heapmem->cursize;
+}
int
memusehigh(void)
=======================================
--- /emu/port/dis.c Thu Jan 14 06:36:32 2010
+++ /emu/port/dis.c Fri Jan 29 04:39:08 2010
@@ -83,13 +83,18 @@
n++;
return n;
}
+
+extern ulong heapcursize(void);
+extern int heapneedgc(ulong v);
+static ulong prevheapsize;
+static vlong prevgcpass;
static void
execatidle(void)
{
int done;
- if(tready(nil))
+ if(tready(nil) || !heapneedgc(prevheapsize) && osusectime()-prevgcpass <
10*1000*1000)
return;
gcidle++;
@@ -107,6 +112,10 @@
if(((ulong)gcidlepass&0xFF) == 0)
osyield();
}
+ if(gcruns()) {
+ prevheapsize = heapcursize();
+ prevgcpass = osusectime();
+ }
up->type = Interp;
delrunq(up->prog);
}