Skip to content

Commit ea23f90

Browse files
committed
macOS: queue for munmap operations
Executing many mmap/munmap calls alternately can cause a huge load on macOS. In order to reduce it, we should temporarily store munmap operations in a queue and process them all at once when the queue is filled. When the program terminates, we can discard any remaining munmap operations as corresponding mmaped regions are automatically reclaimed. Add a queue for munmap operations to perform them all at once. Here are some example timings. On the Linux kernel repository that requires about 1700 mmap/munmap calls: time git ls-tree -r -l --full-tree 211ddde > /dev/null Before: real 0m2.083s user 0m0.201s sys 0m1.873s After: real 0m0.243s user 0m0.179s sys 0m0.052s On a private repository that requires about 943000 mmap/munmap calls: time git ls-tree -r -l --full-tree xxxxxxx > /dev/null Before: real 27m15.138s user 0m5.084s sys 27m9.636s After: real 0m24.209s user 0m3.055s sys 0m21.123s Signed-off-by: Koji Nakamaru <koji.nakamaru@gree.net>
1 parent 4253630 commit ea23f90

File tree

3 files changed

+57
-0
lines changed

3 files changed

+57
-0
lines changed

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1654,6 +1654,7 @@ ifeq ($(uname_S),Darwin)
16541654
COMPAT_CFLAGS += -DAPPLE_COMMON_CRYPTO
16551655
endif
16561656
PTHREAD_LIBS =
1657+
COMPAT_OBJS += compat/osxmmap.o
16571658
endif
16581659

16591660
ifdef NO_LIBGEN_H

compat/osxmmap.c

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
#include <pthread.h>
2+
#include "../git-compat-util.h"
3+
/* We need original mmap/munmap here. */
4+
#undef mmap
5+
#undef munmap
6+
7+
/*
8+
* OSX doesn't have any specific setting like Linux's vm.max_map_count,
9+
* so COUNT_MAX can be any large number. We here set it to the default
10+
* value of Linux's vm.max_map_count.
11+
*/
12+
#define COUNT_MAX (65530)
13+
14+
struct munmap_queue {
15+
void *start;
16+
size_t length;
17+
};
18+
19+
void *git_mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset)
20+
{
21+
/*
22+
* We can simply discard munmap operations in the queue by
23+
* restricting mmap arguments.
24+
*/
25+
if (start != NULL || flags != MAP_PRIVATE || prot != PROT_READ)
26+
die("invalid usage of mmap");
27+
return mmap(start, length, prot, flags, fd, offset);
28+
}
29+
30+
int git_munmap(void *start, size_t length)
31+
{
32+
static pthread_mutex_t mutex;
33+
static struct munmap_queue *queue;
34+
static int count;
35+
int i;
36+
37+
pthread_mutex_lock(&mutex);
38+
if (!queue)
39+
queue = xmalloc(COUNT_MAX * sizeof(struct munmap_queue));
40+
queue[count].start = start;
41+
queue[count].length = length;
42+
if (++count == COUNT_MAX) {
43+
for (i = 0; i < COUNT_MAX; i++)
44+
munmap(queue[i].start, queue[i].length);
45+
count = 0;
46+
}
47+
pthread_mutex_unlock(&mutex);
48+
return 0;
49+
}

compat/posix.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,13 @@ int git_munmap(void *start, size_t length);
278278

279279
#include <sys/mman.h>
280280

281+
#if defined(__APPLE__)
282+
#define mmap git_mmap
283+
#define munmap git_munmap
284+
void *git_mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset);
285+
int git_munmap(void *start, size_t length);
286+
#endif
287+
281288
#endif /* NO_MMAP || USE_WIN32_MMAP */
282289

283290
#ifndef MAP_FAILED

0 commit comments

Comments
 (0)