aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Lars Hjemli <hjemli@gmail.com>2008-11-30 00:46:37 (JST)
committerGravatar Lars Hjemli <hjemli@gmail.com>2008-11-30 00:46:37 (JST)
commit8813170390f3c3a0f4743afbc92ede42953fa3b0 (patch)
tree39305350baee1eb564aae00294634bbe544983d3
parent54272e60965ec6a98b49cbf67d72a4b1f5adc55b (diff)
downloadcgit-8813170390f3c3a0f4743afbc92ede42953fa3b0.zip
cgit-8813170390f3c3a0f4743afbc92ede42953fa3b0.tar.gz
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>
-rw-r--r--cgit.h1
-rw-r--r--shared.c1
-rw-r--r--ui-repolist.c16
3 files changed, 14 insertions, 4 deletions
diff --git a/cgit.h b/cgit.h
index ea90833..c99d337 100644
--- a/cgit.h
+++ b/cgit.h
@@ -61,6 +61,7 @@ struct cgit_repo {
61 int snapshots; 61 int snapshots;
62 int enable_log_filecount; 62 int enable_log_filecount;
63 int enable_log_linecount; 63 int enable_log_linecount;
64 time_t mtime;
64}; 65};
65 66
66struct cgit_repolist { 67struct cgit_repolist {
diff --git a/shared.c b/shared.c
index f5875e4..89d1bab 100644
--- a/shared.c
+++ b/shared.c
@@ -60,6 +60,7 @@ struct cgit_repo *cgit_add_repo(const char *url)
60 ret->enable_log_linecount = ctx.cfg.enable_log_linecount; 60 ret->enable_log_linecount = ctx.cfg.enable_log_linecount;
61 ret->module_link = ctx.cfg.module_link; 61 ret->module_link = ctx.cfg.module_link;
62 ret->readme = NULL; 62 ret->readme = NULL;
63 ret->mtime = -1;
63 return ret; 64 return ret;
64} 65}
65 66
diff --git a/ui-repolist.c b/ui-repolist.c
index cf27cb3..aa743bf 100644
--- a/ui-repolist.c
+++ b/ui-repolist.c
@@ -32,19 +32,27 @@ static int get_repo_modtime(const struct cgit_repo *repo, time_t *mtime)
32{ 32{
33 char *path; 33 char *path;
34 struct stat s; 34 struct stat s;
35 struct cgit_repo *r = (struct cgit_repo *)repo;
35 36
37 if (repo->mtime != -1) {
38 *mtime = repo->mtime;
39 return 1;
40 }
36 path = fmt("%s/%s", repo->path, ctx.cfg.agefile); 41 path = fmt("%s/%s", repo->path, ctx.cfg.agefile);
37 if (stat(path, &s) == 0) { 42 if (stat(path, &s) == 0) {
38 *mtime = read_agefile(path); 43 *mtime = read_agefile(path);
44 r->mtime = *mtime;
39 return 1; 45 return 1;
40 } 46 }
41 47
42 path = fmt("%s/refs/heads/%s", repo->path, repo->defbranch); 48 path = fmt("%s/refs/heads/%s", repo->path, repo->defbranch);
43 if (stat(path, &s) == 0) { 49 if (stat(path, &s) == 0)
44 *mtime = s.st_mtime; 50 *mtime = s.st_mtime;
45 return 1; 51 else
46 } 52 *mtime = 0;
47 return 0; 53
54 r->mtime = *mtime;
55 return (r->mtime != 0);
48} 56}
49 57
50static void print_modtime(struct cgit_repo *repo) 58static void print_modtime(struct cgit_repo *repo)