git: improve pack cache heuristics

the pack cache was very stupid: it would close packs
as early as possible, which would prevent packs from
getting reused effectively. It would also select a
bad pack to close.

This picks the oldest pack, refcounts correctly, and
keeps up to Npackcache open at once (though it will
go over if more are in use).
This commit is contained in:
Ori Bernstein 2021-12-05 00:13:54 +00:00
parent 5465c4c01a
commit f0adfb4ded

View file

@ -253,38 +253,51 @@ openpack(Packf *pf)
vlong t; vlong t;
int i, best; int i, best;
if(pf->pack == nil){ if(pf->pack != nil){
if((pf->pack = Bopen(pf->path, OREAD)) == nil) pf->refs++;
return nil; return pf->pack;
openpacks++;
} }
if(openpacks == Npackcache){ /*
t = pf->opentm; * If we've got more packs open
* than we want cached, try to
* free up the oldest ones.
*
* If we can't find a slot, this
* isn't fatal; we can just use
* another fd.
*/
while(openpacks >= Npackcache){
t = (1ull<<62)-1;
best = -1; best = -1;
for(i = 0; i < npackf; i++){ for(i = 0; i < npackf; i++){
if(packf[i].opentm < t && packf[i].refs > 0){ if(&packf[i] != pf
&& packf[i].pack != nil
&& packf[i].opentm < t
&& packf[i].refs == 0){
t = packf[i].opentm; t = packf[i].opentm;
best = i; best = i;
} }
} }
if(best != -1){ if(best == -1){
Bterm(packf[best].pack); fprint(2, "no available pack slots\n");
packf[best].pack = nil; break;
openpacks--;
} }
Bterm(packf[best].pack);
packf[best].pack = nil;
openpacks--;
} }
openpacks++;
pf->opentm = nsec(); pf->opentm = nsec();
pf->refs++; pf->refs++;
if((pf->pack = Bopen(pf->path, OREAD)) == nil)
return nil;
return pf->pack; return pf->pack;
} }
static void static void
closepack(Packf *pf) closepack(Packf *pf)
{ {
if(--pf->refs == 0 && pf->pack != nil){ pf->refs--;
Bterm(pf->pack);
pf->pack = nil;
}
} }
static u32int static u32int