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_SSH "Link with libssh to enable SSH support" ON )
|
||||
OPTION( VALGRIND "Configure build for valgrind" OFF )
|
||||
OPTION( PERF_STATS "Internally track performance data" OFF )
|
||||
|
||||
IF(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
|
||||
SET( USE_ICONV ON )
|
||||
@ -352,6 +353,10 @@ IF (THREADSAFE)
|
||||
ADD_DEFINITIONS(-DGIT_THREADS)
|
||||
ENDIF()
|
||||
|
||||
IF (PERF_STATS)
|
||||
ADD_DEFINITIONS(-DGIT_PERF)
|
||||
ENDIF()
|
||||
|
||||
ADD_DEFINITIONS(-D_FILE_OFFSET_BITS=64)
|
||||
|
||||
# Collect sourcefiles
|
||||
|
@ -185,8 +185,7 @@ static bool checkout_is_workdir_modified(
|
||||
return true;
|
||||
|
||||
if (git_diff__oid_for_file(
|
||||
data->repo, wditem->path, wditem->mode,
|
||||
wditem->file_size, &oid) < 0)
|
||||
&oid, data->diff, wditem->path, wditem->mode, wditem->file_size) < 0)
|
||||
return false;
|
||||
|
||||
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(
|
||||
git_repository *repo,
|
||||
git_oid *out,
|
||||
git_diff *diff,
|
||||
const char *path,
|
||||
uint16_t mode,
|
||||
git_off_t size,
|
||||
git_oid *oid)
|
||||
git_off_t size)
|
||||
{
|
||||
int result = 0;
|
||||
int error = 0;
|
||||
git_buf full_path = GIT_BUF_INIT;
|
||||
git_filter_list *fl = NULL;
|
||||
|
||||
memset(out, 0, sizeof(*out));
|
||||
|
||||
if (git_buf_joinpath(
|
||||
&full_path, git_repository_workdir(repo), path) < 0)
|
||||
&full_path, git_repository_workdir(diff->repo), path) < 0)
|
||||
return -1;
|
||||
|
||||
if (!mode) {
|
||||
struct stat st;
|
||||
|
||||
if (p_stat(path, &st) < 0) {
|
||||
giterr_set(GITERR_OS, "Could not stat '%s'", path);
|
||||
result = -1;
|
||||
goto cleanup;
|
||||
GIT_PERF_INC(diff->stat_calls);
|
||||
|
||||
if (p_stat(full_path.ptr, &st) < 0) {
|
||||
error = git_path_set_error(errno, path, "stat");
|
||||
git_buf_free(&full_path);
|
||||
return error;
|
||||
}
|
||||
|
||||
mode = st.st_mode;
|
||||
@ -540,46 +545,43 @@ int git_diff__oid_for_file(
|
||||
if (S_ISGITLINK(mode)) {
|
||||
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);
|
||||
if (sm_oid)
|
||||
git_oid_cpy(oid, sm_oid);
|
||||
git_oid_cpy(out, sm_oid);
|
||||
git_submodule_free(sm);
|
||||
} else {
|
||||
/* if submodule lookup failed probably just in an intermediate
|
||||
* state where some init hasn't happened, so ignore the error
|
||||
*/
|
||||
giterr_clear();
|
||||
memset(oid, 0, sizeof(*oid));
|
||||
}
|
||||
} 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)) {
|
||||
giterr_set(GITERR_OS, "File size overflow (for 32-bits) on '%s'", path);
|
||||
result = -1;
|
||||
} else {
|
||||
git_filter_list *fl = NULL;
|
||||
|
||||
result = git_filter_list_load(&fl, repo, NULL, path, GIT_FILTER_TO_ODB);
|
||||
if (!result) {
|
||||
int fd = git_futils_open_ro(full_path.ptr);
|
||||
if (fd < 0)
|
||||
result = fd;
|
||||
else {
|
||||
result = git_odb__hashfd_filtered(
|
||||
oid, fd, (size_t)size, GIT_OBJ_BLOB, fl);
|
||||
p_close(fd);
|
||||
}
|
||||
|
||||
git_filter_list_free(fl);
|
||||
error = -1;
|
||||
} else if (!(error = git_filter_list_load(
|
||||
&fl, diff->repo, NULL, path, GIT_FILTER_TO_ODB)))
|
||||
{
|
||||
int fd = git_futils_open_ro(full_path.ptr);
|
||||
if (fd < 0)
|
||||
error = fd;
|
||||
else {
|
||||
GIT_PERF_INC(diff->oid_calculations);
|
||||
error = git_odb__hashfd_filtered(
|
||||
out, fd, (size_t)size, GIT_OBJ_BLOB, fl);
|
||||
p_close(fd);
|
||||
}
|
||||
|
||||
git_filter_list_free(fl);
|
||||
}
|
||||
|
||||
cleanup:
|
||||
git_buf_free(&full_path);
|
||||
return result;
|
||||
return error;
|
||||
}
|
||||
|
||||
static bool diff_time_eq(
|
||||
@ -617,6 +619,8 @@ static int maybe_modified_submodule(
|
||||
ign == GIT_SUBMODULE_IGNORE_ALL)
|
||||
return 0;
|
||||
|
||||
GIT_PERF_INC(diff->submodule_lookups);
|
||||
|
||||
if ((error = git_submodule_lookup(
|
||||
&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 (git_oid_iszero(&noid)) {
|
||||
if ((error = git_diff__oid_for_file(diff->repo,
|
||||
nitem->path, nitem->mode, nitem->file_size, &noid)) < 0)
|
||||
if ((error = git_diff__oid_for_file(&noid,
|
||||
diff, nitem->path, nitem->mode, nitem->file_size)) < 0)
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -914,6 +918,8 @@ static int handle_unmatched_new_item(
|
||||
delta_type = GIT_DELTA_ADDED;
|
||||
|
||||
else if (nitem->mode == GIT_FILEMODE_COMMIT) {
|
||||
GIT_PERF_INC(diff->submodule_lookups);
|
||||
|
||||
/* ignore things that are not actual submodules */
|
||||
if (git_submodule_lookup(NULL, info->repo, nitem->path) != 0) {
|
||||
giterr_clear();
|
||||
@ -1066,6 +1072,11 @@ int git_diff__from_iterators(
|
||||
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:
|
||||
if (!error)
|
||||
*diff_ptr = diff;
|
||||
|
@ -62,6 +62,11 @@ struct git_diff {
|
||||
git_iterator_type_t old_src;
|
||||
git_iterator_type_t new_src;
|
||||
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 (*strncomp)(const char *, const char *, size_t);
|
||||
@ -90,7 +95,7 @@ extern int git_diff_delta__format_file_header(
|
||||
int oid_strlen);
|
||||
|
||||
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(
|
||||
git_diff **diff_ptr,
|
||||
|
@ -574,14 +574,14 @@ static int similarity_measure(
|
||||
if (exact_match) {
|
||||
if (git_oid_iszero(&a_file->id) &&
|
||||
diff->old_src == GIT_ITERATOR_TYPE_WORKDIR &&
|
||||
!git_diff__oid_for_file(diff->repo, a_file->path,
|
||||
a_file->mode, a_file->size, &a_file->id))
|
||||
!git_diff__oid_for_file(&a_file->id,
|
||||
diff, a_file->path, a_file->mode, a_file->size))
|
||||
a_file->flags |= GIT_DIFF_FLAG_VALID_ID;
|
||||
|
||||
if (git_oid_iszero(&b_file->id) &&
|
||||
diff->new_src == GIT_ITERATOR_TYPE_WORKDIR &&
|
||||
!git_diff__oid_for_file(diff->repo, b_file->path,
|
||||
b_file->mode, b_file->size, &b_file->id))
|
||||
!git_diff__oid_for_file(&b_file->id,
|
||||
diff, b_file->path, b_file->mode, b_file->size))
|
||||
b_file->flags |= GIT_DIFF_FLAG_VALID_ID;
|
||||
}
|
||||
|
||||
|
@ -1017,6 +1017,8 @@ static int fs_iterator__expand_dir(fs_iterator *fi)
|
||||
return GIT_ENOTFOUND;
|
||||
}
|
||||
|
||||
GIT_PERF_ADD(fi->base.stat_calls, ff->entries.length);
|
||||
|
||||
fs_iterator__seek_frame_start(fi, ff);
|
||||
|
||||
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 */
|
||||
git_vector_foreach(&ff->entries, pos, entry) {
|
||||
if (S_ISDIR(entry->st.st_mode) &&
|
||||
git_submodule__is_submodule(fi->base.repo, entry->path))
|
||||
{
|
||||
if (!S_ISDIR(entry->st.st_mode))
|
||||
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->path_len--;
|
||||
entry->path[entry->path_len] = '\0';
|
||||
|
@ -53,6 +53,10 @@ struct git_iterator {
|
||||
char *end;
|
||||
int (*prefixcomp)(const char *str, const char *prefix);
|
||||
unsigned int flags;
|
||||
#ifdef GIT_PERF
|
||||
size_t stat_calls;
|
||||
size_t submodule_lookups;
|
||||
#endif
|
||||
};
|
||||
|
||||
extern int git_iterator_for_nothing(
|
||||
|
@ -81,15 +81,15 @@ static unsigned int workdir_delta2status(
|
||||
if (git_oid_iszero(&idx2wd->old_file.id) &&
|
||||
diff->old_src == GIT_ITERATOR_TYPE_WORKDIR &&
|
||||
!git_diff__oid_for_file(
|
||||
diff->repo, idx2wd->old_file.path, idx2wd->old_file.mode,
|
||||
idx2wd->old_file.size, &idx2wd->old_file.id))
|
||||
&idx2wd->old_file.id, diff, idx2wd->old_file.path,
|
||||
idx2wd->old_file.mode, idx2wd->old_file.size))
|
||||
idx2wd->old_file.flags |= GIT_DIFF_FLAG_VALID_ID;
|
||||
|
||||
if (git_oid_iszero(&idx2wd->new_file.id) &&
|
||||
diff->new_src == GIT_ITERATOR_TYPE_WORKDIR &&
|
||||
!git_diff__oid_for_file(
|
||||
diff->repo, idx2wd->new_file.path, idx2wd->new_file.mode,
|
||||
idx2wd->new_file.size, &idx2wd->new_file.id))
|
||||
&idx2wd->new_file.id, diff, idx2wd->new_file.path,
|
||||
idx2wd->new_file.mode, idx2wd->new_file.size))
|
||||
idx2wd->new_file.flags |= GIT_DIFF_FLAG_VALID_ID;
|
||||
|
||||
if (!git_oid_equal(&idx2wd->old_file.id, &idx2wd->new_file.id))
|
||||
|
@ -436,4 +436,12 @@ GIT_INLINE(double) git__timer(void)
|
||||
|
||||
#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__ */
|
||||
|
@ -2,6 +2,11 @@
|
||||
#include "diff_helpers.h"
|
||||
#include "repository.h"
|
||||
|
||||
#ifdef GIT_PERF
|
||||
/* access to diff usage statistics */
|
||||
# include "diff.h"
|
||||
#endif
|
||||
|
||||
static git_repository *g_repo = NULL;
|
||||
|
||||
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(4, exp.line_adds);
|
||||
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);
|
||||
|
Loading…
Reference in New Issue
Block a user