Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'tests/gtests/blenlib/BLI_task_performance_test.cc')
-rw-r--r--tests/gtests/blenlib/BLI_task_performance_test.cc192
1 files changed, 192 insertions, 0 deletions
diff --git a/tests/gtests/blenlib/BLI_task_performance_test.cc b/tests/gtests/blenlib/BLI_task_performance_test.cc
new file mode 100644
index 00000000000..ecc012aa47a
--- /dev/null
+++ b/tests/gtests/blenlib/BLI_task_performance_test.cc
@@ -0,0 +1,192 @@
+/* Apache License, Version 2.0 */
+
+#include "testing/testing.h"
+#include "BLI_ressource_strings.h"
+
+#include "atomic_ops.h"
+
+#define GHASH_INTERNAL_API
+
+extern "C" {
+#include "BLI_utildefines.h"
+
+#include "BLI_listbase.h"
+#include "BLI_mempool.h"
+#include "BLI_task.h"
+
+#include "PIL_time.h"
+
+#include "MEM_guardedalloc.h"
+}
+
+/* *** Parallel iterations over double-linked list items. *** */
+
+#define NUM_RUN_AVERAGED 100
+
+static uint gen_pseudo_random_number(uint num)
+{
+ /* Note: this is taken from BLI_ghashutil_uinthash(), don't want to depend on external code that
+ * might change here... */
+ num += ~(num << 16);
+ num ^= (num >> 5);
+ num += (num << 3);
+ num ^= (num >> 13);
+ num += ~(num << 9);
+ num ^= (num >> 17);
+
+ /* Make final number in [65 - 16385] range. */
+ return ((num & 255) << 6) + 1;
+}
+
+static void task_listbase_light_iter_func(void *UNUSED(userdata), Link *item, int index)
+{
+ LinkData *data = (LinkData *)item;
+
+ data->data = POINTER_FROM_INT(POINTER_AS_INT(data->data) + index);
+}
+
+static void task_listbase_light_membarrier_iter_func(void *userdata, Link *item, int index)
+{
+ LinkData *data = (LinkData *)item;
+ int *count = (int *)userdata;
+
+ data->data = POINTER_FROM_INT(POINTER_AS_INT(data->data) + index);
+ atomic_sub_and_fetch_uint32((uint32_t *)count, 1);
+}
+
+static void task_listbase_heavy_iter_func(void *UNUSED(userdata), Link *item, int index)
+{
+ LinkData *data = (LinkData *)item;
+
+ /* 'Random' number of iterations. */
+ const uint num = gen_pseudo_random_number((uint)index);
+
+ for (uint i = 0; i < num; i++) {
+ data->data = POINTER_FROM_INT(POINTER_AS_INT(data->data) + ((i % 2) ? -index : index));
+ }
+}
+
+static void task_listbase_heavy_membarrier_iter_func(void *userdata, Link *item, int index)
+{
+ LinkData *data = (LinkData *)item;
+ int *count = (int *)userdata;
+
+ /* 'Random' number of iterations. */
+ const uint num = gen_pseudo_random_number((uint)index);
+
+ for (uint i = 0; i < num; i++) {
+ data->data = POINTER_FROM_INT(POINTER_AS_INT(data->data) + ((i % 2) ? -index : index));
+ }
+ atomic_sub_and_fetch_uint32((uint32_t *)count, 1);
+}
+
+static void task_listbase_test_do(ListBase *list,
+ const int num_items,
+ int *num_items_tmp,
+ const char *id,
+ TaskParallelListbaseFunc func,
+ const bool use_threads,
+ const bool check_num_items_tmp)
+{
+ double averaged_timing = 0.0;
+ for (int i = 0; i < NUM_RUN_AVERAGED; i++) {
+ const double init_time = PIL_check_seconds_timer();
+ BLI_task_parallel_listbase(list, num_items_tmp, func, use_threads);
+ averaged_timing += PIL_check_seconds_timer() - init_time;
+
+ /* Those checks should ensure us all items of the listbase were processed once, and only once -
+ * as expected. */
+ if (check_num_items_tmp) {
+ EXPECT_EQ(*num_items_tmp, 0);
+ }
+ LinkData *item;
+ int j;
+ for (j = 0, item = (LinkData *)list->first; j < num_items && item != NULL;
+ j++, item = item->next) {
+ EXPECT_EQ(POINTER_AS_INT(item->data), j);
+ item->data = POINTER_FROM_INT(0);
+ }
+ EXPECT_EQ(num_items, j);
+
+ *num_items_tmp = num_items;
+ }
+
+ printf("\t%s: done in %fs on average over %d runs\n",
+ id,
+ averaged_timing / NUM_RUN_AVERAGED,
+ NUM_RUN_AVERAGED);
+}
+
+static void task_listbase_test(const char *id, const int nbr, const bool use_threads)
+{
+ printf("\n========== STARTING %s ==========\n", id);
+
+ ListBase list = {NULL, NULL};
+ LinkData *items_buffer = (LinkData *)MEM_calloc_arrayN(nbr, sizeof(*items_buffer), __func__);
+
+ BLI_threadapi_init();
+
+ int num_items = 0;
+ for (int i = 0; i < nbr; i++) {
+ BLI_addtail(&list, &items_buffer[i]);
+ num_items++;
+ }
+ int num_items_tmp = num_items;
+
+ task_listbase_test_do(&list,
+ num_items,
+ &num_items_tmp,
+ "Light iter",
+ task_listbase_light_iter_func,
+ use_threads,
+ false);
+
+ task_listbase_test_do(&list,
+ num_items,
+ &num_items_tmp,
+ "Light iter with mem barrier",
+ task_listbase_light_membarrier_iter_func,
+ use_threads,
+ true);
+
+ task_listbase_test_do(&list,
+ num_items,
+ &num_items_tmp,
+ "Heavy iter",
+ task_listbase_heavy_iter_func,
+ use_threads,
+ false);
+
+ task_listbase_test_do(&list,
+ num_items,
+ &num_items_tmp,
+ "Heavy iter with mem barrier",
+ task_listbase_heavy_membarrier_iter_func,
+ use_threads,
+ true);
+
+ MEM_freeN(items_buffer);
+ BLI_threadapi_exit();
+
+ printf("========== ENDED %s ==========\n\n", id);
+}
+
+TEST(task, ListBaseIterNoThread10k)
+{
+ task_listbase_test("ListBase parallel iteration - Single thread - 10000 items", 10000, false);
+}
+
+TEST(task, ListBaseIter10k)
+{
+ task_listbase_test("ListBase parallel iteration - Threaded - 10000 items", 10000, true);
+}
+
+TEST(task, ListBaseIterNoThread100k)
+{
+ task_listbase_test("ListBase parallel iteration - Single thread - 100000 items", 100000, false);
+}
+
+TEST(task, ListBaseIter100k)
+{
+ task_listbase_test("ListBase parallel iteration - Threaded - 100000 items", 100000, true);
+}