From: "Nguyễn Thái Ngọc Duy" <pclouds@gmail.com>
To: git@vger.kernel.org
Cc: "Thomas Rast" <trast@inf.ethz.ch>,
"Nguyễn Thái Ngọc Duy" <pclouds@gmail.com>
Subject: [PATCH 2/5] sha1_file: stuff various pack reading variables into a struct
Date: Tue, 10 Apr 2012 21:39:28 +0700 [thread overview]
Message-ID: <1334068771-32725-3-git-send-email-pclouds@gmail.com> (raw)
In-Reply-To: <1334068771-32725-1-git-send-email-pclouds@gmail.com>
This requires any threads (including the main one) to call
init_pack_context() first. All pack data is per thread.
Original patch is written by Thomas Rast <trast@student.ethz.ch>
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
cache.h | 1 +
git.c | 1 +
sha1_file.c | 251 +++++++++++++++++++++++++++++++++++------------------------
3 files changed, 152 insertions(+), 101 deletions(-)
diff --git a/cache.h b/cache.h
index 26d14b4..868ef48 100644
--- a/cache.h
+++ b/cache.h
@@ -997,6 +997,7 @@ struct packed_git {
extern struct packed_git *get_packed_git(void);
extern void set_packed_git(struct packed_git *);
+extern void init_pack_context(void);
struct pack_entry {
off_t offset;
diff --git a/git.c b/git.c
index 3805616..7eee270 100644
--- a/git.c
+++ b/git.c
@@ -533,6 +533,7 @@ int main(int argc, const char **argv)
const char *cmd;
startup_info = &git_startup_info;
+ init_pack_context();
cmd = git_extract_argv0_path(argv[0]);
if (!cmd)
diff --git a/sha1_file.c b/sha1_file.c
index 4fd4e2c..170c0b1 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -33,16 +33,79 @@ static inline uintmax_t sz_fmt(size_t s) { return s; }
const unsigned char null_sha1[20];
-static struct packed_git *packed_git_;
+#define MAX_DELTA_CACHE (256)
+
+struct delta_base_cache_lru_list {
+ struct delta_base_cache_lru_list *prev;
+ struct delta_base_cache_lru_list *next;
+};
+
+struct delta_base_cache_entry {
+ struct delta_base_cache_lru_list lru;
+ void *data;
+ struct packed_git *p;
+ off_t base_offset;
+ unsigned long size;
+ enum object_type type;
+};
+
+struct pack_context {
+ size_t delta_base_cached;
+ struct delta_base_cache_entry *delta_base_cache;
+ struct delta_base_cache_lru_list *delta_base_cache_lru;
+ struct packed_git *last_found_pack;
+
+ unsigned int pack_used_ctr;
+ unsigned int pack_mmap_calls;
+ unsigned int peak_pack_open_windows;
+ unsigned int pack_open_windows;
+ unsigned int pack_open_fds;
+ unsigned int pack_max_fds;
+ size_t peak_pack_mapped;
+ size_t pack_mapped;
+ struct packed_git *packed_git;
+ int prepare_packed_git_run_once;
+
+ char sha1_file_name_buf[PATH_MAX];
+ char *sha1_pack_name, *sha1_pack_base;
+ char *sha1_pack_index_name, *sha1_pack_index_base;
+};
+
+static pthread_key_t pack_key;
+struct pack_context *get_thread_pack_context(void)
+{
+ return pthread_getspecific(pack_key);
+}
+
struct packed_git *get_packed_git(void)
{
- return packed_git_;
+ return get_thread_pack_context()->packed_git;
}
void set_packed_git(struct packed_git *p)
{
- packed_git_ = p;
+ get_thread_pack_context()->packed_git = p;
}
+void init_pack_context(void)
+{
+ static int initialized = 0;
+ struct pack_context *ctx = xmalloc(sizeof(struct pack_context));
+
+ if (!initialized) {
+ pthread_key_create(&pack_key, NULL);
+ initialized = 1;
+ }
+
+ memset(ctx, 0, sizeof(*ctx));
+ ctx->delta_base_cached = 0;
+ ctx->delta_base_cache_lru = xmalloc(sizeof(struct delta_base_cache_lru_list));
+ ctx->delta_base_cache_lru->prev = ctx->delta_base_cache_lru;
+ ctx->delta_base_cache_lru->next = ctx->delta_base_cache_lru;
+ ctx->delta_base_cache = xcalloc(MAX_DELTA_CACHE, sizeof(struct delta_base_cache_entry));
+ ctx->last_found_pack = NULL;
+ ctx->packed_git = NULL;
+ pthread_setspecific(pack_key, ctx);
+}
/*
* This is meant to hold a *small* number of objects that you would
@@ -65,8 +128,6 @@ static struct cached_object empty_tree = {
0
};
-static struct packed_git *last_found_pack;
-
static struct cached_object *find_cached_object(const unsigned char *sha1)
{
int i;
@@ -177,7 +238,7 @@ static void fill_sha1_path(char *pathbuf, const unsigned char *sha1)
*/
char *sha1_file_name(const unsigned char *sha1)
{
- static char buf[PATH_MAX];
+ char *buf = get_thread_pack_context()->sha1_file_name_buf;
const char *objdir;
int len;
@@ -224,16 +285,14 @@ static char *sha1_get_pack_name(const unsigned char *sha1,
char *sha1_pack_name(const unsigned char *sha1)
{
- static char *name, *base;
-
- return sha1_get_pack_name(sha1, &name, &base, "pack");
+ struct pack_context *ctx = get_thread_pack_context();
+ return sha1_get_pack_name(sha1, &ctx->sha1_pack_name, &ctx->sha1_pack_base, "pack");
}
char *sha1_pack_index_name(const unsigned char *sha1)
{
- static char *name, *base;
-
- return sha1_get_pack_name(sha1, &name, &base, "idx");
+ struct pack_context *ctx = get_thread_pack_context();
+ return sha1_get_pack_name(sha1, &ctx->sha1_pack_index_name, &ctx->sha1_pack_index_base, "idx");
}
struct alternate_object_database *alt_odb_list;
@@ -455,18 +514,10 @@ static int has_loose_object(const unsigned char *sha1)
has_loose_object_nonlocal(sha1);
}
-static unsigned int pack_used_ctr;
-static unsigned int pack_mmap_calls;
-static unsigned int peak_pack_open_windows;
-static unsigned int pack_open_windows;
-static unsigned int pack_open_fds;
-static unsigned int pack_max_fds;
-static size_t peak_pack_mapped;
-static size_t pack_mapped;
-struct packed_git *packed_git;
-
-void pack_report(void)
+void pack_report()
{
+ struct pack_context *ctx = get_thread_pack_context();
+
fprintf(stderr,
"pack_report: getpagesize() = %10" SZ_FMT "\n"
"pack_report: core.packedGitWindowSize = %10" SZ_FMT "\n"
@@ -480,10 +531,10 @@ void pack_report(void)
"pack_report: pack_open_windows = %10u / %10u\n"
"pack_report: pack_mapped = "
"%10" SZ_FMT " / %10" SZ_FMT "\n",
- pack_used_ctr,
- pack_mmap_calls,
- pack_open_windows, peak_pack_open_windows,
- sz_fmt(pack_mapped), sz_fmt(peak_pack_mapped));
+ ctx->pack_used_ctr,
+ ctx->pack_mmap_calls,
+ ctx->pack_open_windows, ctx->peak_pack_open_windows,
+ sz_fmt(ctx->pack_mapped), sz_fmt(ctx->peak_pack_mapped));
}
static int check_packed_git_idx(const char *path, struct packed_git *p)
@@ -624,6 +675,7 @@ static void scan_windows(struct packed_git *p,
static int unuse_one_window(struct packed_git *current, int keep_fd)
{
+ struct pack_context *ctx = get_thread_pack_context();
struct packed_git *p, *lru_p = NULL;
struct pack_window *lru_w = NULL, *lru_l = NULL;
@@ -633,7 +685,7 @@ static int unuse_one_window(struct packed_git *current, int keep_fd)
scan_windows(p, &lru_p, &lru_w, &lru_l);
if (lru_p) {
munmap(lru_w->base, lru_w->len);
- pack_mapped -= lru_w->len;
+ ctx->pack_mapped -= lru_w->len;
if (lru_l)
lru_l->next = lru_w->next;
else {
@@ -641,12 +693,12 @@ static int unuse_one_window(struct packed_git *current, int keep_fd)
if (!lru_p->windows && lru_p->pack_fd != -1
&& lru_p->pack_fd != keep_fd) {
close(lru_p->pack_fd);
- pack_open_fds--;
+ ctx->pack_open_fds--;
lru_p->pack_fd = -1;
}
}
free(lru_w);
- pack_open_windows--;
+ ctx->pack_open_windows--;
return 1;
}
return 0;
@@ -654,8 +706,9 @@ static int unuse_one_window(struct packed_git *current, int keep_fd)
void release_pack_memory(size_t need, int fd)
{
- size_t cur = pack_mapped;
- while (need >= (cur - pack_mapped) && unuse_one_window(NULL, fd))
+ struct pack_context *ctx = get_thread_pack_context();
+ size_t cur = ctx->pack_mapped;
+ while (need >= (cur - ctx->pack_mapped) && unuse_one_window(NULL, fd))
; /* nothing */
}
@@ -676,6 +729,7 @@ void *xmmap(void *start, size_t length,
void close_pack_windows(struct packed_git *p)
{
+ struct pack_context *ctx = get_thread_pack_context();
while (p->windows) {
struct pack_window *w = p->windows;
@@ -683,8 +737,8 @@ void close_pack_windows(struct packed_git *p)
die("pack '%s' still has open windows to it",
p->pack_name);
munmap(w->base, w->len);
- pack_mapped -= w->len;
- pack_open_windows--;
+ ctx->pack_mapped -= w->len;
+ ctx->pack_open_windows--;
p->windows = w->next;
free(w);
}
@@ -719,7 +773,8 @@ void close_pack_index(struct packed_git *p)
*/
void free_pack_by_name(const char *pack_name)
{
- struct packed_git *p, **pp = &packed_git_;
+ struct pack_context *ctx = get_thread_pack_context();
+ struct packed_git *p, **pp = &ctx->packed_git;
while (*pp) {
p = *pp;
@@ -728,13 +783,13 @@ void free_pack_by_name(const char *pack_name)
close_pack_windows(p);
if (p->pack_fd != -1) {
close(p->pack_fd);
- pack_open_fds--;
+ ctx->pack_open_fds--;
}
close_pack_index(p);
free(p->bad_object_sha1);
*pp = p->next;
- if (last_found_pack == p)
- last_found_pack = NULL;
+ if (ctx->last_found_pack == p)
+ ctx->last_found_pack = NULL;
free(p);
return;
}
@@ -748,6 +803,7 @@ void free_pack_by_name(const char *pack_name)
*/
static int open_packed_git_1(struct packed_git *p)
{
+ struct pack_context *ctx = get_thread_pack_context();
struct stat st;
struct pack_header hdr;
unsigned char sha1[20];
@@ -757,7 +813,7 @@ static int open_packed_git_1(struct packed_git *p)
if (!p->index_data && open_pack_index(p))
return error("packfile %s index unavailable", p->pack_name);
- if (!pack_max_fds) {
+ if (!ctx->pack_max_fds) {
struct rlimit lim;
unsigned int max_fds;
@@ -768,18 +824,18 @@ static int open_packed_git_1(struct packed_git *p)
/* Save 3 for stdin/stdout/stderr, 22 for work */
if (25 < max_fds)
- pack_max_fds = max_fds - 25;
+ ctx->pack_max_fds = max_fds - 25;
else
- pack_max_fds = 1;
+ ctx->pack_max_fds = 1;
}
- while (pack_max_fds <= pack_open_fds && unuse_one_window(NULL, -1))
+ while (ctx->pack_max_fds <= ctx->pack_open_fds && unuse_one_window(NULL, -1))
; /* nothing */
p->pack_fd = git_open_noatime(p->pack_name);
if (p->pack_fd < 0 || fstat(p->pack_fd, &st))
return -1;
- pack_open_fds++;
+ ctx->pack_open_fds++;
/* If we created the struct before we had the pack we lack size. */
if (!p->pack_size) {
@@ -827,11 +883,12 @@ static int open_packed_git_1(struct packed_git *p)
static int open_packed_git(struct packed_git *p)
{
+ struct pack_context *ctx = get_thread_pack_context();
if (!open_packed_git_1(p))
return 0;
if (p->pack_fd != -1) {
close(p->pack_fd);
- pack_open_fds--;
+ ctx->pack_open_fds--;
p->pack_fd = -1;
}
return -1;
@@ -855,6 +912,7 @@ unsigned char *use_pack(struct packed_git *p,
off_t offset,
unsigned long *left)
{
+ struct pack_context *ctx = get_thread_pack_context();
struct pack_window *win = *w_cursor;
/* Since packfiles end in a hash of their content and it's
@@ -887,8 +945,8 @@ unsigned char *use_pack(struct packed_git *p,
if (len > packed_git_window_size)
len = packed_git_window_size;
win->len = (size_t)len;
- pack_mapped += win->len;
- while (packed_git_limit < pack_mapped
+ ctx->pack_mapped += win->len;
+ while (packed_git_limit < ctx->pack_mapped
&& unuse_one_window(p, p->pack_fd))
; /* nothing */
win->base = xmmap(NULL, win->len,
@@ -901,21 +959,21 @@ unsigned char *use_pack(struct packed_git *p,
if (!win->offset && win->len == p->pack_size
&& !p->do_not_close) {
close(p->pack_fd);
- pack_open_fds--;
+ ctx->pack_open_fds--;
p->pack_fd = -1;
}
- pack_mmap_calls++;
- pack_open_windows++;
- if (pack_mapped > peak_pack_mapped)
- peak_pack_mapped = pack_mapped;
- if (pack_open_windows > peak_pack_open_windows)
- peak_pack_open_windows = pack_open_windows;
+ ctx->pack_mmap_calls++;
+ ctx->pack_open_windows++;
+ if (ctx->pack_mapped > ctx->peak_pack_mapped)
+ ctx->peak_pack_mapped = ctx->pack_mapped;
+ if (ctx->pack_open_windows > ctx->peak_pack_open_windows)
+ ctx->peak_pack_open_windows = ctx->pack_open_windows;
win->next = p->windows;
p->windows = win;
}
}
if (win != *w_cursor) {
- win->last_used = pack_used_ctr++;
+ win->last_used = ctx->pack_used_ctr++;
win->inuse_cnt++;
*w_cursor = win;
}
@@ -998,8 +1056,9 @@ struct packed_git *parse_pack_index(unsigned char *sha1, const char *idx_path)
void install_packed_git(struct packed_git *pack)
{
+ struct pack_context *ctx = get_thread_pack_context();
if (pack->pack_fd != -1)
- pack_open_fds++;
+ ctx->pack_open_fds++;
pack->next = get_packed_git();
set_packed_git(pack);
@@ -1108,12 +1167,12 @@ static void rearrange_packed_git(void)
free(ary);
}
-static int prepare_packed_git_run_once = 0;
void prepare_packed_git(void)
{
struct alternate_object_database *alt;
+ struct pack_context *ctx = get_thread_pack_context();
- if (prepare_packed_git_run_once)
+ if (ctx->prepare_packed_git_run_once)
return;
prepare_packed_git_one(get_object_directory(), 1);
prepare_alt_odb();
@@ -1123,13 +1182,14 @@ void prepare_packed_git(void)
alt->name[-1] = '/';
}
rearrange_packed_git();
- prepare_packed_git_run_once = 1;
+ ctx->prepare_packed_git_run_once = 1;
}
void reprepare_packed_git(void)
{
+ struct pack_context *ctx = get_thread_pack_context();
discard_revindex();
- prepare_packed_git_run_once = 0;
+ ctx->prepare_packed_git_run_once = 0;
prepare_packed_git();
}
@@ -1664,24 +1724,6 @@ static void *unpack_compressed_entry(struct packed_git *p,
return buffer;
}
-#define MAX_DELTA_CACHE (256)
-
-static size_t delta_base_cached;
-
-static struct delta_base_cache_lru_list {
- struct delta_base_cache_lru_list *prev;
- struct delta_base_cache_lru_list *next;
-} delta_base_cache_lru = { &delta_base_cache_lru, &delta_base_cache_lru };
-
-static struct delta_base_cache_entry {
- struct delta_base_cache_lru_list lru;
- void *data;
- struct packed_git *p;
- off_t base_offset;
- unsigned long size;
- enum object_type type;
-} delta_base_cache[MAX_DELTA_CACHE];
-
static unsigned long pack_entry_hash(struct packed_git *p, off_t base_offset)
{
unsigned long hash;
@@ -1694,7 +1736,8 @@ static unsigned long pack_entry_hash(struct packed_git *p, off_t base_offset)
static int in_delta_base_cache(struct packed_git *p, off_t base_offset)
{
unsigned long hash = pack_entry_hash(p, base_offset);
- struct delta_base_cache_entry *ent = delta_base_cache + hash;
+ struct delta_base_cache_entry *ent
+ = get_thread_pack_context()->delta_base_cache + hash;
return (ent->data && ent->p == p && ent->base_offset == base_offset);
}
@@ -1703,7 +1746,8 @@ static void *cache_or_unpack_entry(struct packed_git *p, off_t base_offset,
{
void *ret;
unsigned long hash = pack_entry_hash(p, base_offset);
- struct delta_base_cache_entry *ent = delta_base_cache + hash;
+ struct pack_context *ctx = get_thread_pack_context();
+ struct delta_base_cache_entry *ent = ctx->delta_base_cache + hash;
ret = ent->data;
if (!ret || ent->p != p || ent->base_offset != base_offset)
@@ -1713,7 +1757,7 @@ static void *cache_or_unpack_entry(struct packed_git *p, off_t base_offset,
ent->data = NULL;
ent->lru.next->prev = ent->lru.prev;
ent->lru.prev->next = ent->lru.next;
- delta_base_cached -= ent->size;
+ ctx->delta_base_cached -= ent->size;
} else {
ret = xmemdupz(ent->data, ent->size);
}
@@ -1722,48 +1766,52 @@ static void *cache_or_unpack_entry(struct packed_git *p, off_t base_offset,
return ret;
}
-static inline void release_delta_base_cache(struct delta_base_cache_entry *ent)
+static inline void release_delta_base_cache(struct pack_context *ctx,
+ struct delta_base_cache_entry *ent)
{
if (ent->data) {
free(ent->data);
ent->data = NULL;
ent->lru.next->prev = ent->lru.prev;
ent->lru.prev->next = ent->lru.next;
- delta_base_cached -= ent->size;
+ ctx->delta_base_cached -= ent->size;
}
}
void clear_delta_base_cache(void)
{
unsigned long p;
+ struct pack_context *ctx = get_thread_pack_context();
+ struct delta_base_cache_entry *delta_base_cache = ctx->delta_base_cache;
for (p = 0; p < MAX_DELTA_CACHE; p++)
- release_delta_base_cache(&delta_base_cache[p]);
+ release_delta_base_cache(ctx, &delta_base_cache[p]);
}
static void add_delta_base_cache(struct packed_git *p, off_t base_offset,
void *base, unsigned long base_size, enum object_type type)
{
unsigned long hash = pack_entry_hash(p, base_offset);
- struct delta_base_cache_entry *ent = delta_base_cache + hash;
+ struct pack_context *ctx = get_thread_pack_context();
+ struct delta_base_cache_entry *ent = ctx->delta_base_cache + hash;
struct delta_base_cache_lru_list *lru;
- release_delta_base_cache(ent);
- delta_base_cached += base_size;
+ release_delta_base_cache(ctx, ent);
+ ctx->delta_base_cached += base_size;
- for (lru = delta_base_cache_lru.next;
- delta_base_cached > delta_base_cache_limit
- && lru != &delta_base_cache_lru;
+ for (lru = ctx->delta_base_cache_lru->next;
+ ctx->delta_base_cached > delta_base_cache_limit
+ && lru != ctx->delta_base_cache_lru;
lru = lru->next) {
struct delta_base_cache_entry *f = (void *)lru;
if (f->type == OBJ_BLOB)
- release_delta_base_cache(f);
+ release_delta_base_cache(ctx, f);
}
- for (lru = delta_base_cache_lru.next;
- delta_base_cached > delta_base_cache_limit
- && lru != &delta_base_cache_lru;
+ for (lru = ctx->delta_base_cache_lru->next;
+ ctx->delta_base_cached > delta_base_cache_limit
+ && lru != ctx->delta_base_cache_lru;
lru = lru->next) {
struct delta_base_cache_entry *f = (void *)lru;
- release_delta_base_cache(f);
+ release_delta_base_cache(ctx, f);
}
ent->p = p;
@@ -1771,10 +1819,10 @@ static void add_delta_base_cache(struct packed_git *p, off_t base_offset,
ent->type = type;
ent->data = base;
ent->size = base_size;
- ent->lru.next = &delta_base_cache_lru;
- ent->lru.prev = delta_base_cache_lru.prev;
- delta_base_cache_lru.prev->next = &ent->lru;
- delta_base_cache_lru.prev = &ent->lru;
+ ent->lru.next = ctx->delta_base_cache_lru;
+ ent->lru.prev = ctx->delta_base_cache_lru->prev;
+ ctx->delta_base_cache_lru->prev->next = &ent->lru;
+ ctx->delta_base_cache_lru->prev = &ent->lru;
}
static void *read_object(const unsigned char *sha1, enum object_type *type,
@@ -2066,20 +2114,21 @@ static int fill_pack_entry(const unsigned char *sha1,
static int find_pack_entry(const unsigned char *sha1, struct pack_entry *e)
{
+ struct pack_context *ctx = get_thread_pack_context();
struct packed_git *p;
prepare_packed_git();
if (!get_packed_git())
return 0;
- if (last_found_pack && fill_pack_entry(sha1, e, last_found_pack))
+ if (ctx->last_found_pack && fill_pack_entry(sha1, e, ctx->last_found_pack))
return 1;
for (p = get_packed_git(); p; p = p->next) {
- if (p == last_found_pack || !fill_pack_entry(sha1, e, p))
+ if (p == ctx->last_found_pack || !fill_pack_entry(sha1, e, p))
continue;
- last_found_pack = p;
+ ctx->last_found_pack = p;
return 1;
}
return 0;
--
1.7.8.36.g69ee2
next prev parent reply other threads:[~2012-04-10 14:42 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-04-10 14:39 [PATCH 0/5] multithread traverse_commit_list (aka rev-list) Nguyễn Thái Ngọc Duy
2012-04-10 14:39 ` [PATCH 1/5] Remove global pointer "packed_git" in favor or set/get function pair Nguyễn Thái Ngọc Duy
2012-04-10 14:39 ` Nguyễn Thái Ngọc Duy [this message]
2012-04-10 14:39 ` [PATCH 3/5] Make lookup_*() functions thread-safe Nguyễn Thái Ngọc Duy
2012-04-10 14:39 ` [PATCH 4/5] Teach traverse_commit_list callsites about new parameter, nr_threads Nguyễn Thái Ngọc Duy
2012-04-10 14:39 ` [PATCH 5/5] Support multithread in traverse_commit_list and rev-list Nguyễn Thái Ngọc Duy
2012-04-10 16:51 ` [PATCH 0/5] multithread traverse_commit_list (aka rev-list) Martin Fick
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1334068771-32725-3-git-send-email-pclouds@gmail.com \
--to=pclouds@gmail.com \
--cc=git@vger.kernel.org \
--cc=trast@inf.ethz.ch \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).