diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index 9b11a2fb..25fd5dc5 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -22,30 +22,57 @@ jobs: compiler_mode: [gcc, clang, gcc-asan, clang-msan] build_mode: [release, debug] target: [all] # Just compile most configs + include_slow_tests: ['true'] + run_nightly_tests: ['false'] exclude: # Don't do a compile job on these, since we will do run-tests on them below - compiler_mode: gcc-asan build_mode: release target: all + include_slow_tests: 'true' + run_nightly_tests: 'false' - compiler_mode: clang-msan build_mode: release target: all + include_slow_tests: 'true' + run_nightly_tests: 'false' - compiler_mode: clang build_mode: debug target: all + include_slow_tests: 'true' + run_nightly_tests: 'false' + - compiler_mode: gcc + build_mode: release + target: all + include_slow_tests: 'true' + run_nightly_tests: 'false' include: # Compile and run tests on these configs - compiler_mode: gcc-asan build_mode: release target: run-tests + include_slow_tests: 'true' + run_nightly_tests: 'false' - compiler_mode: clang-msan build_mode: release - sanitizer: msan target: run-tests + include_slow_tests: 'true' + run_nightly_tests: 'false' - compiler_mode: clang build_mode: debug target: run-tests - name: ${{ matrix.target == 'all' && 'Compile' || 'Run' }} ${{ matrix.compiler_mode }} ${{ matrix.build_mode }} ${{ matrix.target }} + include_slow_tests: 'true' + run_nightly_tests: 'false' + - compiler_mode: gcc + build_mode: release + target: run-tests + include_slow_tests: 'false' + run_nightly_tests: 'true' + name: > + ${{ matrix.target == 'all' && 'Compile' || 'Run' }} + ${{ matrix.compiler_mode }} ${{ matrix.build_mode }} ${{ matrix.target }} + ${{ matrix.target == 'run-tests' && matrix.include_slow_tests == 'true' && '(slow tests)' || '' }} + ${{ matrix.target == 'run-tests' && matrix.run_nightly_tests == 'true' && '(nightly tests)' || '' }} runs-on: ubuntu-latest env: CC: ${{ startsWith(matrix.compiler_mode, 'gcc') && 'gcc' || 'clang' }} @@ -53,7 +80,8 @@ jobs: BUILD_MODE: ${{ matrix.build_mode }} BUILD_ASAN: ${{ endsWith(matrix.compiler_mode, 'asan') && 1 || 0 }} BUILD_MSAN: ${{ endsWith(matrix.compiler_mode, 'msan') && 1 || 0 }} - INCLUDE_SLOW_TESTS: true + INCLUDE_SLOW_TESTS: ${{ matrix.include_slow_tests }} + RUN_NIGHTLY_TESTS: ${{ matrix.run_nightly_tests }} steps: - name: Maximize build space uses: easimon/maximize-build-space@master diff --git a/src/clockcache.c b/src/clockcache.c index 0337da22..d0e9ee92 100644 --- a/src/clockcache.c +++ b/src/clockcache.c @@ -963,8 +963,11 @@ clockcache_batch_start_writeback(clockcache *cc, uint64 batch, bool32 is_urgent) && clockcache_try_set_writeback(cc, next_entry_no, is_urgent)); - async_io_state *state = TYPED_MALLOC(cc->heap_id, state); - platform_assert(state != NULL); + async_io_state *state; + while ((state = TYPED_MALLOC(cc->heap_id, state)) == NULL) { + clockcache_wait(cc); + } + state->cc = cc; state->outstanding_pages = NULL; io_async_state_init(state->iostate, diff --git a/test.sh b/test.sh index 1ddadd2e..3c465259 100755 --- a/test.sh +++ b/test.sh @@ -179,6 +179,7 @@ function nightly_functionality_stress_tests() { --num-tables ${ntables} \ --cache-capacity-gib ${cache_size} \ --db-location ${dbname} + rm ${dbname} # ---- ntables=2 @@ -190,6 +191,7 @@ function nightly_functionality_stress_tests() { --num-tables ${ntables} \ --cache-capacity-gib ${cache_size} \ --db-location ${dbname} + rm ${dbname} # ---- cache_size=1 # GiB @@ -206,6 +208,7 @@ function nightly_functionality_stress_tests() { --num-tables ${ntables} \ --cache-capacity-gib ${cache_size} \ --db-location ${dbname} + rm ${dbname} # ---- ntables=4 @@ -217,6 +220,8 @@ function nightly_functionality_stress_tests() { --num-tables ${ntables} \ --cache-capacity-gib ${cache_size} \ --db-location ${dbname} + rm ${dbname} + # ---- cache_size=512 # MiB test_descr="${nrows_h} rows, ${ntables} tables, ${cache_size} MiB cache" @@ -238,6 +243,7 @@ function nightly_unit_stress_tests() { local n_mills=10 local num_rows=$((n_mills * 1000 * 1000)) local nrows_h="${n_mills} mil" + local dbname="splinterdb_unit_tests_db" # ---- local n_threads=32 @@ -252,6 +258,8 @@ function nightly_unit_stress_tests() { --num-inserts ${num_rows} \ --num-memtable-bg-threads 8 \ --num-normal-bg-threads 20 + rm ${dbname} + } # ############################################################################# @@ -298,7 +306,7 @@ function nightly_sync_perf_tests() { --tree-size-gib 4 \ --db-capacity-gib 60 \ --db-location ${dbname} \ - --verbose-progress + --verbose-progress \ ${Use_shmem} rm ${dbname} @@ -353,6 +361,7 @@ function nightly_cache_perf_tests() { "$BINDIR"/driver_test cache_test --perf \ --db-location ${dbname} \ ${Use_shmem} + rm ${dbname} cache_size=6 # GiB test_descr="${cache_size} GiB cache" @@ -377,13 +386,16 @@ function nightly_async_perf_tests() { local npthreads=20 local nbgthreads=20 local nasync=10 + local tree_size=5 local test_descr="${npthreads} pthreads,bgt=${nbgthreads},async=${nasync}" local dbname="splinter_test.perf.db" run_with_timing "Parallel Async Performance test ${test_descr}" \ "$BINDIR"/driver_test splinter_test --parallel-perf \ - --num-bg-threads ${nbgthreads} \ --max-async-inflight ${nasync} \ --num-pthreads ${npthreads} \ + --tree-size-gib ${tree_size} \ + --num-normal-bg-threads ${nbgthreads} \ + --num-memtable-bg-threads 2 \ --db-capacity-gib 60 \ --db-location ${dbname} rm ${dbname} @@ -397,7 +409,7 @@ function run_nightly_perf_tests() { nightly_cache_perf_tests - # nightly_async_perf_tests + nightly_async_perf_tests } # ############################################################################# @@ -692,6 +704,7 @@ function run_slower_forked_process_tests() { msg="Splinter tests using ${num_forked_procs} forked child processes" run_with_timing "${msg}" "$BINDIR"/unit/splinterdb_forked_child_test \ --num-processes ${num_forked_procs} + rm splinterdb_unit_tests_db # ---- Run large_inserts_stress_test with small configuration as a quick check # using forked child process execution. @@ -934,71 +947,6 @@ testRunStartSeconds=$SECONDS echo "$(TZ="America/Los_Angeles" date) **** SplinterDB${run_type}Test Suite Execution Times **** " > "${test_exec_log_file}" echo >> "${test_exec_log_file}" -# ---- Nightly Stress and Performance test runs ---- -if [ "$RUN_NIGHTLY_TESTS" == "true" ]; then - - set +e - run_with_timing "Check limits, error conditions." nightly_test_limitations - - run_nightly_stress_tests - - Use_shmem="" run_nightly_perf_tests - Use_shmem="--use-shmem" run_nightly_perf_tests - set -e - - record_elapsed_time ${testRunStartSeconds} "Nightly Stress & Performance Tests" - cat_exec_log_file - exit 0 -fi - -# ---- Fast running Smoke test runs ---- -if [ "$INCLUDE_SLOW_TESTS" != "true" ]; then - - # For some coverage, exercise --help, --list args for unit test binaries - set -x - "$BINDIR"/unit_test --help - "$BINDIR"/unit_test --list - "$BINDIR"/unit_test --list splinterdb_quick - "$BINDIR"/unit/btree_test --help - "$BINDIR"/unit/splinterdb_quick_test --list - set +x - - echo " " - echo "NOTE: **** Only running fast unit tests ****" - echo "To run all tests, set the env var, and re-run: $ INCLUDE_SLOW_TESTS=true ./$Me" - echo " " - - # Exercise config-parsing test case. Here, we feed-in a set of - # --config-params that the test code knows to "expect" and validates. - # These options can come in any order. - set -x - run_with_timing "Config-params parsing test" - "$BINDIR"/unit/config_parse_test --log \ - --num-inserts 20 \ - --rough-count-height 11 \ - --stats \ - --verbose-logging \ - --verbose-progress - set +x - - start_seconds=$SECONDS - - run_with_timing "Smoke tests" run_fast_unit_tests "" - - Use_shmem="--use-shmem" - run_with_timing "Smoke tests using shared memory" run_fast_unit_tests - - if [ "$RUN_MAKE_TESTS" == "true" ]; then - run_with_timing "Basic build-and-test tests" test_make_run_tests - fi - - cat_exec_log_file - exit 0 -fi - -# ---- Rest of the coverage runs included in CI test runs ---- -UNIT_TESTS_DB_DEV="unit_tests_db" - # ------------------------------------------------------------------------ # Fast-path execution support. You can invoke this script specifying the # name of one of the functions to execute a specific set of tests. If the @@ -1039,29 +987,94 @@ if [ $# -ge 1 ]; then exit 0 fi -# Run all the unit-tests first, to get basic coverage -run_with_timing "Fast unit tests" "$BINDIR"/unit_test +# +# Fast tests +# -# ------------------------------------------------------------------------ -# Run mini-unit-tests that were excluded from bin/unit_test binary: -# ------------------------------------------------------------------------ -Use_shmem="" -run_slower_unit_tests +# For some coverage, exercise --help, --list args for unit test binaries +set -x +"$BINDIR"/unit_test --help +"$BINDIR"/unit_test --list +"$BINDIR"/unit_test --list splinterdb_quick +"$BINDIR"/unit/btree_test --help +"$BINDIR"/unit/splinterdb_quick_test --list +set +x + +# Exercise config-parsing test case. Here, we feed-in a set of +# --config-params that the test code knows to "expect" and validates. +# These options can come in any order. +set -x +run_with_timing "Config-params parsing test" + "$BINDIR"/unit/config_parse_test --log \ + --num-inserts 20 \ + --rough-count-height 11 \ + --stats \ + --verbose-logging \ + --verbose-progress +set +x -if [ -f ${UNIT_TESTS_DB_DEV} ]; then rm ${UNIT_TESTS_DB_DEV}; fi +run_with_timing "Smoke tests" run_fast_unit_tests "" -run_splinter_functionality_tests +Use_shmem="--use-shmem" +run_with_timing "Smoke tests using shared memory" run_fast_unit_tests -run_splinter_perf_tests +if [ "$RUN_MAKE_TESTS" == "true" ]; then + run_with_timing "Basic build-and-test tests" test_make_run_tests +fi -run_btree_tests +# +# Slow tests +# + +if [ "$INCLUDE_SLOW_TESTS" == "true" ]; then + + # ---- Rest of the coverage runs included in CI test runs ---- + UNIT_TESTS_DB_DEV="unit_tests_db" + + # Run all the unit-tests first, to get basic coverage + run_with_timing "Fast unit tests" "$BINDIR"/unit_test + + # ------------------------------------------------------------------------ + # Run mini-unit-tests that were excluded from bin/unit_test binary: + # ------------------------------------------------------------------------ + Use_shmem="" + run_slower_unit_tests + + if [ -f ${UNIT_TESTS_DB_DEV} ]; then rm ${UNIT_TESTS_DB_DEV}; fi + + run_splinter_functionality_tests + + run_splinter_perf_tests + + run_btree_tests + + run_other_driver_tests + + record_elapsed_time ${testRunStartSeconds} "Tests without shared memory configured" + # ------------------------------------------------------------------------ + # Re-run a collection of tests using shared-memory. + Use_shmem="--use-shmem" run_tests_with_shared_memory + +fi + +# ---- Nightly Stress and Performance test runs ---- +if [ "$RUN_NIGHTLY_TESTS" == "true" ]; then + + set +e + run_with_timing "Check limits, error conditions." nightly_test_limitations + + run_nightly_stress_tests + + Use_shmem="" run_nightly_perf_tests + Use_shmem="--use-shmem" run_nightly_perf_tests + set -e + + record_elapsed_time ${testRunStartSeconds} "Nightly Stress & Performance Tests" + cat_exec_log_file + exit 0 +fi -run_other_driver_tests -record_elapsed_time ${testRunStartSeconds} "Tests without shared memory configured" -# ------------------------------------------------------------------------ -# Re-run a collection of tests using shared-memory. -Use_shmem="--use-shmem" run_tests_with_shared_memory record_elapsed_time ${testRunStartSeconds} "All Tests" echo ALL PASSED diff --git a/tests/functional/cache_test.c b/tests/functional/cache_test.c index 06927563..66a4605c 100644 --- a/tests/functional/cache_test.c +++ b/tests/functional/cache_test.c @@ -18,7 +18,7 @@ #include "task.h" #include "util.h" #include "random.h" - +#include "test_common.h" #include "poison.h" platform_status @@ -574,29 +574,29 @@ test_cache_flush(cache *cc, typedef struct { page_get_async_state_buffer buffer; enum { waiting_on_io, ready_to_continue, done } status; -} test_async_ctxt; +} cache_test_async_ctxt; typedef struct { - cache *cc; // IN - clockcache_config *cfg; // IN - task_system *ts; // IN - platform_thread thread; // IN - platform_heap_id hid; // IN - bool32 mt_reader; // IN readers are MT - bool32 logger; // IN logger thread - const uint64 *addr_arr; // IN array of page addrs - uint64 num_pages; // IN #of pages to get - uint64 num_pages_ws; // IN #of pages in working set - uint32 sync_probability; // IN probability of sync get - page_handle **handle_arr; // page handles - test_async_ctxt ctxt[READER_BATCH_SIZE]; // async_get() contexts + cache *cc; // IN + clockcache_config *cfg; // IN + task_system *ts; // IN + platform_thread thread; // IN + platform_heap_id hid; // IN + bool32 mt_reader; // IN readers are MT + bool32 logger; // IN logger thread + const uint64 *addr_arr; // IN array of page addrs + uint64 num_pages; // IN #of pages to get + uint64 num_pages_ws; // IN #of pages in working set + uint32 sync_probability; // IN probability of sync get + page_handle **handle_arr; // page handles + cache_test_async_ctxt ctxt[READER_BATCH_SIZE]; // async_get() contexts } test_params; void test_async_callback(void *ctxt) { - test_async_ctxt *test_ctxt = (test_async_ctxt *)ctxt; - test_ctxt->status = ready_to_continue; + cache_test_async_ctxt *test_ctxt = (cache_test_async_ctxt *)ctxt; + test_ctxt->status = ready_to_continue; } // Wait for in flight async lookups @@ -607,7 +607,7 @@ test_wait_inflight(test_params *params, uint64 j; for (j = 0; j < READER_BATCH_SIZE; j++) { - test_async_ctxt *ctxt = ¶ms->ctxt[j]; + cache_test_async_ctxt *ctxt = ¶ms->ctxt[j]; if (ctxt->status != done) { while (ctxt->status != done) { @@ -643,8 +643,8 @@ test_do_read_batch(threadid tid, test_params *params, uint64 batch_start) uint64 j; for (j = 0; j < READER_BATCH_SIZE; j++) { - async_status res; - test_async_ctxt *ctxt = ¶ms->ctxt[j]; + async_status res; + cache_test_async_ctxt *ctxt = ¶ms->ctxt[j]; // MT test probabilistically mixes sync and async api to test races if (mt_reader && params->sync_probability != 0 @@ -692,12 +692,14 @@ test_reader_thread(void *arg) uint64 i, j, k; const uint64 num_pages = ROUNDDOWN(params->num_pages, READER_BATCH_SIZE); const threadid tid = platform_get_tid(); + uint64 progress = 0; for (i = k = 0; i < num_pages; i += READER_BATCH_SIZE) { if (params->logger) { - platform_throttled_error_log(DEFAULT_THROTTLE_INTERVAL_SEC, - PLATFORM_CR "test %3lu%% complete", - i * 100 / num_pages); + test_print_progress(&progress, + i * 100 / num_pages, + PLATFORM_CR "test %3lu%% complete", + i * 100 / num_pages); } // Maintain working set by doing ungets on old pages if (i >= k + params->num_pages_ws) { diff --git a/tests/functional/io_apis_test.c b/tests/functional/io_apis_test.c index 89aab684..3335ebfb 100644 --- a/tests/functional/io_apis_test.c +++ b/tests/functional/io_apis_test.c @@ -882,7 +882,7 @@ test_async_reads(platform_heap_id hid, } } - io_cleanup(ioh, NUM_PAGES_RW_ASYNC_PER_THREAD); + io_wait_all(ioh); platform_free(hid, exp); free_buf: diff --git a/tests/functional/splinter_test.c b/tests/functional/splinter_test.c index a88cea22..d6f4c810 100644 --- a/tests/functional/splinter_test.c +++ b/tests/functional/splinter_test.c @@ -72,6 +72,7 @@ typedef struct test_splinter_thread_params { uint8 lookup_positive_pct; // parallel lookup positive % uint64 seed; uint64 range_lookups_done; + uint64 progress; } test_splinter_thread_params; /* @@ -142,11 +143,13 @@ test_trunk_insert_thread(void *arg) if (test_is_done(done, spl_idx)) { continue; } - platform_default_log(PLATFORM_CR "Thread %lu inserting %3lu%% " - "complete for table %u ... ", - thread_number, - insert_base[spl_idx] / (total_ops[spl_idx] / 100), - spl_idx); + test_print_progress(¶ms->progress, + insert_base[spl_idx] / (total_ops[spl_idx] / 100), + PLATFORM_CR "Thread %lu inserting %3lu%% " + "complete for table %u", + thread_number, + insert_base[spl_idx] / (total_ops[spl_idx] / 100), + spl_idx); insert_base[spl_idx] = __sync_fetch_and_add(&curr_op[spl_idx], op_granularity); if (insert_base[spl_idx] >= total_ops[spl_idx]) { @@ -251,12 +254,13 @@ test_trunk_lookup_thread(void *arg) if (test_is_done(done, spl_idx)) { continue; } - platform_throttled_error_log( - DEFAULT_THROTTLE_INTERVAL_SEC, - PLATFORM_CR "Thread %lu lookups %3lu%% complete for table %u", - thread_number, - lookup_base[spl_idx] / (total_ops[spl_idx] / 100), - spl_idx); + test_print_progress(¶ms->progress, + lookup_base[spl_idx] / (total_ops[spl_idx] / 100), + PLATFORM_CR "Thread %lu lookups %3lu%% complete " + "for table %u", + thread_number, + lookup_base[spl_idx] / (total_ops[spl_idx] / 100), + spl_idx); lookup_base[spl_idx] = __sync_fetch_and_add(&curr_op[spl_idx], op_granularity); if (lookup_base[spl_idx] >= total_ops[spl_idx]) { @@ -398,15 +402,16 @@ test_trunk_range_thread(void *arg) start_time = platform_get_timestamp(); } } - platform_throttled_error_log( - DEFAULT_THROTTLE_INTERVAL_SEC, - PLATFORM_CR "Thread %lu range lookups %3lu%% complete for table %u" - ", range_base=%lu%s", - thread_number, - range_base[spl_idx] / (total_ops[spl_idx] / 100), - spl_idx, - range_base[spl_idx], - newmsg); + test_print_progress(¶ms->progress, + range_base[spl_idx] / (total_ops[spl_idx] / 100), + PLATFORM_CR + "Thread %lu range lookups %3lu%% " + "complete for table %u, range_base=%lu%s", + thread_number, + range_base[spl_idx] / (total_ops[spl_idx] / 100), + spl_idx, + range_base[spl_idx], + newmsg); range_base[spl_idx] = __sync_fetch_and_add(&curr_op[spl_idx], op_granularity); @@ -463,12 +468,12 @@ test_trunk_range_thread(void *arg) *----------------------------------------------------------------------------- */ static bool32 -advance_base(const test_splinter_thread_params *params, - uint64 *curr_op, - uint64 *base, - uint8 *done, - random_state *rs, - test_splinter_pthread_op_type type) +advance_base(test_splinter_thread_params *params, + uint64 *curr_op, + uint64 *base, + uint8 *done, + random_state *rs, + test_splinter_pthread_op_type type) { const uint64 *total_ops = params->total_ops; const uint64 op_granularity = params->op_granularity; @@ -481,12 +486,12 @@ advance_base(const test_splinter_thread_params *params, } if (type == OP_INSERT) { - platform_throttled_error_log( - DEFAULT_THROTTLE_INTERVAL_SEC, - PLATFORM_CR "inserting/lookups %3lu%% complete for table %u", - base[spl_idx] / (total_ops[spl_idx] / 100), - spl_idx); - + test_print_progress(¶ms->progress, + base[spl_idx] / (total_ops[spl_idx] / 100), + PLATFORM_CR "inserting/lookups %3lu%% complete " + "for table %u", + base[spl_idx] / (total_ops[spl_idx] / 100), + spl_idx); base[spl_idx] = __sync_fetch_and_add(&curr_op[spl_idx], op_granularity); if (base[spl_idx] >= total_ops[spl_idx]) { @@ -681,8 +686,8 @@ test_trunk_insert_lookup_thread(void *arg) uint64 *bases[NUM_OP_TYPES]; uint64 granularities[NUM_OP_TYPES]; uint64 offsets[NUM_OP_TYPES]; - uint8 insert_done; - uint64 num_ops = 0; + uint8 insert_done = 0; + uint64 num_ops = 0; random_state rs; random_init(&rs, seed, 0); diff --git a/tests/test_common.h b/tests/test_common.h index c7ab6b69..c359cffe 100644 --- a/tests/test_common.h +++ b/tests/test_common.h @@ -59,3 +59,11 @@ test_show_verbose_progress(test_exec_config *test_exec_cfg) void trace_wait_for_gdb(void); + +#define test_print_progress(progress_state, progress, ...) \ + do { \ + if (*progress_state != progress) { \ + *progress_state = progress; \ + platform_default_log(__VA_ARGS__); \ + } \ + } while (0)