mirror of
https://git.proxmox.com/git/libgit2
synced 2025-06-20 13:41:23 +00:00
Add build option for diff internal statistics
This commit is contained in:
parent
6a1ca96e41
commit
240f4af321
@ -37,6 +37,7 @@ OPTION( ANDROID "Build for android NDK" OFF )
|
|||||||
OPTION( USE_ICONV "Link with and use iconv library" OFF )
|
OPTION( USE_ICONV "Link with and use iconv library" OFF )
|
||||||
OPTION( USE_SSH "Link with libssh to enable SSH support" ON )
|
OPTION( USE_SSH "Link with libssh to enable SSH support" ON )
|
||||||
OPTION( VALGRIND "Configure build for valgrind" OFF )
|
OPTION( VALGRIND "Configure build for valgrind" OFF )
|
||||||
|
OPTION( PERF_STATS "Internally track performance data" OFF )
|
||||||
|
|
||||||
IF(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
|
IF(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
|
||||||
SET( USE_ICONV ON )
|
SET( USE_ICONV ON )
|
||||||
@ -352,6 +353,10 @@ IF (THREADSAFE)
|
|||||||
ADD_DEFINITIONS(-DGIT_THREADS)
|
ADD_DEFINITIONS(-DGIT_THREADS)
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
|
IF (PERF_STATS)
|
||||||
|
ADD_DEFINITIONS(-DGIT_PERF)
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
ADD_DEFINITIONS(-D_FILE_OFFSET_BITS=64)
|
ADD_DEFINITIONS(-D_FILE_OFFSET_BITS=64)
|
||||||
|
|
||||||
# Collect sourcefiles
|
# Collect sourcefiles
|
||||||
|
@ -185,8 +185,7 @@ static bool checkout_is_workdir_modified(
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (git_diff__oid_for_file(
|
if (git_diff__oid_for_file(
|
||||||
data->repo, wditem->path, wditem->mode,
|
&oid, data->diff, wditem->path, wditem->mode, wditem->file_size) < 0)
|
||||||
wditem->file_size, &oid) < 0)
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return (git_oid__cmp(&baseitem->id, &oid) != 0);
|
return (git_oid__cmp(&baseitem->id, &oid) != 0);
|
||||||
|
79
src/diff.c
79
src/diff.c
@ -510,26 +510,31 @@ void git_diff_addref(git_diff *diff)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int git_diff__oid_for_file(
|
int git_diff__oid_for_file(
|
||||||
git_repository *repo,
|
git_oid *out,
|
||||||
|
git_diff *diff,
|
||||||
const char *path,
|
const char *path,
|
||||||
uint16_t mode,
|
uint16_t mode,
|
||||||
git_off_t size,
|
git_off_t size)
|
||||||
git_oid *oid)
|
|
||||||
{
|
{
|
||||||
int result = 0;
|
int error = 0;
|
||||||
git_buf full_path = GIT_BUF_INIT;
|
git_buf full_path = GIT_BUF_INIT;
|
||||||
|
git_filter_list *fl = NULL;
|
||||||
|
|
||||||
|
memset(out, 0, sizeof(*out));
|
||||||
|
|
||||||
if (git_buf_joinpath(
|
if (git_buf_joinpath(
|
||||||
&full_path, git_repository_workdir(repo), path) < 0)
|
&full_path, git_repository_workdir(diff->repo), path) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (!mode) {
|
if (!mode) {
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
|
||||||
if (p_stat(path, &st) < 0) {
|
GIT_PERF_INC(diff->stat_calls);
|
||||||
giterr_set(GITERR_OS, "Could not stat '%s'", path);
|
|
||||||
result = -1;
|
if (p_stat(full_path.ptr, &st) < 0) {
|
||||||
goto cleanup;
|
error = git_path_set_error(errno, path, "stat");
|
||||||
|
git_buf_free(&full_path);
|
||||||
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
mode = st.st_mode;
|
mode = st.st_mode;
|
||||||
@ -540,46 +545,43 @@ int git_diff__oid_for_file(
|
|||||||
if (S_ISGITLINK(mode)) {
|
if (S_ISGITLINK(mode)) {
|
||||||
git_submodule *sm;
|
git_submodule *sm;
|
||||||
|
|
||||||
memset(oid, 0, sizeof(*oid));
|
GIT_PERF_INC(diff->submodule_lookups);
|
||||||
|
|
||||||
if (!git_submodule_lookup(&sm, repo, path)) {
|
if (!git_submodule_lookup(&sm, diff->repo, path)) {
|
||||||
const git_oid *sm_oid = git_submodule_wd_id(sm);
|
const git_oid *sm_oid = git_submodule_wd_id(sm);
|
||||||
if (sm_oid)
|
if (sm_oid)
|
||||||
git_oid_cpy(oid, sm_oid);
|
git_oid_cpy(out, sm_oid);
|
||||||
git_submodule_free(sm);
|
git_submodule_free(sm);
|
||||||
} else {
|
} else {
|
||||||
/* if submodule lookup failed probably just in an intermediate
|
/* if submodule lookup failed probably just in an intermediate
|
||||||
* state where some init hasn't happened, so ignore the error
|
* state where some init hasn't happened, so ignore the error
|
||||||
*/
|
*/
|
||||||
giterr_clear();
|
giterr_clear();
|
||||||
memset(oid, 0, sizeof(*oid));
|
|
||||||
}
|
}
|
||||||
} else if (S_ISLNK(mode)) {
|
} else if (S_ISLNK(mode)) {
|
||||||
result = git_odb__hashlink(oid, full_path.ptr);
|
GIT_PERF_INC(diff->oid_calculations);
|
||||||
|
error = git_odb__hashlink(out, full_path.ptr);
|
||||||
} else if (!git__is_sizet(size)) {
|
} else if (!git__is_sizet(size)) {
|
||||||
giterr_set(GITERR_OS, "File size overflow (for 32-bits) on '%s'", path);
|
giterr_set(GITERR_OS, "File size overflow (for 32-bits) on '%s'", path);
|
||||||
result = -1;
|
error = -1;
|
||||||
} else {
|
} else if (!(error = git_filter_list_load(
|
||||||
git_filter_list *fl = NULL;
|
&fl, diff->repo, NULL, path, GIT_FILTER_TO_ODB)))
|
||||||
|
{
|
||||||
result = git_filter_list_load(&fl, repo, NULL, path, GIT_FILTER_TO_ODB);
|
int fd = git_futils_open_ro(full_path.ptr);
|
||||||
if (!result) {
|
if (fd < 0)
|
||||||
int fd = git_futils_open_ro(full_path.ptr);
|
error = fd;
|
||||||
if (fd < 0)
|
else {
|
||||||
result = fd;
|
GIT_PERF_INC(diff->oid_calculations);
|
||||||
else {
|
error = git_odb__hashfd_filtered(
|
||||||
result = git_odb__hashfd_filtered(
|
out, fd, (size_t)size, GIT_OBJ_BLOB, fl);
|
||||||
oid, fd, (size_t)size, GIT_OBJ_BLOB, fl);
|
p_close(fd);
|
||||||
p_close(fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
git_filter_list_free(fl);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
git_filter_list_free(fl);
|
||||||
}
|
}
|
||||||
|
|
||||||
cleanup:
|
|
||||||
git_buf_free(&full_path);
|
git_buf_free(&full_path);
|
||||||
return result;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool diff_time_eq(
|
static bool diff_time_eq(
|
||||||
@ -617,6 +619,8 @@ static int maybe_modified_submodule(
|
|||||||
ign == GIT_SUBMODULE_IGNORE_ALL)
|
ign == GIT_SUBMODULE_IGNORE_ALL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
GIT_PERF_INC(diff->submodule_lookups);
|
||||||
|
|
||||||
if ((error = git_submodule_lookup(
|
if ((error = git_submodule_lookup(
|
||||||
&sub, diff->repo, info->nitem->path)) < 0) {
|
&sub, diff->repo, info->nitem->path)) < 0) {
|
||||||
|
|
||||||
@ -748,8 +752,8 @@ static int maybe_modified(
|
|||||||
*/
|
*/
|
||||||
if (status == GIT_DELTA_MODIFIED && git_oid_iszero(&nitem->id)) {
|
if (status == GIT_DELTA_MODIFIED && git_oid_iszero(&nitem->id)) {
|
||||||
if (git_oid_iszero(&noid)) {
|
if (git_oid_iszero(&noid)) {
|
||||||
if ((error = git_diff__oid_for_file(diff->repo,
|
if ((error = git_diff__oid_for_file(&noid,
|
||||||
nitem->path, nitem->mode, nitem->file_size, &noid)) < 0)
|
diff, nitem->path, nitem->mode, nitem->file_size)) < 0)
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -914,6 +918,8 @@ static int handle_unmatched_new_item(
|
|||||||
delta_type = GIT_DELTA_ADDED;
|
delta_type = GIT_DELTA_ADDED;
|
||||||
|
|
||||||
else if (nitem->mode == GIT_FILEMODE_COMMIT) {
|
else if (nitem->mode == GIT_FILEMODE_COMMIT) {
|
||||||
|
GIT_PERF_INC(diff->submodule_lookups);
|
||||||
|
|
||||||
/* ignore things that are not actual submodules */
|
/* ignore things that are not actual submodules */
|
||||||
if (git_submodule_lookup(NULL, info->repo, nitem->path) != 0) {
|
if (git_submodule_lookup(NULL, info->repo, nitem->path) != 0) {
|
||||||
giterr_clear();
|
giterr_clear();
|
||||||
@ -1066,6 +1072,11 @@ int git_diff__from_iterators(
|
|||||||
error = 0;
|
error = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GIT_PERF_ADD(diff->stat_calls, old_iter->stat_calls);
|
||||||
|
GIT_PERF_ADD(diff->stat_calls, new_iter->stat_calls);
|
||||||
|
GIT_PERF_ADD(diff->submodule_lookups, old_iter->submodule_lookups);
|
||||||
|
GIT_PERF_ADD(diff->submodule_lookups, new_iter->submodule_lookups);
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
if (!error)
|
if (!error)
|
||||||
*diff_ptr = diff;
|
*diff_ptr = diff;
|
||||||
|
@ -62,6 +62,11 @@ struct git_diff {
|
|||||||
git_iterator_type_t old_src;
|
git_iterator_type_t old_src;
|
||||||
git_iterator_type_t new_src;
|
git_iterator_type_t new_src;
|
||||||
uint32_t diffcaps;
|
uint32_t diffcaps;
|
||||||
|
#ifdef GIT_PERF
|
||||||
|
size_t stat_calls;
|
||||||
|
size_t oid_calculations;
|
||||||
|
size_t submodule_lookups;
|
||||||
|
#endif
|
||||||
|
|
||||||
int (*strcomp)(const char *, const char *);
|
int (*strcomp)(const char *, const char *);
|
||||||
int (*strncomp)(const char *, const char *, size_t);
|
int (*strncomp)(const char *, const char *, size_t);
|
||||||
@ -90,7 +95,7 @@ extern int git_diff_delta__format_file_header(
|
|||||||
int oid_strlen);
|
int oid_strlen);
|
||||||
|
|
||||||
extern int git_diff__oid_for_file(
|
extern int git_diff__oid_for_file(
|
||||||
git_repository *, const char *, uint16_t, git_off_t, git_oid *);
|
git_oid *oit, git_diff *, const char *, uint16_t, git_off_t);
|
||||||
|
|
||||||
extern int git_diff__from_iterators(
|
extern int git_diff__from_iterators(
|
||||||
git_diff **diff_ptr,
|
git_diff **diff_ptr,
|
||||||
|
@ -574,14 +574,14 @@ static int similarity_measure(
|
|||||||
if (exact_match) {
|
if (exact_match) {
|
||||||
if (git_oid_iszero(&a_file->id) &&
|
if (git_oid_iszero(&a_file->id) &&
|
||||||
diff->old_src == GIT_ITERATOR_TYPE_WORKDIR &&
|
diff->old_src == GIT_ITERATOR_TYPE_WORKDIR &&
|
||||||
!git_diff__oid_for_file(diff->repo, a_file->path,
|
!git_diff__oid_for_file(&a_file->id,
|
||||||
a_file->mode, a_file->size, &a_file->id))
|
diff, a_file->path, a_file->mode, a_file->size))
|
||||||
a_file->flags |= GIT_DIFF_FLAG_VALID_ID;
|
a_file->flags |= GIT_DIFF_FLAG_VALID_ID;
|
||||||
|
|
||||||
if (git_oid_iszero(&b_file->id) &&
|
if (git_oid_iszero(&b_file->id) &&
|
||||||
diff->new_src == GIT_ITERATOR_TYPE_WORKDIR &&
|
diff->new_src == GIT_ITERATOR_TYPE_WORKDIR &&
|
||||||
!git_diff__oid_for_file(diff->repo, b_file->path,
|
!git_diff__oid_for_file(&b_file->id,
|
||||||
b_file->mode, b_file->size, &b_file->id))
|
diff, b_file->path, b_file->mode, b_file->size))
|
||||||
b_file->flags |= GIT_DIFF_FLAG_VALID_ID;
|
b_file->flags |= GIT_DIFF_FLAG_VALID_ID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1017,6 +1017,8 @@ static int fs_iterator__expand_dir(fs_iterator *fi)
|
|||||||
return GIT_ENOTFOUND;
|
return GIT_ENOTFOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GIT_PERF_ADD(fi->base.stat_calls, ff->entries.length);
|
||||||
|
|
||||||
fs_iterator__seek_frame_start(fi, ff);
|
fs_iterator__seek_frame_start(fi, ff);
|
||||||
|
|
||||||
ff->next = fi->stack;
|
ff->next = fi->stack;
|
||||||
@ -1304,9 +1306,11 @@ static int workdir_iterator__enter_dir(fs_iterator *fi)
|
|||||||
|
|
||||||
/* convert submodules to GITLINK and remove trailing slashes */
|
/* convert submodules to GITLINK and remove trailing slashes */
|
||||||
git_vector_foreach(&ff->entries, pos, entry) {
|
git_vector_foreach(&ff->entries, pos, entry) {
|
||||||
if (S_ISDIR(entry->st.st_mode) &&
|
if (!S_ISDIR(entry->st.st_mode))
|
||||||
git_submodule__is_submodule(fi->base.repo, entry->path))
|
continue;
|
||||||
{
|
|
||||||
|
GIT_PERF_INC(fi->base.submodule_lookups);
|
||||||
|
if (git_submodule__is_submodule(fi->base.repo, entry->path)) {
|
||||||
entry->st.st_mode = GIT_FILEMODE_COMMIT;
|
entry->st.st_mode = GIT_FILEMODE_COMMIT;
|
||||||
entry->path_len--;
|
entry->path_len--;
|
||||||
entry->path[entry->path_len] = '\0';
|
entry->path[entry->path_len] = '\0';
|
||||||
|
@ -53,6 +53,10 @@ struct git_iterator {
|
|||||||
char *end;
|
char *end;
|
||||||
int (*prefixcomp)(const char *str, const char *prefix);
|
int (*prefixcomp)(const char *str, const char *prefix);
|
||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
|
#ifdef GIT_PERF
|
||||||
|
size_t stat_calls;
|
||||||
|
size_t submodule_lookups;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
extern int git_iterator_for_nothing(
|
extern int git_iterator_for_nothing(
|
||||||
|
@ -81,15 +81,15 @@ static unsigned int workdir_delta2status(
|
|||||||
if (git_oid_iszero(&idx2wd->old_file.id) &&
|
if (git_oid_iszero(&idx2wd->old_file.id) &&
|
||||||
diff->old_src == GIT_ITERATOR_TYPE_WORKDIR &&
|
diff->old_src == GIT_ITERATOR_TYPE_WORKDIR &&
|
||||||
!git_diff__oid_for_file(
|
!git_diff__oid_for_file(
|
||||||
diff->repo, idx2wd->old_file.path, idx2wd->old_file.mode,
|
&idx2wd->old_file.id, diff, idx2wd->old_file.path,
|
||||||
idx2wd->old_file.size, &idx2wd->old_file.id))
|
idx2wd->old_file.mode, idx2wd->old_file.size))
|
||||||
idx2wd->old_file.flags |= GIT_DIFF_FLAG_VALID_ID;
|
idx2wd->old_file.flags |= GIT_DIFF_FLAG_VALID_ID;
|
||||||
|
|
||||||
if (git_oid_iszero(&idx2wd->new_file.id) &&
|
if (git_oid_iszero(&idx2wd->new_file.id) &&
|
||||||
diff->new_src == GIT_ITERATOR_TYPE_WORKDIR &&
|
diff->new_src == GIT_ITERATOR_TYPE_WORKDIR &&
|
||||||
!git_diff__oid_for_file(
|
!git_diff__oid_for_file(
|
||||||
diff->repo, idx2wd->new_file.path, idx2wd->new_file.mode,
|
&idx2wd->new_file.id, diff, idx2wd->new_file.path,
|
||||||
idx2wd->new_file.size, &idx2wd->new_file.id))
|
idx2wd->new_file.mode, idx2wd->new_file.size))
|
||||||
idx2wd->new_file.flags |= GIT_DIFF_FLAG_VALID_ID;
|
idx2wd->new_file.flags |= GIT_DIFF_FLAG_VALID_ID;
|
||||||
|
|
||||||
if (!git_oid_equal(&idx2wd->old_file.id, &idx2wd->new_file.id))
|
if (!git_oid_equal(&idx2wd->old_file.id, &idx2wd->new_file.id))
|
||||||
|
@ -436,4 +436,12 @@ GIT_INLINE(double) git__timer(void)
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef GIT_PERF
|
||||||
|
# define GIT_PERF_INC(counter) (counter)++
|
||||||
|
# define GIT_PERF_ADD(counter,val) (counter) += (val)
|
||||||
|
#else
|
||||||
|
# define GIT_PERF_INC(counter) 0
|
||||||
|
# define GIT_PERF_ADD(counter,val) 0
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* INCLUDE_util_h__ */
|
#endif /* INCLUDE_util_h__ */
|
||||||
|
@ -2,6 +2,11 @@
|
|||||||
#include "diff_helpers.h"
|
#include "diff_helpers.h"
|
||||||
#include "repository.h"
|
#include "repository.h"
|
||||||
|
|
||||||
|
#ifdef GIT_PERF
|
||||||
|
/* access to diff usage statistics */
|
||||||
|
# include "diff.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
static git_repository *g_repo = NULL;
|
static git_repository *g_repo = NULL;
|
||||||
|
|
||||||
void test_diff_workdir__initialize(void)
|
void test_diff_workdir__initialize(void)
|
||||||
@ -58,6 +63,13 @@ void test_diff_workdir__to_index(void)
|
|||||||
cl_assert_equal_i(5, exp.line_ctxt);
|
cl_assert_equal_i(5, exp.line_ctxt);
|
||||||
cl_assert_equal_i(4, exp.line_adds);
|
cl_assert_equal_i(4, exp.line_adds);
|
||||||
cl_assert_equal_i(5, exp.line_dels);
|
cl_assert_equal_i(5, exp.line_dels);
|
||||||
|
|
||||||
|
#ifdef GIT_PERF
|
||||||
|
cl_assert_equal_sz(
|
||||||
|
13 /* in root */ + 3 /* in subdir */, diff->stat_calls);
|
||||||
|
cl_assert_equal_sz(9, diff->oid_calculations);
|
||||||
|
cl_assert_equal_sz(2, diff->submodule_lookups);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
git_diff_free(diff);
|
git_diff_free(diff);
|
||||||
|
Loading…
Reference in New Issue
Block a user