1/*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef BENCHMARKS_COMMON
17#define BENCHMARKS_COMMON
18
19#include <chrono>
20#include <cstdlib>
21#include <inttypes.h>
22#include "ffrt_inner.h"
23
24size_t COMPUTE_TIME_US = 0;
25uint64_t REPEAT = 1;
26uint64_t PREHOT_FFRT = 1;
27uint64_t FIB_NUM = 0;
28
29#define CLOCK std::chrono::steady_clock::now()
30#define TIME_BEGIN(t) auto __##t##_start = CLOCK
31#define TIME_END(t) \
32    do { \
33        decltype(__##t##_start) __##t##_cur = CLOCK; \
34        ("%-12s:%-4d %6lu us\n", __FILE__, __LINE__, \
35            long(std::chrono::duration_cast<std::chrono::microseconds>(__##t##_cur - __##t##_start).count())); \
36    } while (0)
37#define TIME_END_INFO(t, info) \
38    do { \
39        decltype(__##t##_start) __##t##_cur = CLOCK; \
40        printf("%-12s:%-4d %s %6lu us\n", __FILE__, __LINE__, info, \
41            long(std::chrono::duration_cast<std::chrono::microseconds>(__##t##_cur - __##t##_start).count())); \
42    } while (0)
43
44#define GET_ENV(name, var, default) \
45    do { \
46        auto __get_env_##name = getenv(#name); \
47        var = __get_env_##name ? atoi(__get_env_##name) : default; \
48        printf(#name " = %" PRIu64 "\n", (uint64_t)(var)); \
49    } while (0)
50
51#define EXPECT(cond) \
52    if (!(cond)) { \
53        printf(#cond " check failed\n"); \
54    }
55
56static inline void simulate_task_compute_time(size_t us)
57{
58    auto start = std::chrono::steady_clock::now();
59    size_t passed = 0;
60    while (passed < us) {
61        passed =
62            std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::steady_clock::now() - start).count();
63    }
64}
65
66static void FibFFRT(int x, int& y)
67{
68    if (x <= 1) {
69        y = x;
70    } else {
71        int y1;
72        int y2;
73        ffrt::submit([&]() { FibFFRT(x - 1, y1); }, {&x}, {&y1});
74        ffrt::submit([&]() { FibFFRT(x - 2, y2); }, {&x}, {&y2});
75        ffrt::wait({&y1, &y2});
76        y = y1 + y2;
77    }
78    simulate_task_compute_time(COMPUTE_TIME_US);
79}
80
81void PreHotFFRT(void)
82{
83    if (!PREHOT_FFRT) {
84        return;
85    }
86    int output;
87    ffrt::submit([&]() { FibFFRT(20, output); }, {}, {&output});
88    ffrt::wait({&output});
89}
90
91void GetEnvs(void)
92{
93    GET_ENV(COMPUTE_TIME_US, COMPUTE_TIME_US, 0);
94    GET_ENV(REPEAT, REPEAT, 1);
95    GET_ENV(PREHOT_FFRT, PREHOT_FFRT, 0);
96    GET_ENV(FIB_NUM, FIB_NUM, 5);
97}
98
99static inline void completely_paralle(uint32_t count, uint32_t duration, int64_t& time)
100{
101    uint32_t loop = count;
102    auto start = std::chrono::steady_clock::now();
103    while (loop--) {
104        ffrt::submit([&]() { simulate_task_compute_time(duration); }, {}, {});
105    }
106    ffrt::wait();
107    time = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::steady_clock::now() - start).count();
108}
109
110static inline void completely_serial(uint32_t count, uint32_t duration, int64_t& time)
111{
112    uint32_t x = 0;
113    uint32_t loop = count;
114    auto start = std::chrono::steady_clock::now();
115    while (loop--) {
116        ffrt::submit([&]() { simulate_task_compute_time(duration); }, {&x}, {&x});
117    }
118    ffrt::wait();
119    time = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::steady_clock::now() - start).count();
120}
121static inline void single_thread(uint32_t count, uint32_t duration, int64_t& time)
122{
123    uint32_t loop = count;
124    auto start = std::chrono::steady_clock::now();
125    while (loop--) {
126        simulate_task_compute_time(duration);
127    }
128    time = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::steady_clock::now() - start).count();
129}
130#endif