VirtualBox

source: vbox/trunk/src/VBox/Runtime/testcase/tstPrfRT.cpp@ 96781

Last change on this file since 96781 was 96407, checked in by vboxsync, 2 years ago

scm copyright and license note update

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 9.1 KB
Line 
1/* $Id: tstPrfRT.cpp 96407 2022-08-22 17:43:14Z vboxsync $ */
2/** @file
3 * IPRT testcase - profile some of the important functions.
4 */
5
6/*
7 * Copyright (C) 2006-2022 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * The contents of this file may alternatively be used under the terms
26 * of the Common Development and Distribution License Version 1.0
27 * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
28 * in the VirtualBox distribution, in which case the provisions of the
29 * CDDL are applicable instead of those of the GPL.
30 *
31 * You may elect to license modified versions of this file under the
32 * terms and conditions of either the GPL or the CDDL or both.
33 *
34 * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
35 */
36
37
38/*********************************************************************************************************************************
39* Header Files *
40*********************************************************************************************************************************/
41#include <iprt/initterm.h>
42#include <iprt/time.h>
43#include <iprt/log.h>
44#include <iprt/test.h>
45#include <iprt/thread.h>
46#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
47# include <iprt/asm-amd64-x86.h>
48#endif
49
50
51/*********************************************************************************************************************************
52* Internal Functions *
53*********************************************************************************************************************************/
54#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
55DECLASM(void) tstRTPRfAMemoryAccess(void);
56DECLASM(void) tstRTPRfARegisterAccess(void);
57DECLASM(void) tstRTPRfAMemoryUnalignedAccess(void);
58#endif
59
60
61/*********************************************************************************************************************************
62* Global Variables *
63*********************************************************************************************************************************/
64static RTTEST g_hTest;
65
66
67#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
68
69void PrintResult(uint64_t u64Ticks, uint64_t u64MaxTicks, uint64_t u64MinTicks, unsigned cTimes, const char *pszOperation)
70{
71 //RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS,
72 // "%-32s %5lld / %5lld / %5lld ticks per call (%u calls %lld ticks)\n",
73 // pszOperation, u64MinTicks, u64Ticks / (uint64_t)cTimes, u64MaxTicks, cTimes, u64Ticks);
74 //RTTestValueF(g_hTest, u64MinTicks, RTTESTUNIT_NONE, "%s min ticks", pszOperation);
75 RTTestValueF(g_hTest, u64Ticks / (uint64_t)cTimes, RTTESTUNIT_NONE, "%s avg ticks", pszOperation);
76 //RTTestValueF(g_hTest, u64MaxTicks, RTTESTUNIT_NONE, "%s max ticks", pszOperation);
77 RT_NOREF_PV(u64MaxTicks); RT_NOREF_PV(u64MinTicks);
78}
79
80# define ITERATE(preexpr, expr, postexpr, cIterations) \
81 AssertCompile(((cIterations) % 8) == 0); \
82 /* Min and max value. */ \
83 for (i = 0, u64MinTS = UINT64_MAX, u64MaxTS = 0; i < (cIterations); i++) \
84 { \
85 { preexpr } \
86 uint64_t u64StartTS = ASMReadTSC(); \
87 { expr } \
88 uint64_t u64ElapsedTS = ASMReadTSC() - u64StartTS; \
89 { postexpr } \
90 if (u64ElapsedTS > u64MinTS * 32) \
91 { \
92 i--; \
93 continue; \
94 } \
95 if (u64ElapsedTS < u64MinTS) \
96 u64MinTS = u64ElapsedTS; \
97 if (u64ElapsedTS > u64MaxTS) \
98 u64MaxTS = u64ElapsedTS; \
99 } \
100 { \
101 /* Calculate a good average value (may be smaller than min). */ \
102 i = (cIterations); \
103 AssertRelease((i % 8) == 0); \
104 { preexpr } \
105 uint64_t u64StartTS = ASMReadTSC(); \
106 while (i != 0) \
107 { \
108 { expr } \
109 { expr } \
110 { expr } \
111 { expr } \
112 { expr } \
113 { expr } \
114 { expr } \
115 { expr } \
116 i -= 8; \
117 } \
118 u64TotalTS = ASMReadTSC() - u64StartTS; \
119 { postexpr } \
120 i = (cIterations); \
121 }
122
123#else /* !AMD64 && !X86 */
124
125void PrintResult(uint64_t cNs, uint64_t cNsMax, uint64_t cNsMin, unsigned cTimes, const char *pszOperation)
126{
127 //RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS,
128 // "%-32s %5lld / %5lld / %5lld ns per call (%u calls %lld ns)\n",
129 // pszOperation, cNsMin, cNs / (uint64_t)cTimes, cNsMax, cTimes, cNs);
130 //RTTestValueF(g_hTest, cNsMin, RTTESTUNIT_NS_PER_CALL, "%s min", pszOperation);
131 RTTestValueF(g_hTest, cNs / (uint64_t)cTimes, RTTESTUNIT_NS_PER_CALL, "%s avg", pszOperation);
132 //RTTestValueF(g_hTest, cNsMax, RTTESTUNIT_NS_PER_CALL, "%s max", pszOperation);
133}
134
135# define ITERATE(preexpr, expr, postexpr, cIterations) \
136 for (i = 0, u64TotalTS = 0, u64MinTS = UINT64_MAX, u64MaxTS = 0; i < (cIterations); i++) \
137 { \
138 { preexpr } \
139 uint64_t u64StartTS = RTTimeNanoTS(); \
140 { expr } \
141 uint64_t u64ElapsedTS = RTTimeNanoTS() - u64StartTS; \
142 { postexpr } \
143 if (u64ElapsedTS > u64MinTS * 32) \
144 { \
145 i--; \
146 continue; \
147 } \
148 if (u64ElapsedTS < u64MinTS) \
149 u64MinTS = u64ElapsedTS; \
150 if (u64ElapsedTS > u64MaxTS) \
151 u64MaxTS = u64ElapsedTS; \
152 u64TotalTS += u64ElapsedTS; \
153 }
154
155#endif /* !AMD64 && !X86 */
156
157
158int main(int argc, char **argv)
159{
160 uint64_t u64TotalTS;
161 uint64_t u64MinTS;
162 uint64_t u64MaxTS;
163 uint32_t i;
164
165 RTEXITCODE rcExit = RTTestInitExAndCreate(argc, &argv, argc == 2 ? RTR3INIT_FLAGS_SUPLIB : 0, "tstRTPrf", &g_hTest);
166 if (rcExit != RTEXITCODE_SUCCESS)
167 return rcExit;
168 RTTestBanner(g_hTest);
169
170 /*
171 * RTTimeNanoTS, RTTimeProgramNanoTS, RTTimeMilliTS, and RTTimeProgramMilliTS.
172 */
173 ITERATE(RT_NOTHING, RTTimeNanoTS();, RT_NOTHING, _32M);
174 PrintResult(u64TotalTS, u64MaxTS, u64MinTS, i, "RTTimeNanoTS");
175
176 ITERATE(RT_NOTHING, RTTimeProgramNanoTS();, RT_NOTHING, UINT32_C(1000000));
177 PrintResult(u64TotalTS, u64MaxTS, u64MinTS, i, "RTTimeProgramNanoTS");
178
179 ITERATE(RT_NOTHING, RTTimeMilliTS();, RT_NOTHING, UINT32_C(1000000));
180 PrintResult(u64TotalTS, u64MaxTS, u64MinTS, i, "RTTimeMilliTS");
181
182 ITERATE(RT_NOTHING, RTTimeProgramMilliTS();, RT_NOTHING, UINT32_C(1000000));
183 PrintResult(u64TotalTS, u64MaxTS, u64MinTS, i, "RTTimeProgramMilliTS");
184
185 /*
186 * RTTimeNow
187 */
188 RTTIMESPEC Time;
189 ITERATE(RT_NOTHING, RTTimeNow(&Time);, RT_NOTHING, UINT32_C(1000000));
190 PrintResult(u64TotalTS, u64MaxTS, u64MinTS, i, "RTTimeNow");
191
192 /*
193 * RTLogDefaultInstance()
194 */
195 ITERATE(RT_NOTHING, RTLogDefaultInstance();, RT_NOTHING, UINT32_C(1000000));
196 PrintResult(u64TotalTS, u64MaxTS, u64MinTS, i, "RTLogDefaultInstance");
197
198 /*
199 * RTThreadSelf and RTThreadNativeSelf
200 */
201 ITERATE(RT_NOTHING, RTThreadSelf();, RT_NOTHING, UINT32_C(1000000));
202 PrintResult(u64TotalTS, u64MaxTS, u64MinTS, i, "RTThreadSelf");
203
204 ITERATE(RT_NOTHING, RTThreadNativeSelf();, RT_NOTHING, UINT32_C(1000000));
205 PrintResult(u64TotalTS, u64MaxTS, u64MinTS, i, "RTThreadNativeSelf");
206
207#if defined(RT_ARCH_X86) || defined(RT_ARCH_AMD64)
208 /*
209 * Registers vs stack.
210 */
211 ITERATE(RT_NOTHING, tstRTPRfARegisterAccess();, RT_NOTHING, UINT32_C(1000));
212 uint64_t const cRegTotal = u64TotalTS;
213 //PrintResult(u64TotalTS, u64MaxTS, u64MinTS, i, "Register only algorithm");
214
215 ITERATE(RT_NOTHING, tstRTPRfAMemoryAccess();, RT_NOTHING, UINT32_C(1000));
216 uint64_t const cMemTotal = u64TotalTS;
217 //PrintResult(u64TotalTS, u64MaxTS, u64MinTS, i, "Memory only algorithm");
218
219 ITERATE(RT_NOTHING, tstRTPRfAMemoryUnalignedAccess();, RT_NOTHING, UINT32_C(1000));
220 uint64_t const cMemUnalignedTotal = u64TotalTS;
221 //PrintResult(u64TotalTS, u64MaxTS, u64MinTS, i, "Memory only algorithm");
222
223 uint64_t const cSlower100 = cMemTotal * 100 / cRegTotal;
224 RTTestValue(g_hTest, "Memory instead of registers slowdown", cSlower100, RTTESTUNIT_PCT);
225 uint64_t const cUnalignedSlower100 = cMemUnalignedTotal * 100 / cRegTotal;
226 RTTestValue(g_hTest, "Unaligned memory instead of registers slowdown", cUnalignedSlower100, RTTESTUNIT_PCT);
227#endif
228
229 return RTTestSummaryAndDestroy(g_hTest);
230}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette