VirtualBox

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

Last change on this file was 106061, checked in by vboxsync, 8 weeks ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 9.1 KB
Line 
1/* $Id: tstPrfRT.cpp 106061 2024-09-16 14:03:52Z vboxsync $ */
2/** @file
3 * IPRT testcase - profile some of the important functions.
4 */
5
6/*
7 * Copyright (C) 2006-2024 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
69static void 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 RT_NOREF(cNsMax, cNsMin);
128 //RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS,
129 // "%-32s %5lld / %5lld / %5lld ns per call (%u calls %lld ns)\n",
130 // pszOperation, cNsMin, cNs / (uint64_t)cTimes, cNsMax, cTimes, cNs);
131 //RTTestValueF(g_hTest, cNsMin, RTTESTUNIT_NS_PER_CALL, "%s min", pszOperation);
132 RTTestValueF(g_hTest, cNs / (uint64_t)cTimes, RTTESTUNIT_NS_PER_CALL, "%s avg", pszOperation);
133 //RTTestValueF(g_hTest, cNsMax, RTTESTUNIT_NS_PER_CALL, "%s max", pszOperation);
134}
135
136# define ITERATE(preexpr, expr, postexpr, cIterations) \
137 for (i = 0, u64TotalTS = 0, u64MinTS = UINT64_MAX, u64MaxTS = 0; i < (cIterations); i++) \
138 { \
139 { preexpr } \
140 uint64_t u64StartTS = RTTimeNanoTS(); \
141 { expr } \
142 uint64_t u64ElapsedTS = RTTimeNanoTS() - u64StartTS; \
143 { postexpr } \
144 if (u64ElapsedTS > u64MinTS * 32) \
145 { \
146 i--; \
147 continue; \
148 } \
149 if (u64ElapsedTS < u64MinTS) \
150 u64MinTS = u64ElapsedTS; \
151 if (u64ElapsedTS > u64MaxTS) \
152 u64MaxTS = u64ElapsedTS; \
153 u64TotalTS += u64ElapsedTS; \
154 }
155
156#endif /* !AMD64 && !X86 */
157
158
159int main(int argc, char **argv)
160{
161 uint64_t u64TotalTS;
162 uint64_t u64MinTS;
163 uint64_t u64MaxTS;
164 uint32_t i;
165
166 RTEXITCODE rcExit = RTTestInitExAndCreate(argc, &argv, argc == 2 ? RTR3INIT_FLAGS_SUPLIB : 0, "tstRTPrf", &g_hTest);
167 if (rcExit != RTEXITCODE_SUCCESS)
168 return rcExit;
169 RTTestBanner(g_hTest);
170
171 /*
172 * RTTimeNanoTS, RTTimeProgramNanoTS, RTTimeMilliTS, and RTTimeProgramMilliTS.
173 */
174 ITERATE(RT_NOTHING, RTTimeNanoTS();, RT_NOTHING, _32M);
175 PrintResult(u64TotalTS, u64MaxTS, u64MinTS, i, "RTTimeNanoTS");
176
177 ITERATE(RT_NOTHING, RTTimeProgramNanoTS();, RT_NOTHING, UINT32_C(1000000));
178 PrintResult(u64TotalTS, u64MaxTS, u64MinTS, i, "RTTimeProgramNanoTS");
179
180 ITERATE(RT_NOTHING, RTTimeMilliTS();, RT_NOTHING, UINT32_C(1000000));
181 PrintResult(u64TotalTS, u64MaxTS, u64MinTS, i, "RTTimeMilliTS");
182
183 ITERATE(RT_NOTHING, RTTimeProgramMilliTS();, RT_NOTHING, UINT32_C(1000000));
184 PrintResult(u64TotalTS, u64MaxTS, u64MinTS, i, "RTTimeProgramMilliTS");
185
186 /*
187 * RTTimeNow
188 */
189 RTTIMESPEC Time;
190 ITERATE(RT_NOTHING, RTTimeNow(&Time);, RT_NOTHING, UINT32_C(1000000));
191 PrintResult(u64TotalTS, u64MaxTS, u64MinTS, i, "RTTimeNow");
192
193 /*
194 * RTLogDefaultInstance()
195 */
196 ITERATE(RT_NOTHING, RTLogDefaultInstance();, RT_NOTHING, UINT32_C(1000000));
197 PrintResult(u64TotalTS, u64MaxTS, u64MinTS, i, "RTLogDefaultInstance");
198
199 /*
200 * RTThreadSelf and RTThreadNativeSelf
201 */
202 ITERATE(RT_NOTHING, RTThreadSelf();, RT_NOTHING, UINT32_C(1000000));
203 PrintResult(u64TotalTS, u64MaxTS, u64MinTS, i, "RTThreadSelf");
204
205 ITERATE(RT_NOTHING, RTThreadNativeSelf();, RT_NOTHING, UINT32_C(1000000));
206 PrintResult(u64TotalTS, u64MaxTS, u64MinTS, i, "RTThreadNativeSelf");
207
208#if defined(RT_ARCH_X86) || defined(RT_ARCH_AMD64)
209 /*
210 * Registers vs stack.
211 */
212 ITERATE(RT_NOTHING, tstRTPRfARegisterAccess();, RT_NOTHING, UINT32_C(1000));
213 uint64_t const cRegTotal = u64TotalTS;
214 //PrintResult(u64TotalTS, u64MaxTS, u64MinTS, i, "Register only algorithm");
215
216 ITERATE(RT_NOTHING, tstRTPRfAMemoryAccess();, RT_NOTHING, UINT32_C(1000));
217 uint64_t const cMemTotal = u64TotalTS;
218 //PrintResult(u64TotalTS, u64MaxTS, u64MinTS, i, "Memory only algorithm");
219
220 ITERATE(RT_NOTHING, tstRTPRfAMemoryUnalignedAccess();, RT_NOTHING, UINT32_C(1000));
221 uint64_t const cMemUnalignedTotal = u64TotalTS;
222 //PrintResult(u64TotalTS, u64MaxTS, u64MinTS, i, "Memory only algorithm");
223
224 uint64_t const cSlower100 = cMemTotal * 100 / cRegTotal;
225 RTTestValue(g_hTest, "Memory instead of registers slowdown", cSlower100, RTTESTUNIT_PCT);
226 uint64_t const cUnalignedSlower100 = cMemUnalignedTotal * 100 / cRegTotal;
227 RTTestValue(g_hTest, "Unaligned memory instead of registers slowdown", cUnalignedSlower100, RTTESTUNIT_PCT);
228#endif
229
230 return RTTestSummaryAndDestroy(g_hTest);
231}
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