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 subsequent 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 _______________________________________________ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel