[SCM] Samba Shared Repository - branch v4-0-test updated - release-4-0-0alpha3-265-gca7e4d9

James Peach jpeach at samba.org
Mon Apr 21 22:12:04 GMT 2008


The branch, v4-0-test has been updated
       via  ca7e4d9166a7cb10495cf3ecd9c4e72103fbec30 (commit)
      from  8fa23fac516dbf4c8245c1d009e81f02a6341775 (commit)

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=v4-0-test


- Log -----------------------------------------------------------------
commit ca7e4d9166a7cb10495cf3ecd9c4e72103fbec30
Author: James Peach <jpeach at apple.com>
Date:   Mon Apr 21 15:09:43 2008 -0700

    smbtorture: Add RAW-BENCH-LOOKUP micro-benchmark.
    
    This test samples the lookup rate for a non-existant filename in a
    directory, while varying the number of files in the directory. The
    lookup rate should continue to approximate the lookup rate for the
    empty directory case.

-----------------------------------------------------------------------

Summary of changes:
 source/torture/config.mk        |    1 +
 source/torture/raw/lookuprate.c |  319 +++++++++++++++++++++++++++++++++++++++
 source/torture/raw/raw.c        |    2 +
 3 files changed, 322 insertions(+), 0 deletions(-)
 create mode 100644 source/torture/raw/lookuprate.c


Changeset truncated at 500 lines:

