/* Measure bsearch functions. Copyright (C) 2022-2025 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library 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. The GNU C Library 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 the GNU C Library; if not, see . */ #define TEST_MAIN #define TEST_NAME "bsearch" #define ARRAY_SIZE 100000 #define LOOP_ITERS 100000000 /* Directly including leads to the use of an inline version of bsearch(), which may cause our test cases to be optimized away by the compiler due to predictability. To address this, we should include directly and replace __extern_inline with __attribute__((noinline)) to ensure the compiler does not inline the function. Additionally, we need to add some macros required for compilation. */ #include #define __extern_inline __attribute__((noinline)) #define __GNUC_PREREQ(x, y) 0 typedef int (*__compar_fn_t) (const void *, const void *); #include #undef __extern_inline #undef __GNUC_PREREQ #include "json-lib.h" #include "bench-timing.h" int arr[ARRAY_SIZE]; static int comp_asc (const void *p1, const void *p2) { int x1 = *(int *) p1; int x2 = *(int *) p2; if (x1 < x2) return -1; if (x1 > x2) return 1; return 0; } static int comp_desc (const void *p1, const void *p2) { int x1 = *(int *) p1; int x2 = *(int *) p2; if (x1 > x2) return -1; if (x1 < x2) return 1; return 0; } static void do_bench (json_ctx_t *json_ctx, bool ascending, bool contained) { size_t i, iters = LOOP_ITERS; timing_t start, stop, cur; int key; volatile __attribute__((__unused__)) void *res; for (i = 0; i < ARRAY_SIZE; ++i) { arr[i] = (ascending ? i : ARRAY_SIZE - 1 - i) << 1; } json_element_object_begin (json_ctx); json_attr_uint (json_ctx, "array-size", ARRAY_SIZE); json_attr_uint (json_ctx, "element-size", sizeof(arr[0])); json_attr_string (json_ctx, "key-pattern", ascending ? "ascending" : "descending"); json_attr_string (json_ctx, "contained", contained ? "yes" : "no"); json_attr_string (json_ctx, "simple", "yes"); TIMING_NOW (start); for (i = 0; i < iters; ++i) { key = (i % ARRAY_SIZE << 1) + !contained; res = bsearch(&key, arr, ARRAY_SIZE, sizeof(arr[0]), ascending ? comp_asc : comp_desc); } TIMING_NOW (stop); TIMING_DIFF (cur, start, stop); json_attr_double (json_ctx, "timing", (double) cur / (double) iters); json_element_object_end (json_ctx); } int do_test (void) { json_ctx_t json_ctx; json_init (&json_ctx, 0, stdout); json_document_begin (&json_ctx); json_attr_string (&json_ctx, "timing_type", TIMING_TYPE); json_attr_object_begin (&json_ctx, "functions"); json_attr_object_begin (&json_ctx, TEST_NAME); json_attr_string (&json_ctx, "bench-variant", "default"); json_array_begin (&json_ctx, "results"); for (int ascending = 0; ascending < 2; ++ascending) { for (int contained = 0; contained < 2; ++contained) { do_bench(&json_ctx, ascending, contained); } } json_array_end (&json_ctx); json_attr_object_end (&json_ctx); json_attr_object_end (&json_ctx); json_document_end (&json_ctx); return 0; } #include