]> www.infradead.org Git - mtd-utils.git/commitdiff
fs-tests: add simple performance test
authorAdrian Hunter <ext-adrian.hunter@nokia.com>
Tue, 6 Nov 2007 11:08:12 +0000 (13:08 +0200)
committerArtem Bityutskiy <Artem.Bityutskiy@nokia.com>
Mon, 16 Jun 2008 15:02:31 +0000 (18:02 +0300)
Signed-off-by: Adrian Hunter <ext-adrian.hunter@nokia.com>
tests/fs-tests/lib/tests.c
tests/fs-tests/lib/tests.h
tests/fs-tests/simple/Makefile
tests/fs-tests/simple/perf.c [new file with mode: 0644]

index 9b8f44330543290ff027d8fb5219a36aff7a8040..aaf3907c91010f40f97d82d12fc073772d6286a9 100644 (file)
@@ -1002,6 +1002,48 @@ void tests_remount(void)
        CHECK(chdir(cwd) != -1);
 }
 
+/* Un-mount or re-mount test file system */
+static void tests_mnt(int mnt)
+{
+       static struct mntent mount_info;
+       char *source;
+       char *target;
+       char *filesystemtype;
+       unsigned long mountflags;
+       void *data;
+       static char cwd[4096];
+
+       if (mnt == 0) {
+               CHECK(tests_get_mount_info(&mount_info));
+               if (strcmp(mount_info.mnt_dir,"/") == 0)
+                       return;
+               CHECK(getcwd(cwd, 4096) != NULL);
+               CHECK(chdir("/") != -1);
+               CHECK(umount(tests_file_system_mount_dir) != -1);
+       } else {
+               source = mount_info.mnt_fsname;
+               target = tests_file_system_mount_dir;
+               filesystemtype = tests_file_system_type;
+               mountflags = 0;
+               data = NULL;
+               CHECK(mount(source, target, filesystemtype, mountflags, data)
+                       != -1);
+               CHECK(chdir(cwd) != -1);
+       }
+}
+
+/* Unmount test file system */
+void tests_unmount(void)
+{
+       tests_mnt(0);
+}
+
+/* Mount test file system */
+void tests_mount(void)
+{
+       tests_mnt(1);
+}
+
 /* Check whether the test file system is also the root file system */
 int tests_fs_is_rootfs(void)
 {
index db08628aa7914f9455f2b42d26135e90bc3da7cf..04c834d83e8034f48b43767bc7595b4fe886fd12 100644 (file)
@@ -146,6 +146,12 @@ int64_t tests_remove_entry(void);
 /* Un-mount and re-mount test file system */
 void tests_remount(void);
 
+/* Un-mount test file system */
+void tests_unmount(void);
+
+/* Mount test file system */
+void tests_mount(void);
+
 /* Check whether the test file system is also the root file system */
 int tests_fs_is_rootfs(void);
 
index 8190993171ded369169b5a9d3171b868ca834dc0..d447da3cf9afa6d1a5c1b8074a51da5679c4ccc9 100644 (file)
@@ -10,7 +10,8 @@ LDFLAGS := $(LDFLAGS)
 TARGETS = test_1 \
        test_2 \
        ftrunc \
-       orph
+       orph \
+       perf
 
 all: $(TARGETS)
 
@@ -26,3 +27,4 @@ tests: all
        ./test_2 --sync
        ./ftrunc
        ./orph --sync
+       ./perf
diff --git a/tests/fs-tests/simple/perf.c b/tests/fs-tests/simple/perf.c
new file mode 100644 (file)
index 0000000..43d708d
--- /dev/null
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) 2007 Nokia Corporation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ * Author: Adrian Hunter
+ */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <time.h>
+#include <limits.h>
+
+#include "tests.h"
+
+#define BLOCK_SIZE 32 * 1024
+
+struct timeval tv_start;
+struct timeval tv_stop;
+
+static inline void start_timer(void)
+{
+       CHECK(gettimeofday(&tv_start, NULL) != -1);
+}
+
+static inline long long stop_timer(void)
+{
+       long long usecs;
+
+       CHECK(gettimeofday(&tv_stop, NULL) != -1);
+       usecs = (tv_stop.tv_sec - tv_start.tv_sec);
+       usecs *= 1000000;
+       usecs += tv_stop.tv_usec;
+       usecs -= tv_start.tv_usec;
+       return usecs;
+}
+
+static unsigned speed(size_t bytes, long long usecs)
+{
+       unsigned long long k;
+
+       k = bytes * 1000000ULL;
+       k /= usecs;
+       k /= 1024;
+       CHECK(k <= UINT_MAX);
+       return (unsigned) k;
+}
+
+void perf(void)
+{
+       pid_t pid;
+       int fd, i;
+       ssize_t written, readsz;
+       size_t remains, block, actual_size;
+       char file_name[256];
+       unsigned char *buf;
+       long long write_time, unmount_time, mount_time, read_time;
+
+       /* Sync all file systems */
+       sync();
+       /* Make random data to write */
+       buf = malloc(BLOCK_SIZE);
+       CHECK(buf != NULL);
+       pid = getpid();
+       srand(pid);
+       for (i = 0; i < BLOCK_SIZE; i++)
+               buf[i] = rand();
+       /* Open file */
+       tests_cat_pid(file_name, "perf_test_file_", pid);
+       start_timer();
+       fd = open(file_name, O_CREAT | O_RDWR | O_TRUNC,
+                 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH);
+       CHECK(fd != -1);
+       CHECK(tests_size_parameter > 0);
+       CHECK(tests_size_parameter <= SIZE_MAX);
+       /* Write to file */
+       actual_size = 0;
+       remains = tests_size_parameter;
+       while (remains > 0) {
+               if (remains > BLOCK_SIZE)
+                       block = BLOCK_SIZE;
+               else
+                       block = remains;
+               written = write(fd, buf, block);
+               if (written <= 0) {
+                       CHECK(errno == ENOSPC); /* File system full */
+                       errno = 0;
+                       break;
+               }
+               remains -= written;
+               actual_size += written;
+       }
+       CHECK(fsync(fd) != -1);
+       CHECK(close(fd) != -1);
+       write_time = stop_timer();
+       /* Unmount */
+       start_timer();
+       tests_unmount();
+       unmount_time = stop_timer();
+       /* Mount */
+       start_timer();
+       tests_mount();
+       mount_time = stop_timer();
+       /* Open file, read it, and close it */
+       start_timer();
+       fd = open(file_name, O_RDONLY);
+       CHECK(fd != -1);
+       remains = actual_size;
+       while (remains > 0) {
+               if (remains > BLOCK_SIZE)
+                       block = BLOCK_SIZE;
+               else
+                       block = remains;
+               readsz = read(fd, buf, block);
+               CHECK(readsz == block);
+               remains -= readsz;
+       }
+       CHECK(close(fd) != -1);
+       read_time = stop_timer();
+       CHECK(unlink(file_name) != -1);
+       /* Display timings */
+       printf("File system read and write speed\n");
+       printf("================================\n");
+       printf("Specfied file size: %lld\n", tests_size_parameter);
+       printf("Actual file size: %zu\n", actual_size);
+       printf("Write time (us): %lld\n", write_time);
+       printf("Unmount time (us): %lld\n", unmount_time);
+       printf("Mount time (us): %lld\n", mount_time);
+       printf("Read time (us): %lld\n", read_time);
+       printf("Write speed (KiB/s): %u\n", speed(actual_size, write_time));
+       printf("Read speed (KiB/s): %u\n", speed(actual_size, read_time));
+       printf("Test completed\n");
+}
+
+/* Title of this test */
+
+const char *perf_get_title(void)
+{
+       return "Measure file system read and write speed";
+}
+
+/* Description of this test */
+
+const char *perf_get_description(void)
+{
+       return
+               "Syncs the file system (a newly created empty file system is " \
+               "preferable). Creates a file named perf_test_file_pid, where " \
+               "pid is the process id. The file is filled with random data. " \
+               "The size of the file is given by the -z or --size option, " \
+               "otherwise it defaults to 10MiB. Unmounts the file system. " \
+               "Mounts the file system. Reads the entire file in 32KiB size " \
+               "blocks. Displays the time taken for each activity. Deletes " \
+               "the file. Note that the file is synced after writing and " \
+               "that time is included in the write time and speed.";
+}
+
+int main(int argc, char *argv[])
+{
+       int run_test;
+
+       /* Set default test file size */
+       tests_size_parameter = 10 * 1024 * 1024;
+
+       /* Handle common arguments */
+       run_test = tests_get_args(argc, argv, perf_get_title(),
+                       perf_get_description(), "z");
+       if (!run_test)
+               return 1;
+       /* Change directory to the file system and check it is ok for testing */
+       tests_check_test_file_system();
+       /* Do the actual test */
+       perf();
+       return 0;
+}