diff --git a/source/torture/config.mk b/source/torture/config.mk
index 2f3fa38..1565797 100644
--- a/source/torture/config.mk
+++ b/source/torture/config.mk
@@ -86,6 +86,7 @@ TORTURE_RAW_OBJ_FILES = $(addprefix torture/raw/, \
 		lock.o \
 		pingpong.o \
 		lockbench.o \
+		lookuprate.o \
 		openbench.o \
 		rename.o \
 		eas.o \
diff --git a/source/torture/raw/lookuprate.c b/source/torture/raw/lookuprate.c
new file mode 100644
index 0000000..4b505dc
--- /dev/null
+++ b/source/torture/raw/lookuprate.c
@@ -0,0 +1,319 @@
+/*
+   File lookup rate test.
+
+   Copyright (C) James Peach 2006
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "param/param.h"
+#include "system/filesys.h"
+#include "torture/torture.h"
+#include "torture/basic/proto.h"
+#include "libcli/libcli.h"
+#include "lib/cmdline/popt_common.h"
+#include "auth/credentials/credentials.h"
+
+#define BASEDIR "\\lookuprate"
+#define MISSINGNAME BASEDIR "\\foo"
+
+#define FUZZ_PERCENT 10
+
+#define usec_to_sec(s) ((s) / 1000000)
+#define sec_to_usec(s) ((s) * 1000000)
+
+struct rate_record
+{
+    unsigned	dirent_count;
+    unsigned	querypath_persec;
+    unsigned	findfirst_persec;
+};
+
+static struct rate_record records[] =
+{
+    { 0, 0, 0 },	/* Base (optimal) lookup rate. */
+    { 100, 0, 0},
+    { 1000, 0, 0},
+    { 10000, 0, 0},
+    { 100000, 0, 0}
+};
+
+typedef NTSTATUS lookup_function(struct smbcli_tree *tree, const char * path);
+
+/* Test whether rhs is within fuzz% of lhs. */
+static bool fuzzily_equal(unsigned lhs, unsigned rhs, int percent)
+{
+	double fuzz = (double)lhs * (double)percent/100.0;
+
+	if (((double)rhs >= ((double)lhs - fuzz)) &&
+	    ((double)rhs <= ((double)lhs + fuzz))) {
+		return true;
+	}
+
+	return false;
+
+}
+
+static NTSTATUS fill_directory(struct smbcli_tree *tree,
+	    const char * path, unsigned count)
+{
+	NTSTATUS	status;
+	char		*fname = NULL;
+	unsigned	i;
+	unsigned	current;
+
+	struct timeval start;
+	struct timeval now;
+
+	status = smbcli_mkdir(tree, path);
+	if (!NT_STATUS_IS_OK(status)) {
+		return status;
+	}
+
+	printf("filling directory %s with %u files... ", path, count);
+	fflush(stdout);
+
+	current = random();
+	start = timeval_current();
+
+	for (i = 0; i < count; ++i) {
+		int fnum;
+
+		++current;
+		fname = talloc_asprintf(NULL, "%s\\fill%u",
+				    path, current);
+
+		fnum = smbcli_open(tree, fname, O_RDONLY|O_CREAT,
+				OPENX_MODE_DENY_NONE);
+		if (fnum < 0) {
+			talloc_free(fname);
+			return smbcli_nt_error(tree);
+		}
+
+		smbcli_close(tree, fnum);
+		talloc_free(fname);
+	}
+
+	if (count) {
+		double rate;
+		now = timeval_current();
+		rate = (double)count / usec_to_sec((double)usec_time_diff(&now, &start));
+		printf("%u/sec\n", (unsigned)rate);
+	} else {
+		printf("done\n");
+	}
+
+	return NT_STATUS_OK;
+}
+
+static NTSTATUS squash_lookup_error(NTSTATUS status)
+{
+	if (NT_STATUS_IS_OK(status)) {
+		return NT_STATUS_OK;
+	}
+
+	/* We don't care if the file isn't there. */
+	if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
+		return NT_STATUS_OK;
+	}
+
+	if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
+		return NT_STATUS_OK;
+	}
+
+	if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_FILE)) {
+		return NT_STATUS_OK;
+	}
+
+	return status;
+}
+
+/* Look up a pathname using TRANS2_QUERY_PATH_INFORMATION. */
+static NTSTATUS querypath_lookup(struct smbcli_tree *tree, const char * path)
+{
+	NTSTATUS	status;
+	time_t		ftimes[3];
+	size_t		fsize;
+	uint16_t	fmode;
+
+	status = smbcli_qpathinfo(tree, path, &ftimes[0], &ftimes[1], &ftimes[2],
+			&fsize, &fmode);
+
+	return squash_lookup_error(status);
+}
+
+/* Look up a pathname using TRANS2_FIND_FIRST2. */
+static NTSTATUS findfirst_lookup(struct smbcli_tree *tree, const char * path)
+{
+	NTSTATUS status = NT_STATUS_OK;
+
+	if (smbcli_list(tree, path, 0, NULL, NULL) < 0) {
+		status = smbcli_nt_error(tree);
+	}
+
+	return squash_lookup_error(status);
+}
+
+static NTSTATUS lookup_rate_convert(struct smbcli_tree *tree,
+	lookup_function lookup, const char * path, unsigned * rate)
+{
+	NTSTATUS	status;
+
+	struct timeval	start;
+	struct timeval	now;
+	unsigned	count = 0;
+	int64_t		elapsed = 0;
+
+#define LOOKUP_PERIOD_SEC (2)
+
+	start = timeval_current();
+	while (elapsed < sec_to_usec(LOOKUP_PERIOD_SEC)) {
+
+		status = lookup(tree, path);
+		if (!NT_STATUS_IS_OK(status)) {
+			return status;
+		}
+
+		++count;
+		now = timeval_current();
+		elapsed = usec_time_diff(&now, &start);
+	}
+
+#undef LOOKUP_PERIOD_SEC
+
+	*rate = (unsigned)((double)count / (double)usec_to_sec(elapsed));
+	return NT_STATUS_OK;
+}
+
+static bool remove_working_directory(struct smbcli_tree *tree,
+		const char * path)
+{
+	int tries;
+
+	/* Using smbcli_deltree to delete a very large number of files
+	 * doesn't work against all servers. Work around this by
+	 * retrying.
+	 */
+	for (tries = 0; tries < 5; ) {
+		int ret;
+
+		ret = smbcli_deltree(tree, BASEDIR);
+		if (ret == -1) {
+			tries++;
+			printf("(%s) failed to deltree %s: %s\n",
+				__location__, BASEDIR,
+				smbcli_errstr(tree));
+			continue;
+		}
+
+		return true;
+	}
+
+	return false;
+
+}
+
+/* Verify that looking up a file name takes constant time.
+ *
+ * This test samples the lookup rate for a non-existant filename in a
+ * directory, while varying the number of files in the directory. The
+ * lookup rate should continue to approximate the lookup rate for the
+ * empty directory case.
+ */
+bool torture_bench_lookup(struct torture_context *torture)
+{
+	NTSTATUS	status;
+	bool		result = false;
+
+	int i, tries;
+	struct smbcli_state *cli = NULL;
+
+	if (!torture_open_connection(&cli, torture, 0)) {
+		goto done;
+	}
+
+	remove_working_directory(cli->tree, BASEDIR);
+
+	for (i = 0; i < ARRAY_SIZE(records); ++i) {
+		printf("testing lookup rate with %u directory entries\n",
+				records[i].dirent_count);
+
+		status = fill_directory(cli->tree, BASEDIR,
+				records[i].dirent_count);
+		if (!NT_STATUS_IS_OK(status)) {
+			printf("failed to fill directory: %s\n", nt_errstr(status));
+			goto done;
+		}
+
+		status = lookup_rate_convert(cli->tree, querypath_lookup,
+			MISSINGNAME, &records[i].querypath_persec);
+		if (!NT_STATUS_IS_OK(status)) {
+			printf("querypathinfo of %s failed: %s\n",
+				MISSINGNAME, nt_errstr(status));
+			goto done;
+		}
+
+		status = lookup_rate_convert(cli->tree, findfirst_lookup,
+			MISSINGNAME, &records[i].findfirst_persec);
+		if (!NT_STATUS_IS_OK(status)) {
+			printf("findfirst of %s failed: %s\n",
+				MISSINGNAME, nt_errstr(status));
+			goto done;
+		}
+
+		printf("entries = %u, querypath = %u/sec, findfirst = %u/sec\n",
+				records[i].dirent_count,
+				records[i].querypath_persec,
+				records[i].findfirst_persec);
+
+		if (!remove_working_directory(cli->tree, BASEDIR)) {
+			goto done;
+		}
+	}
+
+	/* Ok. We have run all our tests. Walk through the records we
+	 * accumulated and figure out whether the lookups took constant
+	 * time of not.
+	 */
+	for (i = 0; i < ARRAY_SIZE(records); ++i) {
+		if (!fuzzily_equal(records[0].querypath_persec,
+				    records[i].querypath_persec,
+				    FUZZ_PERCENT)) {
+			printf("querypath rate for %d entries differed by "
+				"more than %d%% from base rate\n",
+				records[i].dirent_count, FUZZ_PERCENT);
+			result = false;
+		}
+
+		if (!fuzzily_equal(records[0].findfirst_persec,
+				    records[i].findfirst_persec,
+				    FUZZ_PERCENT)) {
+			printf("findfirst rate for %d entries differed by "
+				"more than %d%% from base rate\n",
+				records[i].dirent_count, FUZZ_PERCENT);
+			result = false;
+		}
+	}
+
+done:
+	if (cli) {
+		remove_working_directory(cli->tree, BASEDIR);
+		talloc_free(cli);
+	}
+
+	return result;
+}
+
+/* vim: set sts=8 sw=8 : */
diff --git a/source/torture/raw/raw.c b/source/torture/raw/raw.c
index bb3dde7..262ed13 100644
--- a/source/torture/raw/raw.c
+++ b/source/torture/raw/raw.c
@@ -33,6 +33,8 @@ NTSTATUS torture_raw_init(void)
 	torture_suite_add_simple_test(suite, "PING-PONG", torture_ping_pong);
 	torture_suite_add_simple_test(suite, "BENCH-LOCK", torture_bench_lock);
 	torture_suite_add_simple_test(suite, "BENCH-OPEN", torture_bench_open);
+	torture_suite_add_simple_test(suite, "BENCH-LOOKUP",
+		torture_bench_lookup);
 	torture_suite_add_simple_test(suite, "OFFLINE", torture_test_offline);
 	torture_suite_add_1smb_test(suite, "QFSINFO", torture_raw_qfsinfo);
 	torture_suite_add_1smb_test(suite, "QFILEINFO", torture_raw_qfileinfo);


-- 
Samba Shared Repository


More information about the samba-cvs mailing list