[systemd-devel] [PATCH] test-manyunits: test unit_file_get_list perforamnce with many units

Ken Sedgwick ksedgwic at bonsai.com
Fri Oct 17 15:54:52 PDT 2014


This test temporarily creates several thousand unit files and checks
the performance of unit_file_get_list.

This test is currently added to manual_tests only since it does not
pass.

This test does pass if the enabled unit cache patch is applied.
---
 .gitignore                |   1 +
 Makefile.am               |  13 ++++-
 src/test/test-manyunits.c | 133 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 146 insertions(+), 1 deletion(-)
 create mode 100644 src/test/test-manyunits.c

diff --git a/.gitignore b/.gitignore
index 97b2b2b..7d5c97c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -207,6 +207,7 @@
 /test-login-tables
 /test-loopback
 /test-machine-tables
+/test-manyunits
 /test-mmap-cache
 /test-namespace
 /test-network
diff --git a/Makefile.am b/Makefile.am
index 46d532c..12cae02 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1306,7 +1306,8 @@ manual_tests += \
 	test-install \
 	test-watchdog \
 	test-log \
-	test-ipcrm
+	test-ipcrm \
+	test-manyunits
 
 if HAVE_KMOD
 manual_tests += \
@@ -1819,6 +1820,16 @@ test_enabled_LDADD = \
 	libsystemd-shared.la \
 	libsystemd-internal.la
 
+test_manyunits_SOURCES = \
+	src/test/test-manyunits.c
+
+test_manyunits_LDADD = \
+	libsystemd-core.la \
+	libsystemd-units.la \
+	libsystemd-label.la \
+	libsystemd-shared.la \
+	libsystemd-internal.la
+
 test_watchdog_SOURCES = \
 	src/test/test-watchdog.c
 
diff --git a/src/test/test-manyunits.c b/src/test/test-manyunits.c
new file mode 100644
index 0000000..e76f04c
--- /dev/null
+++ b/src/test/test-manyunits.c
@@ -0,0 +1,133 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+  This file is part of systemd.
+
+  Copyright 2014 Pantheon, Inc.
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd 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
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/param.h>
+#include <unistd.h>
+#include <time.h>
+
+#include "manager.h"
+#include "macro.h"
+#include "util.h"
+
+static const int NUNITS = 3000;
+
+static const char *root_dir;
+
+/* Cleanup the created unit files if we fail an assertion. */
+#define assert_se_cleanup(expr)                                         \
+        do {                                                            \
+                if (_unlikely_(!(expr))) {                              \
+                        cleanup_manyunits();                            \
+                        log_assert_failed(#expr, __FILE__, __LINE__,    \
+                                          __PRETTY_FUNCTION__);         \
+                }                                                       \
+        } while (false)                                                 \
+
+static const char *many_path(int unitnum) {
+        static char path[PATH_MAX];
+        snprintf(path, PATH_MAX, "%s/%s/many-%06d.service",
+                 root_dir, "usr/lib/systemd/system", unitnum);
+        return path;
+}
+
+static const char *link_path(int unitnum) {
+        static char path[PATH_MAX];
+        snprintf(path, PATH_MAX, "%s/%s/many-%06d.service",
+                 root_dir, "etc/systemd/system/some.target.wants", unitnum);
+        return path;
+}
+
+static const char *another_path(void) {
+        static char path[PATH_MAX];
+        snprintf(path, PATH_MAX, "%s/%s/another.service",
+                 root_dir, "usr/lib/systemd/system");
+        return path;
+}
+
+
+static void cleanup_manyunits(void) {
+        int unitnum;
+
+        fprintf(stderr, "removing %d unit files\n", NUNITS);
+
+        for (unitnum = 0; unitnum < NUNITS; ++unitnum) {
+                unlink(link_path(unitnum));
+                unlink(many_path(unitnum));
+        }
+}
+
+static void setup_manyunits(void) {
+        int unitnum;
+        const char *another;
+
+        another = another_path();
+
+        fprintf(stderr, "creating %d unit files\n", NUNITS);
+
+        for (unitnum = 0; unitnum < NUNITS; ++unitnum) {
+                assert_se_cleanup(link(another, many_path(unitnum)) == 0);
+                assert_se_cleanup(symlink(many_path(unitnum),
+                                          link_path(unitnum)) == 0);
+        }
+}
+
+static void test_manyunits(void) {
+        time_t t0, t1;
+        int r = 0;
+        int count = 0;
+        Hashmap *h;
+        UnitFileList *p;
+        Iterator i;
+
+        fprintf(stderr, "testing with %d unit files\n", NUNITS);
+
+        t0 = time(NULL);
+        h = hashmap_new(&string_hash_ops);
+        r = unit_file_get_list(UNIT_FILE_SYSTEM, root_dir, h);
+        assert_se_cleanup(r >= 0);
+        HASHMAP_FOREACH(p, h, i) {
+                ++count;
+        }
+        fprintf(stderr, "saw %d units\n", count);
+        assert_se_cleanup(count == 3015);
+        t1 = time(NULL);
+
+        fprintf(stderr, "unit_file_get_list took %ld seconds\n",
+                (long) (t1 - t0));
+
+        assert_se_cleanup(t1 - t0 < 10);
+}
+
+int main(int argc, char* argv[]) {
+        root_dir = strappenda(TEST_DIR, "/test-enabled-root");
+
+        setup_manyunits();
+
+        test_manyunits();
+
+        cleanup_manyunits();
+
+        return 0;
+}
-- 
1.9.3



More information about the systemd-devel mailing list