Commit 240f4af3 by Russell Belfer

Add build option for diff internal statistics

parent 6a1ca96e
......@@ -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);
......
......@@ -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);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment