all repos — cgit @ 8813170390f3c3a0f4743afbc92ede42953fa3b0

a hyperfast web frontend for git written in c

ui-repolist: implement lazy caching of repo->mtime

When sorting the list of repositories by their last modification time,
cgit would (in the worst case) invoke fstat(3) four times and open(3)
twice for each callback from qsort(3). This obviously scales very badly.

Now, the calculated modtime for each repo is saved in repo->mtime, thus
keeping the number of stat/open invocations identical for sorted and
unsorted repo-listings.

Signed-off-by: Lars Hjemli <hjemli@gmail.com>
Lars Hjemli hjemli@gmail.com
Sat, 29 Nov 2008 16:46:37 +0100
commit

8813170390f3c3a0f4743afbc92ede42953fa3b0

parent

54272e60965ec6a98b49cbf67d72a4b1f5adc55b

3 files changed, 14 insertions(+), 4 deletions(-)

jump to
M cgit.hcgit.h

@@ -61,6 +61,7 @@ char *clone_url;

int snapshots; int enable_log_filecount; int enable_log_linecount; + time_t mtime; }; struct cgit_repolist {
M shared.cshared.c

@@ -60,6 +60,7 @@ ret->enable_log_filecount = ctx.cfg.enable_log_filecount;

ret->enable_log_linecount = ctx.cfg.enable_log_linecount; ret->module_link = ctx.cfg.module_link; ret->readme = NULL; + ret->mtime = -1; return ret; }
M ui-repolist.cui-repolist.c

@@ -32,19 +32,27 @@ static int get_repo_modtime(const struct cgit_repo *repo, time_t *mtime)

{ char *path; struct stat s; + struct cgit_repo *r = (struct cgit_repo *)repo; + if (repo->mtime != -1) { + *mtime = repo->mtime; + return 1; + } path = fmt("%s/%s", repo->path, ctx.cfg.agefile); if (stat(path, &s) == 0) { *mtime = read_agefile(path); + r->mtime = *mtime; return 1; } path = fmt("%s/refs/heads/%s", repo->path, repo->defbranch); - if (stat(path, &s) == 0) { + if (stat(path, &s) == 0) *mtime = s.st_mtime; - return 1; - } - return 0; + else + *mtime = 0; + + r->mtime = *mtime; + return (r->mtime != 0); } static void print_modtime(struct cgit_repo *repo)