]> git.ipfire.org Git - thirdparty/git.git/commitdiff
scalar: teach `diagnose` to gather loose objects information
authorMatthew John Cheetham <mjcheetham@outlook.com>
Sat, 28 May 2022 23:11:18 +0000 (16:11 -0700)
committerJunio C Hamano <gitster@pobox.com>
Tue, 31 May 2022 06:07:31 +0000 (23:07 -0700)
When operating at the scale that Scalar wants to support, certain data
shapes are more likely to cause undesirable performance issues, such as
large numbers of loose objects.

By including statistics about this, `scalar diagnose` now makes it
easier to identify such scenarios.

Signed-off-by: Matthew John Cheetham <mjcheetham@outlook.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
contrib/scalar/scalar.c
contrib/scalar/t/t9099-scalar.sh

index f7455190385a134cc7c5c131b767e690531783da..28176914e57b91e823d6197a926909a87cfe1d16 100644 (file)
@@ -618,6 +618,60 @@ static int dir_file_stats(struct object_directory *object_dir, void *data)
        return 0;
 }
 
+static int count_files(char *path)
+{
+       DIR *dir = opendir(path);
+       struct dirent *e;
+       int count = 0;
+
+       if (!dir)
+               return 0;
+
+       while ((e = readdir(dir)) != NULL)
+               if (!is_dot_or_dotdot(e->d_name) && e->d_type == DT_REG)
+                       count++;
+
+       closedir(dir);
+       return count;
+}
+
+static void loose_objs_stats(struct strbuf *buf, const char *path)
+{
+       DIR *dir = opendir(path);
+       struct dirent *e;
+       int count;
+       int total = 0;
+       unsigned char c;
+       struct strbuf count_path = STRBUF_INIT;
+       size_t base_path_len;
+
+       if (!dir)
+               return;
+
+       strbuf_addstr(buf, "Object directory stats for ");
+       strbuf_add_absolute_path(buf, path);
+       strbuf_addstr(buf, ":\n");
+
+       strbuf_add_absolute_path(&count_path, path);
+       strbuf_addch(&count_path, '/');
+       base_path_len = count_path.len;
+
+       while ((e = readdir(dir)) != NULL)
+               if (!is_dot_or_dotdot(e->d_name) &&
+                   e->d_type == DT_DIR && strlen(e->d_name) == 2 &&
+                   !hex_to_bytes(&c, e->d_name, 1)) {
+                       strbuf_setlen(&count_path, base_path_len);
+                       strbuf_addstr(&count_path, e->d_name);
+                       total += (count = count_files(count_path.buf));
+                       strbuf_addf(buf, "%s : %7d files\n", e->d_name, count);
+               }
+
+       strbuf_addf(buf, "Total: %d loose objects", total);
+
+       strbuf_release(&count_path);
+       closedir(dir);
+}
+
 static int cmd_diagnose(int argc, const char **argv)
 {
        struct option options[] = {
@@ -686,6 +740,11 @@ static int cmd_diagnose(int argc, const char **argv)
        foreach_alt_odb(dir_file_stats, &buf);
        strvec_push(&archiver_args, buf.buf);
 
+       strbuf_reset(&buf);
+       strbuf_addstr(&buf, "--add-virtual-file=objects-local.txt:");
+       loose_objs_stats(&buf, ".git/objects");
+       strvec_push(&archiver_args, buf.buf);
+
        if ((res = add_directory_to_archiver(&archiver_args, ".git", 0)) ||
            (res = add_directory_to_archiver(&archiver_args, ".git/hooks", 0)) ||
            (res = add_directory_to_archiver(&archiver_args, ".git/info", 0)) ||
index 2603e2278f5593d2112cffc3853518c1540a15aa..10b1172a8aa0d219f26a0f927c6bbf1800ba3a1c 100755 (executable)
@@ -103,6 +103,7 @@ test_expect_success UNZIP 'scalar diagnose' '
        scalar clone "file://$(pwd)" cloned --single-branch &&
        git repack &&
        echo "$(pwd)/.git/objects/" >>cloned/src/.git/objects/info/alternates &&
+       test_commit -C cloned/src loose &&
        scalar diagnose cloned >out 2>err &&
        grep "Available space" out &&
        sed -n "s/.*$SQ\\(.*\\.zip\\)$SQ.*/\\1/p" <err >zip_path &&
@@ -114,7 +115,9 @@ test_expect_success UNZIP 'scalar diagnose' '
        unzip -p "$zip_path" diagnostics.log >out &&
        test_file_not_empty out &&
        unzip -p "$zip_path" packs-local.txt >out &&
-       grep "$(pwd)/.git/objects" out
+       grep "$(pwd)/.git/objects" out &&
+       unzip -p "$zip_path" objects-local.txt >out &&
+       grep "^Total: [1-9]" out
 '
 
 test_done