Skip to content

Commit 6dbbced

Browse files
committed
Merge pull request libgit2#2889 from jeffhostetler/jeffhostetler/merge_performance
Large merge perf test.
2 parents 5820edc + d97ba7f commit 6dbbced

File tree

5 files changed

+226
-0
lines changed

5 files changed

+226
-0
lines changed
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
#include "clar_libgit2.h"
2+
#include "helper__perf__do_merge.h"
3+
#include "helper__perf__timer.h"
4+
5+
static git_repository * g_repo;
6+
7+
void perf__do_merge(const char *fixture,
8+
const char *test_name,
9+
const char *id_a,
10+
const char *id_b)
11+
{
12+
git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT;
13+
git_clone_options clone_opts = GIT_CLONE_OPTIONS_INIT;
14+
git_merge_options merge_opts = GIT_MERGE_OPTIONS_INIT;
15+
git_oid oid_a;
16+
git_oid oid_b;
17+
git_reference *ref_branch_a = NULL;
18+
git_reference *ref_branch_b = NULL;
19+
git_commit *commit_a = NULL;
20+
git_commit *commit_b = NULL;
21+
git_annotated_commit *annotated_commits[1] = { NULL };
22+
perf_timer t_total = PERF_TIMER_INIT;
23+
perf_timer t_clone = PERF_TIMER_INIT;
24+
perf_timer t_checkout = PERF_TIMER_INIT;
25+
perf_timer t_merge = PERF_TIMER_INIT;
26+
27+
perf__timer__start(&t_total);
28+
29+
checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE;
30+
clone_opts.checkout_opts = checkout_opts;
31+
cl_git_pass(git_signature_now(&clone_opts.signature, "Me", "foo@example.com"));
32+
33+
perf__timer__start(&t_clone);
34+
cl_git_pass(git_clone(&g_repo, fixture, test_name, &clone_opts));
35+
perf__timer__stop(&t_clone);
36+
37+
git_oid_fromstr(&oid_a, id_a);
38+
cl_git_pass(git_commit_lookup(&commit_a, g_repo, &oid_a));
39+
cl_git_pass(git_branch_create(&ref_branch_a, g_repo,
40+
"A", commit_a,
41+
0, NULL, NULL));
42+
43+
perf__timer__start(&t_checkout);
44+
cl_git_pass(git_checkout_tree(g_repo, (git_object*)commit_a, &checkout_opts));
45+
perf__timer__stop(&t_checkout);
46+
47+
cl_git_pass(git_repository_set_head(g_repo,
48+
git_reference_name(ref_branch_a),
49+
NULL, NULL));
50+
51+
git_oid_fromstr(&oid_b, id_b);
52+
cl_git_pass(git_commit_lookup(&commit_b, g_repo, &oid_b));
53+
cl_git_pass(git_branch_create(&ref_branch_b, g_repo,
54+
"B", commit_b,
55+
0, NULL, NULL));
56+
57+
cl_git_pass(git_annotated_commit_lookup(&annotated_commits[0], g_repo, &oid_b));
58+
59+
perf__timer__start(&t_merge);
60+
cl_git_pass(git_merge(g_repo,
61+
(const git_annotated_commit **)annotated_commits, 1,
62+
&merge_opts, &checkout_opts));
63+
perf__timer__stop(&t_merge);
64+
65+
git_reference_free(ref_branch_a);
66+
git_reference_free(ref_branch_b);
67+
git_commit_free(commit_a);
68+
git_commit_free(commit_b);
69+
git_annotated_commit_free(annotated_commits[0]);
70+
git_repository_free(g_repo);
71+
72+
perf__timer__stop(&t_total);
73+
74+
perf__timer__report(&t_clone, "%s: clone", test_name);
75+
perf__timer__report(&t_checkout, "%s: checkout", test_name);
76+
perf__timer__report(&t_merge, "%s: merge", test_name);
77+
perf__timer__report(&t_total, "%s: total", test_name);
78+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
void perf__do_merge(const char *fixture,
2+
const char *test_name,
3+
const char *id_a,
4+
const char *id_b);

tests/perf/helper__perf__timer.c

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
#include "clar_libgit2.h"
2+
#include "helper__perf__timer.h"
3+
4+
#if defined(GIT_WIN32)
5+
6+
void perf__timer__start(perf_timer *t)
7+
{
8+
QueryPerformanceCounter(&t->time_started);
9+
}
10+
11+
void perf__timer__stop(perf_timer *t)
12+
{
13+
LARGE_INTEGER time_now;
14+
QueryPerformanceCounter(&time_now);
15+
16+
t->sum.QuadPart += (time_now.QuadPart - t->time_started.QuadPart);
17+
}
18+
19+
void perf__timer__report(perf_timer *t, const char *fmt, ...)
20+
{
21+
va_list arglist;
22+
LARGE_INTEGER freq;
23+
double fraction;
24+
25+
QueryPerformanceFrequency(&freq);
26+
27+
fraction = ((double)t->sum.QuadPart) / ((double)freq.QuadPart);
28+
29+
printf("%10.3f: ", fraction);
30+
31+
va_start(arglist, fmt);
32+
vprintf(fmt, arglist);
33+
va_end(arglist);
34+
35+
printf("\n");
36+
}
37+
38+
#else
39+
40+
#include <sys/time.h>
41+
42+
static uint32_t now_in_ms(void)
43+
{
44+
struct timeval now;
45+
gettimeofday(&now, NULL);
46+
return (uint32_t)((now.tv_sec * 1000) + (now.tv_usec / 1000));
47+
}
48+
49+
void perf__timer__start(perf_timer *t)
50+
{
51+
t->time_started = now_in_ms();
52+
}
53+
54+
void perf__timer__stop(perf_timer *t)
55+
{
56+
uint32_t now = now_in_ms();
57+
t->sum += (now - t->time_started);
58+
}
59+
60+
void perf__timer__report(perf_timer *t, const char *fmt, ...)
61+
{
62+
va_list arglist;
63+
64+
printf("%10.3f: ", ((double)t->sum) / 1000);
65+
66+
va_start(arglist, fmt);
67+
vprintf(fmt, arglist);
68+
va_end(arglist);
69+
70+
printf("\n");
71+
}
72+
73+
#endif

tests/perf/helper__perf__timer.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#if defined(GIT_WIN32)
2+
3+
struct perf__timer
4+
{
5+
LARGE_INTEGER sum;
6+
LARGE_INTEGER time_started;
7+
};
8+
9+
#define PERF_TIMER_INIT {0}
10+
11+
#else
12+
13+
struct perf__timer
14+
{
15+
uint32_t sum;
16+
uint32_t time_started;
17+
};
18+
19+
#define PERF_TIMER_INIT {0}
20+
21+
#endif
22+
23+
typedef struct perf__timer perf_timer;
24+
25+
void perf__timer__start(perf_timer *t);
26+
void perf__timer__stop(perf_timer *t);
27+
void perf__timer__report(perf_timer *t, const char *fmt, ...);

tests/perf/merge.c

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
#include "clar_libgit2.h"
2+
#include "helper__perf__do_merge.h"
3+
4+
/* This test requires a large repo with many files.
5+
* It doesn't care about the contents, just the size.
6+
*
7+
* For now, we use the LibGit2 repo containing the
8+
* source tree because it is already here.
9+
*
10+
* `find . | wc -l` reports 5128.
11+
*
12+
*/
13+
#define SRC_REPO (cl_fixture("../.."))
14+
15+
/* We need 2 arbitrary commits within that repo
16+
* that have a large number of changed files.
17+
* Again, we don't care about the actual contents,
18+
* just the size.
19+
*
20+
* For now, we use these public branches:
21+
* maint/v0.21 d853fb9f24e0fe63b3dce9fbc04fd9cfe17a030b Always checkout with case sensitive iterator
22+
* maint/v0.22 1ce9ea3ba9b4fa666602d52a5281d41a482cc58b checkout tests: cleanup realpath impl on Win32
23+
*
24+
*/
25+
#define ID_BRANCH_A "d853fb9f24e0fe63b3dce9fbc04fd9cfe17a030b"
26+
#define ID_BRANCH_B "1ce9ea3ba9b4fa666602d52a5281d41a482cc58b"
27+
28+
29+
void test_perf_merge__initialize(void)
30+
{
31+
}
32+
33+
void test_perf_merge__cleanup(void)
34+
{
35+
}
36+
37+
void test_perf_merge__m1(void)
38+
{
39+
#if 1
40+
cl_skip();
41+
#else
42+
perf__do_merge(SRC_REPO, "m1", ID_BRANCH_A, ID_BRANCH_B);
43+
#endif
44+
}

0 commit comments

Comments
 (0)