}
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 size_t peak_pack_mapped;
static size_t pack_mapped;
static size_t page_size;
struct packed_git *packed_git;
+void pack_report()
+{
+ fprintf(stderr,
+ "pack_report: getpagesize() = %10lu\n"
+ "pack_report: core.packedGitWindowSize = %10lu\n"
+ "pack_report: core.packedGitLimit = %10lu\n",
+ page_size,
+ packed_git_window_size,
+ packed_git_limit);
+ fprintf(stderr,
+ "pack_report: pack_used_ctr = %10u\n"
+ "pack_report: pack_mmap_calls = %10u\n"
+ "pack_report: pack_open_windows = %10u / %10u\n"
+ "pack_report: pack_mapped = %10lu / %10lu\n",
+ pack_used_ctr,
+ pack_mmap_calls,
+ pack_open_windows, peak_pack_open_windows,
+ pack_mapped, peak_pack_mapped);
+}
+
static int check_packed_git_idx(const char *path, unsigned long *idx_size_,
void **idx_map_)
{
return 0;
}
-static int unuse_one_window(void)
+static void scan_windows(struct packed_git *p,
+ struct packed_git **lru_p,
+ struct pack_window **lru_w,
+ struct pack_window **lru_l)
{
- struct packed_git *p, *lru_p = NULL;
- struct pack_window *w, *w_l, *lru_w = NULL, *lru_l = NULL;
+ struct pack_window *w, *w_l;
- for (p = packed_git; p; p = p->next) {
- for (w_l = NULL, w = p->windows; w; w = w->next) {
- if (!w->inuse_cnt) {
- if (!lru_w || w->last_used < lru_w->last_used) {
- lru_p = p;
- lru_w = w;
- lru_l = w_l;
- }
+ for (w_l = NULL, w = p->windows; w; w = w->next) {
+ if (!w->inuse_cnt) {
+ if (!*lru_w || w->last_used < (*lru_w)->last_used) {
+ *lru_p = p;
+ *lru_w = w;
+ *lru_l = w_l;
}
- w_l = w;
}
+ w_l = w;
}
+}
+
+static int unuse_one_window(struct packed_git *current)
+{
+ struct packed_git *p, *lru_p = NULL;
+ struct pack_window *lru_w = NULL, *lru_l = NULL;
+
+ if (current)
+ scan_windows(current, &lru_p, &lru_w, &lru_l);
+ for (p = packed_git; p; p = p->next)
+ scan_windows(p, &lru_p, &lru_w, &lru_l);
if (lru_p) {
munmap(lru_w->base, lru_w->len);
pack_mapped -= lru_w->len;
lru_l->next = lru_w->next;
else {
lru_p->windows = lru_w->next;
- if (!lru_p->windows) {
+ if (!lru_p->windows && lru_p != current) {
close(lru_p->pack_fd);
lru_p->pack_fd = -1;
}
}
free(lru_w);
+ pack_open_windows--;
return 1;
}
return 0;
}
+void release_pack_memory(size_t need)
+{
+ size_t cur = pack_mapped;
+ while (need >= (cur - pack_mapped) && unuse_one_window(NULL))
+ ; /* nothing */
+}
+
void unuse_pack(struct pack_window **w_cursor)
{
struct pack_window *w = *w_cursor;
if (win->len > packed_git_window_size)
win->len = packed_git_window_size;
pack_mapped += win->len;
- while (packed_git_limit < pack_mapped && unuse_one_window())
+ while (packed_git_limit < pack_mapped
+ && unuse_one_window(p))
; /* nothing */
win->base = mmap(NULL, win->len,
PROT_READ, MAP_PRIVATE,
die("packfile %s cannot be mapped: %s",
p->pack_name,
strerror(errno));
+ 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;
win->next = p->windows;
p->windows = win;
}