| From 711727ad9226c070554e3b5ff4e020a66bc86d0c Mon Sep 17 00:00:00 2001 |
| From: Garima Singh <garima.singh@microsoft.com> |
| Date: Wed, 4 Sep 2019 13:36:39 -0400 |
| Subject: test-path-utils: offer to run a protectNTFS/protectHFS benchmark |
| |
| In preparation to flipping the default on `core.protectNTFS`, let's have |
| some way to measure the speed impact of this config setting reliably |
| (and for comparison, the `core.protectHFS` config setting). |
| |
| For now, this is a manual performance benchmark: |
| |
| ./t/helper/test-path-utils protect_ntfs_hfs [arguments...] |
| |
| where the arguments are an optional number of file names to test with, |
| optionally followed by minimum and maximum length of the random file |
| names. The default values are one million, 3 and 20, respectively. |
| |
| Just like `sqrti()` in `bisect.c`, we introduce a very simple function |
| to approximation the square root of a given value, in order to avoid |
| having to introduce the first user of `<math.h>` in Git's source code. |
| |
| Note: this is _not_ implemented as a Unix shell script in t/perf/ |
| because we really care about _very_ precise timings here, and Unix shell |
| scripts are simply unsuited for precise and consistent benchmarking. |
| |
| Signed-off-by: Garima Singh <garima.singh@microsoft.com> |
| Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> |
| (cherry picked from commit a62f9d1ace8c6556cbc1bb7df69eff0a0bb9e774) |
| Signed-off-by: Jonathan Nieder <jrnieder@gmail.com> |
| --- |
| t/helper/test-path-utils.c | 96 ++++++++++++++++++++++++++++++++++++++ |
| 1 file changed, 96 insertions(+) |
| |
| diff --git a/t/helper/test-path-utils.c b/t/helper/test-path-utils.c |
| index ae091d9b3e..d9411032d2 100644 |
| --- a/t/helper/test-path-utils.c |
| +++ b/t/helper/test-path-utils.c |
| @@ -177,6 +177,99 @@ static int is_dotgitmodules(const char *path) |
| return is_hfs_dotgitmodules(path) || is_ntfs_dotgitmodules(path); |
| } |
| |
| +/* |
| + * A very simple, reproducible pseudo-random generator. Copied from |
| + * `test-genrandom.c`. |
| + */ |
| +static uint64_t my_random_value = 1234; |
| + |
| +static uint64_t my_random(void) |
| +{ |
| + my_random_value = my_random_value * 1103515245 + 12345; |
| + return my_random_value; |
| +} |
| + |
| +/* |
| + * A fast approximation of the square root, without requiring math.h. |
| + * |
| + * It uses Newton's method to approximate the solution of 0 = x^2 - value. |
| + */ |
| +static double my_sqrt(double value) |
| +{ |
| + const double epsilon = 1e-6; |
| + double x = value; |
| + |
| + if (value == 0) |
| + return 0; |
| + |
| + for (;;) { |
| + double delta = (value / x - x) / 2; |
| + if (delta < epsilon && delta > -epsilon) |
| + return x + delta; |
| + x += delta; |
| + } |
| +} |
| + |
| +static int protect_ntfs_hfs_benchmark(int argc, const char **argv) |
| +{ |
| + size_t i, j, nr, min_len = 3, max_len = 20; |
| + char **names; |
| + int repetitions = 15, file_mode = 0100644; |
| + uint64_t begin, end; |
| + double m[3][2], v[3][2]; |
| + uint64_t cumul; |
| + double cumul2; |
| + |
| + if (argc > 1 && !strcmp(argv[1], "--with-symlink-mode")) { |
| + file_mode = 0120000; |
| + argc--; |
| + argv++; |
| + } |
| + |
| + nr = argc > 1 ? strtoul(argv[1], NULL, 0) : 1000000; |
| + ALLOC_ARRAY(names, nr); |
| + |
| + if (argc > 2) { |
| + min_len = strtoul(argv[2], NULL, 0); |
| + if (argc > 3) |
| + max_len = strtoul(argv[3], NULL, 0); |
| + if (min_len > max_len) |
| + die("min_len > max_len"); |
| + } |
| + |
| + for (i = 0; i < nr; i++) { |
| + size_t len = min_len + (my_random() % (max_len + 1 - min_len)); |
| + |
| + names[i] = xmallocz(len); |
| + while (len > 0) |
| + names[i][--len] = (char)(' ' + (my_random() % ('\x7f' - ' '))); |
| + } |
| + |
| + for (protect_ntfs = 0; protect_ntfs < 2; protect_ntfs++) |
| + for (protect_hfs = 0; protect_hfs < 2; protect_hfs++) { |
| + cumul = 0; |
| + cumul2 = 0; |
| + for (i = 0; i < repetitions; i++) { |
| + begin = getnanotime(); |
| + for (j = 0; j < nr; j++) |
| + verify_path(names[j], file_mode); |
| + end = getnanotime(); |
| + printf("protect_ntfs = %d, protect_hfs = %d: %lfms\n", protect_ntfs, protect_hfs, (end-begin) / (double)1e6); |
| + cumul += end - begin; |
| + cumul2 += (end - begin) * (end - begin); |
| + } |
| + m[protect_ntfs][protect_hfs] = cumul / (double)repetitions; |
| + v[protect_ntfs][protect_hfs] = my_sqrt(cumul2 / (double)repetitions - m[protect_ntfs][protect_hfs] * m[protect_ntfs][protect_hfs]); |
| + printf("mean: %lfms, stddev: %lfms\n", m[protect_ntfs][protect_hfs] / (double)1e6, v[protect_ntfs][protect_hfs] / (double)1e6); |
| + } |
| + |
| + for (protect_ntfs = 0; protect_ntfs < 2; protect_ntfs++) |
| + for (protect_hfs = 0; protect_hfs < 2; protect_hfs++) |
| + printf("ntfs=%d/hfs=%d: %lf%% slower\n", protect_ntfs, protect_hfs, (m[protect_ntfs][protect_hfs] - m[0][0]) * 100 / m[0][0]); |
| + |
| + return 0; |
| +} |
| + |
| int cmd__path_utils(int argc, const char **argv) |
| { |
| if (argc == 3 && !strcmp(argv[1], "normalize_path_copy")) { |
| @@ -291,6 +384,9 @@ int cmd__path_utils(int argc, const char **argv) |
| return !!res; |
| } |
| |
| + if (argc > 1 && !strcmp(argv[1], "protect_ntfs_hfs")) |
| + return !!protect_ntfs_hfs_benchmark(argc - 1, argv + 1); |
| + |
| fprintf(stderr, "%s: unknown function name: %s\n", argv[0], |
| argv[1] ? argv[1] : "(there was none)"); |
| return 1; |
| -- |
| 2.24.0.393.g34dc348eaf |
| |