mirror of
https://github.com/hrydgard/ppsspp.git
synced 2024-11-26 23:10:38 +00:00
Add some jit benchmarking code.
This commit is contained in:
parent
47b731b882
commit
2efecc5c38
127
unittest/JitHarness.cpp
Normal file
127
unittest/JitHarness.cpp
Normal file
@ -0,0 +1,127 @@
|
||||
// Copyright (c) 2012- PPSSPP Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0 or later versions.
|
||||
|
||||
// This program 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 General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official git repository and contact information can be found at
|
||||
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
|
||||
|
||||
#include "base/timeutil.h"
|
||||
#include "Core/MIPS/JitCommon/JitCommon.h"
|
||||
#include "Core/MIPS/MIPSCodeUtils.h"
|
||||
#include "Core/MemMap.h"
|
||||
#include "Core/Core.h"
|
||||
#include "Core/CoreTiming.h"
|
||||
#include "Core/HLE/HLE.h"
|
||||
|
||||
struct InputState;
|
||||
// Temporary hacks around annoying linking errors. Copied from Headless.
|
||||
void D3D9_SwapBuffers() { }
|
||||
void GL_SwapBuffers() { }
|
||||
void NativeUpdate(InputState &input_state) { }
|
||||
void NativeRender() { }
|
||||
void NativeResized() { }
|
||||
|
||||
void System_SendMessage(const char *command, const char *parameter) {}
|
||||
bool System_InputBoxGetWString(const wchar_t *title, const std::wstring &defaultvalue, std::wstring &outvalue) { return false; }
|
||||
|
||||
#ifndef _WIN32
|
||||
InputState input_state;
|
||||
#endif
|
||||
|
||||
void UnitTestTerminator() {
|
||||
Core_Stop();
|
||||
}
|
||||
|
||||
HLEFunction UnitTestFakeSyscalls[] = {
|
||||
{0x1234BEEF, &UnitTestTerminator, "UnitTestTerminator"},
|
||||
};
|
||||
|
||||
double ExecCPUTest() {
|
||||
int blockTicks = 1000000;
|
||||
int total = 0;
|
||||
double st = real_time_now();
|
||||
do {
|
||||
for (int j = 0; j < 1000; ++j) {
|
||||
currentMIPS->pc = PSP_GetUserMemoryBase();
|
||||
coreState = CORE_RUNNING;
|
||||
|
||||
while (coreState == CORE_RUNNING) {
|
||||
mipsr4k.RunLoopUntil(blockTicks);
|
||||
}
|
||||
++total;
|
||||
}
|
||||
}
|
||||
while (real_time_now() - st < 0.5);
|
||||
double elapsed = real_time_now() - st;
|
||||
|
||||
return total / elapsed;
|
||||
}
|
||||
|
||||
static void SetupJitHarness() {
|
||||
// We register a syscall so we have an easy way to finish the test.
|
||||
RegisterModule("UnitTestFakeSyscalls", ARRAY_SIZE(UnitTestFakeSyscalls), UnitTestFakeSyscalls);
|
||||
|
||||
// This is pretty much the bare minimum required to setup jit.
|
||||
coreState = CORE_POWERUP;
|
||||
currentMIPS = &mipsr4k;
|
||||
Memory::g_MemorySize = Memory::RAM_NORMAL_SIZE;
|
||||
PSP_CoreParameter().cpuCore = CPU_INTERPRETER;
|
||||
PSP_CoreParameter().unthrottle = true;
|
||||
|
||||
Memory::Init();
|
||||
mipsr4k.Reset();
|
||||
CoreTiming::Init();
|
||||
}
|
||||
|
||||
static void DestroyJitHarness() {
|
||||
// Clear our custom module out to be safe.
|
||||
HLEShutdown();
|
||||
CoreTiming::Shutdown();
|
||||
Memory::Shutdown();
|
||||
mipsr4k.Shutdown();
|
||||
coreState = CORE_POWERDOWN;
|
||||
currentMIPS = nullptr;
|
||||
}
|
||||
|
||||
bool TestJit() {
|
||||
SetupJitHarness();
|
||||
|
||||
currentMIPS->pc = PSP_GetUserMemoryBase();
|
||||
u32 *p = (u32 *)Memory::GetPointer(currentMIPS->pc);
|
||||
|
||||
// TODO: Smarter way of seeding in the code sequence.
|
||||
for (int i = 0; i < 100; ++i) {
|
||||
*p++ = 0xD03B0000 | (1 >> 7) | (7 << 8);
|
||||
*p++ = 0xD03B0000 | (1 >> 7);
|
||||
*p++ = 0xD03B0000 | (7 << 8);
|
||||
*p++ = 0xD03B0000 | (1 >> 7) | (7 << 8);
|
||||
*p++ = 0xD03B0000 | (1 >> 7) | (7 << 8);
|
||||
*p++ = 0xD03B0000 | (1 >> 7) | (7 << 8);
|
||||
*p++ = 0xD03B0000 | (1 >> 7) | (7 << 8);
|
||||
}
|
||||
|
||||
*p++ = MIPS_MAKE_SYSCALL("UnitTestFakeSyscalls", "UnitTestTerminator");
|
||||
*p++ = MIPS_MAKE_BREAK(1);
|
||||
|
||||
double interp_speed = ExecCPUTest();
|
||||
|
||||
mipsr4k.UpdateCore(CPU_JIT);
|
||||
|
||||
double jit_speed = ExecCPUTest();
|
||||
|
||||
printf("Jit was %fx faster than interp.\n", jit_speed / interp_speed);
|
||||
|
||||
DestroyJitHarness();
|
||||
|
||||
return jit_speed >= interp_speed;
|
||||
}
|
20
unittest/JitHarness.h
Normal file
20
unittest/JitHarness.h
Normal file
@ -0,0 +1,20 @@
|
||||
// Copyright (c) 2012- PPSSPP Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0 or later versions.
|
||||
|
||||
// This program 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 General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official git repository and contact information can be found at
|
||||
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
|
||||
|
||||
#pragma once
|
||||
|
||||
bool TestJit();
|
@ -39,6 +39,8 @@
|
||||
#include "Core/Config.h"
|
||||
#include "Core/MIPS/MIPSVFPUUtils.h"
|
||||
|
||||
#include "unittest/JitHarness.h"
|
||||
|
||||
#define EXPECT_TRUE(a) if (!(a)) { printf("%s:%i: Test Fail\n", __FUNCTION__, __LINE__); return false; }
|
||||
#define EXPECT_FALSE(a) if ((a)) { printf("%s:%i: Test Fail\n", __FUNCTION__, __LINE__); return false; }
|
||||
#define EXPECT_EQ_FLOAT(a, b) if ((a) != (b)) { printf("%s:%i: Test Fail\n%f\nvs\n%f\n", __FUNCTION__, __LINE__, a, b); return false; }
|
||||
@ -417,17 +419,75 @@ bool TestVFPUSinCos() {
|
||||
return true;
|
||||
}
|
||||
|
||||
typedef bool (*TestFunc)();
|
||||
struct TestItem {
|
||||
const char *name;
|
||||
TestFunc func;
|
||||
};
|
||||
|
||||
#define TEST_ITEM(name) { #name, &Test ##name, }
|
||||
|
||||
TestItem availableTests[] = {
|
||||
TEST_ITEM(Asin),
|
||||
TEST_ITEM(SinCos),
|
||||
TEST_ITEM(ArmEmitter),
|
||||
TEST_ITEM(VFPUSinCos),
|
||||
TEST_ITEM(MathUtil),
|
||||
TEST_ITEM(Parsers),
|
||||
TEST_ITEM(Jit),
|
||||
};
|
||||
|
||||
int main(int argc, const char *argv[]) {
|
||||
cpu_info.bNEON = true;
|
||||
cpu_info.bVFP = true;
|
||||
cpu_info.bVFPv3 = true;
|
||||
cpu_info.bVFPv4 = true;
|
||||
g_Config.bEnableLogging = true;
|
||||
//TestAsin();
|
||||
//TestSinCos();
|
||||
//TestArmEmitter();
|
||||
TestVFPUSinCos();
|
||||
//TestMathUtil();
|
||||
//TestParsers();
|
||||
|
||||
bool allTests = false;
|
||||
TestFunc testFunc = nullptr;
|
||||
if (argc >= 2) {
|
||||
if (!strcasecmp(argv[1], "all")) {
|
||||
allTests = true;
|
||||
}
|
||||
for (auto f : availableTests) {
|
||||
if (!strcasecmp(argv[1], f.name)) {
|
||||
testFunc = f.func;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (allTests) {
|
||||
int passes = 0;
|
||||
int fails = 0;
|
||||
for (auto f : availableTests) {
|
||||
if (f.func()) {
|
||||
++passes;
|
||||
} else {
|
||||
printf("%s: FAILED\n", f.name);
|
||||
++fails;
|
||||
}
|
||||
}
|
||||
if (passes > 0) {
|
||||
printf("%d tests passed.\n", passes);
|
||||
}
|
||||
if (fails > 0) {
|
||||
return 2;
|
||||
}
|
||||
} else if (testFunc == nullptr) {
|
||||
fprintf(stderr, "You may select a test to run by passing an argument.\n");
|
||||
fprintf(stderr, "\n");
|
||||
fprintf(stderr, "Available tests:\n");
|
||||
for (auto f : availableTests) {
|
||||
fprintf(stderr, " * %s\n", f.name);
|
||||
}
|
||||
return 1;
|
||||
} else {
|
||||
if (!testFunc()) {
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -94,7 +94,9 @@
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>Ws2_32.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>Ws2_32.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;opengl32.lib;dsound.lib;glu32.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;comctl32.lib;d3d9.lib;dxguid.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalOptions>/ignore:4049 /ignore:4217 %(AdditionalOptions)</AdditionalOptions>
|
||||
<AdditionalLibraryDirectories>..\ffmpeg\Windows\x86\lib</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
@ -112,7 +114,9 @@
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>Ws2_32.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>Ws2_32.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;opengl32.lib;dsound.lib;glu32.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;comctl32.lib;d3d9.lib;dxguid.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalOptions>/ignore:4049 /ignore:4217 %(AdditionalOptions)</AdditionalOptions>
|
||||
<AdditionalLibraryDirectories>..\ffmpeg\Windows\x86_64\lib</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
@ -135,7 +139,9 @@
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<AdditionalDependencies>Ws2_32.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>Ws2_32.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;opengl32.lib;dsound.lib;glu32.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;comctl32.lib;d3d9.lib;dxguid.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalOptions>/ignore:4049 /ignore:4217 %(AdditionalOptions)</AdditionalOptions>
|
||||
<AdditionalLibraryDirectories>..\ffmpeg\Windows\x86\lib</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
@ -157,10 +163,14 @@
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<AdditionalDependencies>Ws2_32.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>Ws2_32.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;opengl32.lib;dsound.lib;glu32.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;comctl32.lib;d3d9.lib;dxguid.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalOptions>/ignore:4049 /ignore:4217 %(AdditionalOptions)</AdditionalOptions>
|
||||
<AdditionalLibraryDirectories>..\ffmpeg\Windows\x86_64\lib</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\native\ext\glew\glew.c" />
|
||||
<ClCompile Include="JitHarness.cpp" />
|
||||
<ClCompile Include="UnitTest.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
@ -170,12 +180,24 @@
|
||||
<ProjectReference Include="..\Core\Core.vcxproj">
|
||||
<Project>{533f1d30-d04d-47cc-ad71-20f658907e36}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\ext\libkirk\libkirk.vcxproj">
|
||||
<Project>{3baae095-e0ab-4b0e-b5df-ce39c8ae31de}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\ext\zlib\zlib.vcxproj">
|
||||
<Project>{f761046e-6c38-4428-a5f1-38391a37bb34}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\GPU\GPU.vcxproj">
|
||||
<Project>{457f45d2-556f-47bc-a31d-aff0d15beaed}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\native\native.vcxproj">
|
||||
<Project>{c4df647e-80ea-4111-a0a8-218b1b711e18}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\UI\UI.vcxproj">
|
||||
<Project>{004b8d11-2be3-4bd9-ab40-2be04cf2096f}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="JitHarness.h" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
|
@ -2,5 +2,10 @@
|
||||
<Project ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<ClCompile Include="UnitTest.cpp" />
|
||||
<ClCompile Include="..\native\ext\glew\glew.c" />
|
||||
<ClCompile Include="JitHarness.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="JitHarness.h" />
|
||||
</ItemGroup>
|
||||
</Project>
|
Loading…
Reference in New Issue
Block a user