page: use less aggressive read ahead and keep track of image memory allocation
This commit is contained in:
parent
3904a8357d
commit
041eb4b30d
1 changed files with 62 additions and 48 deletions
|
@ -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;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue