[Pkg-owncloud-commits] [owncloud-client] 03/218: csync_exclude: Speed up siginificantly #3638
Sandro Knauß
hefee-guest at moszumanska.debian.org
Sat Oct 17 14:30:30 UTC 2015
This is an automated email from the git hooks/post-receive script.
hefee-guest pushed a commit to branch master
in repository owncloud-client.
commit 20f4ec6b6756ced80cfc92a5a891ec353b25055d
Author: Christian Kamm <mail at ckamm.de>
Date: Fri Aug 21 14:20:27 2015 +0200
csync_exclude: Speed up siginificantly #3638
The performance test indicates a speedup of around 3x for paths
with around 12 components.
---
csync/src/csync_exclude.c | 65 +++++++++++----------------
csync/tests/csync_tests/check_csync_exclude.c | 43 ++++++++++++++++++
2 files changed, 70 insertions(+), 38 deletions(-)
diff --git a/csync/src/csync_exclude.c b/csync/src/csync_exclude.c
index 7a29e37..42adfe8 100644
--- a/csync/src/csync_exclude.c
+++ b/csync/src/csync_exclude.c
@@ -191,7 +191,6 @@ CSYNC_EXCLUDE_TYPE csync_excluded_no_ctx(c_strlist_t *excludes, const char *path
const char *p = NULL;
char *bname = NULL;
char *dname = NULL;
- char *prev_dname = NULL;
char *conflict = NULL;
int rc = -1;
CSYNC_EXCLUDE_TYPE match = CSYNC_NOT_EXCLUDED;
@@ -340,54 +339,44 @@ CSYNC_EXCLUDE_TYPE csync_excluded_no_ctx(c_strlist_t *excludes, const char *path
}
}
- /* if still not excluded, check each component of the path */
+ /* if still not excluded, check each component and leading directory of the path */
if (match == CSYNC_NOT_EXCLUDED) {
- int trailing_component = 1;
- dname = c_dirname(path);
- bname = c_basename(path);
-
- if (bname == NULL || dname == NULL) {
- match = CSYNC_NOT_EXCLUDED;
- SAFE_FREE(bname);
- SAFE_FREE(dname);
- SAFE_FREE(pattern_stored);
- goto out;
- }
+ char *segmented_path = strdup(path);
+ size_t len = strlen(segmented_path);
+ bool check_segname = !match_dirs_only || filetype != CSYNC_FTW_TYPE_FILE;
+ for (int j = len; ; --j) {
+ // read backwards until a path separator
+ if (j != 0 && segmented_path[j-1] != '/') {
+ continue;
+ }
- /* Check each component of the path */
- do {
- /* Do not check the bname if its a file and the pattern matches dirs only. */
- if ( !(trailing_component == 1 /* it is the trailing component */
- && match_dirs_only /* but only directories are matched by the pattern */
- && filetype == CSYNC_FTW_TYPE_FILE) ) {
- /* Check the name component against the pattern */
- rc = csync_fnmatch(pattern, bname, 0);
+ // check 'basename', i.e. for "/foo/bar/fi" we'd check 'fi', 'bar', 'foo'
+ if (check_segname && segmented_path[j] != 0) {
+ rc = csync_fnmatch(pattern, segmented_path + j, 0);
if (rc == 0) {
match = type;
+ break;
}
}
- if (!(c_streq(dname, ".") || c_streq(dname, "/"))) {
- rc = csync_fnmatch(pattern, dname, 0);
- if (rc == 0) {
- match = type;
- }
+ check_segname = true;
+
+ if (j == 0) {
+ break;
+ }
+
+ // check 'dirname', i.e. for "/foo/bar/fi" we'd check '/foo/bar', '/foo'
+ segmented_path[j-1] = '\0';
+ rc = csync_fnmatch(pattern, segmented_path, 0);
+ if (rc == 0) {
+ match = type;
+ break;
}
- trailing_component = 0;
- prev_dname = dname;
- SAFE_FREE(bname);
- bname = c_basename(prev_dname);
- dname = c_dirname(prev_dname);
- SAFE_FREE(prev_dname);
-
- } while( match == CSYNC_NOT_EXCLUDED && !c_streq(dname, ".")
- && !c_streq(dname, "/") );
+ }
+ SAFE_FREE(segmented_path);
}
SAFE_FREE(pattern_stored);
- SAFE_FREE(bname);
- SAFE_FREE(dname);
}
-
out:
return match;
diff --git a/csync/tests/csync_tests/check_csync_exclude.c b/csync/tests/csync_tests/check_csync_exclude.c
index 94430ea..b0b57ff 100644
--- a/csync/tests/csync_tests/check_csync_exclude.c
+++ b/csync/tests/csync_tests/check_csync_exclude.c
@@ -19,6 +19,7 @@
*/
#include "config_csync.h"
#include <string.h>
+#include <time.h>
#include "torture.h"
@@ -170,8 +171,25 @@ static void check_csync_pathes(void **state)
rc = csync_excluded(csync, "meep/excl", CSYNC_FTW_TYPE_DIR);
assert_int_equal(rc, CSYNC_FILE_EXCLUDE_LIST);
+ rc = csync_excluded(csync, "meep/excl/file", CSYNC_FTW_TYPE_FILE);
+ assert_int_equal(rc, CSYNC_FILE_EXCLUDE_LIST);
+
rc = csync_excluded(csync, "/excl", CSYNC_FTW_TYPE_FILE);
assert_int_equal(rc, CSYNC_NOT_EXCLUDED);
+
+ _csync_exclude_add(&csync->excludes, "/excludepath/withsubdir");
+
+ rc = csync_excluded(csync, "/excludepath/withsubdir", CSYNC_FTW_TYPE_DIR);
+ assert_int_equal(rc, CSYNC_FILE_EXCLUDE_LIST);
+
+ rc = csync_excluded(csync, "/excludepath/withsubdir", CSYNC_FTW_TYPE_FILE);
+ assert_int_equal(rc, CSYNC_FILE_EXCLUDE_LIST);
+
+ rc = csync_excluded(csync, "/excludepath/withsubdir2", CSYNC_FTW_TYPE_DIR);
+ assert_int_equal(rc, CSYNC_NOT_EXCLUDED);
+
+ rc = csync_excluded(csync, "/excludepath/withsubdir/foo", CSYNC_FTW_TYPE_DIR);
+ assert_int_equal(rc, CSYNC_FILE_EXCLUDE_LIST);
}
static void check_csync_is_windows_reserved_word() {
@@ -190,7 +208,31 @@ static void check_csync_is_windows_reserved_word() {
assert_true(csync_is_windows_reserved_word("Z:"));
assert_true(csync_is_windows_reserved_word("M:"));
assert_true(csync_is_windows_reserved_word("m:"));
+}
+
+static void check_csync_excluded_performance(void **state)
+{
+ CSYNC *csync = *state;
+
+ const int N = 10000;
+ int totalRc = 0;
+
+ // Being able to use QElapsedTimer for measurement would be nice...
+ struct timeval before, after;
+ gettimeofday(&before, 0);
+
+ for (int i = 0; i < N; ++i) {
+ totalRc += csync_excluded(csync, "/this/is/quite/a/long/path/with/many/components", CSYNC_FTW_TYPE_DIR);
+ totalRc += csync_excluded(csync, "/1/2/3/4/5/6/7/8/9/10/11/12/13/14/15/16/17/18/19/20/21/22/23/24/25/26/27/29", CSYNC_FTW_TYPE_FILE);
+ }
+ assert_int_equal(totalRc, CSYNC_NOT_EXCLUDED); // mainly to avoid optimization
+
+ gettimeofday(&after, 0);
+ const double total = (after.tv_sec - before.tv_sec)
+ + (after.tv_usec - before.tv_usec) / 1.0e6;
+ const double perCallMs = total / 2 / N * 1000;
+ printf("csync_excluded: %f ms per call\n", perCallMs);
}
int torture_run_tests(void)
@@ -201,6 +243,7 @@ int torture_run_tests(void)
unit_test_setup_teardown(check_csync_excluded, setup_init, teardown),
unit_test_setup_teardown(check_csync_pathes, setup_init, teardown),
unit_test_setup_teardown(check_csync_is_windows_reserved_word, setup_init, teardown),
+ unit_test_setup_teardown(check_csync_excluded_performance, setup_init, teardown),
};
return run_tests(tests);
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-owncloud/owncloud-client.git
More information about the Pkg-owncloud-commits
mailing list