page: use less aggressive read ahead and keep track of image memory allocation

This commit is contained in:
cinap_lenrek 2013-08-03 04:11:24 +02:00
parent 3904a8357d
commit 041eb4b30d

View file

@ -17,7 +17,6 @@ struct Page {
Image *image; Image *image;
int fd; int fd;
int gen;
Page *up; Page *up;
Page *next; Page *next;
@ -31,19 +30,24 @@ int imode;
int newwin; int newwin;
int rotate; int rotate;
int viewgen; int viewgen;
int pagegen;
Point resize, pos; Point resize, pos;
Page *root, *current; Page *root, *current;
QLock pagelock; QLock pagelock;
int nullfd; int nullfd;
enum {
MiB = 1024*1024,
};
ulong imemlimit = 8*MiB;
ulong imemsize;
Image *frame, *paper, *ground; Image *frame, *paper, *ground;
char pagespool[] = "/tmp/pagespool."; char pagespool[] = "/tmp/pagespool.";
enum { enum {
NPROC = 4, NPROC = 4,
NAHEAD = 2,
NBUF = 8*1024, NBUF = 8*1024,
NPATH = 1024, NPATH = 1024,
}; };
@ -128,8 +132,7 @@ addpage(Page *up, char *label, int (*popen)(Page *), void *pdata, int fd)
p = mallocz(sizeof(*p), 1); p = mallocz(sizeof(*p), 1);
p->label = strdup(label); p->label = strdup(label);
p->gen = pagegen; p->image = nil;
p->image = nil;
p->data = pdata; p->data = pdata;
p->open = popen; p->open = popen;
p->fd = fd; p->fd = fd;
@ -818,6 +821,14 @@ openpage(Page *p)
return fd; return fd;
} }
static ulong
imagesize(Image *i)
{
if(i == nil)
return 0;
return Dy(i->r)*bytesperline(i->r, i->depth);
}
void void
loadpage(Page *p) loadpage(Page *p)
{ {
@ -826,15 +837,18 @@ loadpage(Page *p)
if(p->open && p->image == nil){ if(p->open && p->image == nil){
fd = openpage(p); fd = openpage(p);
if(fd >= 0){ if(fd >= 0){
pagegen++;
if((p->image = readimage(display, fd, 1)) == nil) if((p->image = readimage(display, fd, 1)) == nil)
fprint(2, "readimage: %r\n"); fprint(2, "readimage: %r\n");
close(fd); close(fd);
} }
if(p->image == nil) if(p->image == nil)
p->open = nil; p->open = nil;
else {
lockdisplay(display);
imemsize += imagesize(p->image);
unlockdisplay(display);
}
} }
p->gen = pagegen;
} }
void void
@ -843,59 +857,52 @@ unloadpage(Page *p)
if(p->open == nil || p->image == nil) if(p->open == nil || p->image == nil)
return; return;
lockdisplay(display); lockdisplay(display);
imemsize -= imagesize(p->image);
freeimage(p->image); freeimage(p->image);
unlockdisplay(display); unlockdisplay(display);
p->image = nil; p->image = nil;
} }
void void
unloadpages(int age) unloadpages(ulong limit)
{ {
Page *p; Page *p;
for(p = root->down; p; p = nextpage(p)){ for(p = root->down; p && imemsize >= limit; p = nextpage(p)){
if(age == 0) /* synchronous flush */ qlock(p);
qlock(p); unloadpage(p);
else if(!canqlock(p))
continue;
if((pagegen - p->gen) >= age)
unloadpage(p);
qunlock(p); qunlock(p);
} }
} }
void void
loadpages(Page *p, int ahead, int oviewgen) loadpages(Page *p, int oviewgen)
{ {
int i; while(p && viewgen == oviewgen){
qlock(p);
ahead++; /* load at least one */ loadpage(p);
unloadpages(ahead*2); if(viewgen != oviewgen){
for(i = 0; i < ahead && p; p = nextpage(p), i++){ unloadpage(p);
if(viewgen != oviewgen)
break;
if(canqlock(p)){
loadpage(p);
if(viewgen != oviewgen){
unloadpage(p);
qunlock(p);
break;
}
if(p == current){
Point size;
esetcursor(nil);
size = pagesize(p);
if(size.x && size.y && newwin){
newwin = 0;
resizewin(size);
}
lockdisplay(display);
drawpage(p);
unlockdisplay(display);
}
qunlock(p); qunlock(p);
break;
} }
if(p == current){
Point size;
esetcursor(nil);
size = pagesize(p);
if(size.x && size.y && newwin){
newwin = 0;
resizewin(size);
}
lockdisplay(display);
drawpage(p);
unlockdisplay(display);
}
qunlock(p);
if(p != current || imemsize >= imemlimit)
break;
p = nextpage(p);
} }
} }
@ -1149,16 +1156,16 @@ showpage1(Page *p)
esetcursor(&reading); esetcursor(&reading);
current = p; current = p;
oviewgen = viewgen; oviewgen = viewgen;
if(++nproc > NPROC)
if(waitpid() > 0)
nproc--;
switch(rfork(RFPROC|RFMEM)){ switch(rfork(RFPROC|RFMEM)){
case -1: case -1:
sysfatal("rfork: %r"); sysfatal("rfork: %r");
case 0: case 0:
loadpages(p, NAHEAD, oviewgen); loadpages(p, oviewgen);
exits(nil); exits(nil);
} }
if(++nproc >= NPROC)
if(waitpid() > 0)
nproc--;
} }
/* recursive display lock, called from main proc only */ /* recursive display lock, called from main proc only */
@ -1178,7 +1185,11 @@ drawlock(int dolock){
void void
showpage(Page *p) showpage(Page *p)
{ {
if(p == nil)
return;
drawlock(0); drawlock(0);
if(p->image == nil)
unloadpages(imemlimit/2);
showpage1(p); showpage1(p);
drawlock(1); drawlock(1);
} }
@ -1312,7 +1323,7 @@ void drawerr(Display *, char *msg)
void void
usage(void) usage(void)
{ {
fprint(2, "usage: %s [ -iRw ] [ -p ppi ] [ file ... ]\n", argv0); fprint(2, "usage: %s [ -iRw ] [ -m mb ] [ -p ppi ] [ file ... ]\n", argv0);
exits("usage"); exits("usage");
} }
@ -1446,6 +1457,9 @@ main(int argc, char *argv[])
case 'i': case 'i':
imode = 1; imode = 1;
break; break;
case 'm':
imemlimit = atol(EARGF(usage()))*MiB;
break;
case 'p': case 'p':
ppi = atoi(EARGF(usage())); ppi = atoi(EARGF(usage()));
break; break;