mirror of
https://github.com/WinampDesktop/winamp.git
synced 2025-06-21 07:25:39 -04:00
CPU/CodeCache: Rewrite using new-rec's block management
This commit is contained in:
@ -38,6 +38,8 @@ add_library(common
|
||||
minizip_helpers.cpp
|
||||
minizip_helpers.h
|
||||
path.h
|
||||
perf_scope.cpp
|
||||
perf_scope.h
|
||||
progress_callback.cpp
|
||||
progress_callback.h
|
||||
rectangle.h
|
||||
|
@ -28,6 +28,7 @@
|
||||
<ClInclude Include="memory_settings_interface.h" />
|
||||
<ClInclude Include="md5_digest.h" />
|
||||
<ClInclude Include="path.h" />
|
||||
<ClInclude Include="perf_scope.h" />
|
||||
<ClInclude Include="progress_callback.h" />
|
||||
<ClInclude Include="rectangle.h" />
|
||||
<ClInclude Include="scoped_guard.h" />
|
||||
@ -59,6 +60,7 @@
|
||||
<ClCompile Include="memory_settings_interface.cpp" />
|
||||
<ClCompile Include="md5_digest.cpp" />
|
||||
<ClCompile Include="minizip_helpers.cpp" />
|
||||
<ClCompile Include="perf_scope.cpp" />
|
||||
<ClCompile Include="progress_callback.cpp" />
|
||||
<ClCompile Include="sha1_digest.cpp" />
|
||||
<ClCompile Include="small_string.cpp" />
|
||||
|
@ -43,6 +43,7 @@
|
||||
<ClInclude Include="fastjmp.h" />
|
||||
<ClInclude Include="memmap.h" />
|
||||
<ClInclude Include="intrin.h" />
|
||||
<ClInclude Include="perf_scope.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="small_string.cpp" />
|
||||
@ -69,6 +70,7 @@
|
||||
<ClCompile Include="sha1_digest.cpp" />
|
||||
<ClCompile Include="fastjmp.cpp" />
|
||||
<ClCompile Include="memmap.cpp" />
|
||||
<ClCompile Include="perf_scope.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Natvis Include="bitfield.natvis" />
|
||||
|
@ -28,7 +28,7 @@
|
||||
#endif
|
||||
|
||||
template<typename T>
|
||||
static inline void MemsetPtrs(T* ptr, T value, u32 count)
|
||||
ALWAYS_INLINE_RELEASE static void MemsetPtrs(T* ptr, T value, u32 count)
|
||||
{
|
||||
static_assert(std::is_pointer_v<T>, "T is pointer type");
|
||||
static_assert(sizeof(T) == sizeof(void*), "T isn't a fat pointer");
|
||||
|
198
src/common/perf_scope.cpp
Normal file
198
src/common/perf_scope.cpp
Normal file
@ -0,0 +1,198 @@
|
||||
|
||||
// SPDX-FileCopyrightText: 2023 Connor McLaughlin <stenzek@gmail.com>, PCSX2 Team
|
||||
// SPDX-License-Identifier: GPL-3.0
|
||||
|
||||
#include "perf_scope.h"
|
||||
#include "assert.h"
|
||||
#include "string_util.h"
|
||||
|
||||
#include <array>
|
||||
#include <cstring>
|
||||
|
||||
#ifdef __linux__
|
||||
#include <atomic>
|
||||
#include <ctime>
|
||||
#include <elf.h>
|
||||
#include <mutex>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
// #define ProfileWithPerf
|
||||
// #define ProfileWithPerfJitDump
|
||||
|
||||
// Perf is only supported on linux
|
||||
#if defined(__linux__) && defined(ProfileWithPerf)
|
||||
|
||||
static std::FILE* s_map_file = nullptr;
|
||||
static bool s_map_file_opened = false;
|
||||
static std::mutex s_mutex;
|
||||
static void RegisterMethod(const void* ptr, size_t size, const char* symbol)
|
||||
{
|
||||
std::unique_lock lock(s_mutex);
|
||||
|
||||
if (!s_map_file)
|
||||
{
|
||||
if (s_map_file_opened)
|
||||
return;
|
||||
|
||||
char file[256];
|
||||
snprintf(file, std::size(file), "/tmp/perf-%d.map", getpid());
|
||||
s_map_file = std::fopen(file, "wb");
|
||||
s_map_file_opened = true;
|
||||
if (!s_map_file)
|
||||
return;
|
||||
}
|
||||
|
||||
std::fprintf(s_map_file, "%" PRIx64 " %zx %s\n", static_cast<u64>(reinterpret_cast<uintptr_t>(ptr)), size, symbol);
|
||||
std::fflush(s_map_file);
|
||||
}
|
||||
|
||||
#elif defined(__linux__) && defined(ProfileWithPerfJitDump)
|
||||
enum : u32
|
||||
{
|
||||
JIT_CODE_LOAD = 0,
|
||||
JIT_CODE_MOVE = 1,
|
||||
JIT_CODE_DEBUG_INFO = 2,
|
||||
JIT_CODE_CLOSE = 3,
|
||||
JIT_CODE_UNWINDING_INFO = 4
|
||||
};
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct JITDUMP_HEADER
|
||||
{
|
||||
u32 magic = 0x4A695444; // JiTD
|
||||
u32 version = 1;
|
||||
u32 header_size = sizeof(JITDUMP_HEADER);
|
||||
u32 elf_mach;
|
||||
u32 pad1 = 0;
|
||||
u32 pid;
|
||||
u64 timestamp;
|
||||
u64 flags = 0;
|
||||
};
|
||||
struct JITDUMP_RECORD_HEADER
|
||||
{
|
||||
u32 id;
|
||||
u32 total_size;
|
||||
u64 timestamp;
|
||||
};
|
||||
struct JITDUMP_CODE_LOAD
|
||||
{
|
||||
JITDUMP_RECORD_HEADER header;
|
||||
u32 pid;
|
||||
u32 tid;
|
||||
u64 vma;
|
||||
u64 code_addr;
|
||||
u64 code_size;
|
||||
u64 code_index;
|
||||
// name
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
static u64 JitDumpTimestamp()
|
||||
{
|
||||
struct timespec ts = {};
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
return (static_cast<u64>(ts.tv_sec) * 1000000000ULL) + static_cast<u64>(ts.tv_nsec);
|
||||
}
|
||||
|
||||
static FILE* s_jitdump_file = nullptr;
|
||||
static bool s_jitdump_file_opened = false;
|
||||
static std::mutex s_jitdump_mutex;
|
||||
static u32 s_jitdump_record_id;
|
||||
|
||||
static void RegisterMethod(const void* ptr, size_t size, const char* symbol)
|
||||
{
|
||||
const u32 namelen = std::strlen(symbol) + 1;
|
||||
|
||||
std::unique_lock lock(s_jitdump_mutex);
|
||||
if (!s_jitdump_file)
|
||||
{
|
||||
if (!s_jitdump_file_opened)
|
||||
{
|
||||
char file[256];
|
||||
snprintf(file, std::size(file), "jit-%d.dump", getpid());
|
||||
s_jitdump_file = fopen(file, "w+b");
|
||||
s_jitdump_file_opened = true;
|
||||
if (!s_jitdump_file)
|
||||
return;
|
||||
}
|
||||
|
||||
void* perf_marker = mmap(nullptr, 4096, PROT_READ | PROT_EXEC, MAP_PRIVATE, fileno(s_jitdump_file), 0);
|
||||
AssertMsg(perf_marker != MAP_FAILED, "Map perf marker");
|
||||
|
||||
JITDUMP_HEADER jh = {};
|
||||
#if defined(__aarch64__)
|
||||
jh.elf_mach = EM_AARCH64;
|
||||
#else
|
||||
jh.elf_mach = EM_X86_64;
|
||||
#endif
|
||||
jh.pid = getpid();
|
||||
jh.timestamp = JitDumpTimestamp();
|
||||
std::fwrite(&jh, sizeof(jh), 1, s_jitdump_file);
|
||||
}
|
||||
|
||||
JITDUMP_CODE_LOAD cl = {};
|
||||
cl.header.id = JIT_CODE_LOAD;
|
||||
cl.header.total_size = sizeof(cl) + namelen + static_cast<u32>(size);
|
||||
cl.header.timestamp = JitDumpTimestamp();
|
||||
cl.pid = getpid();
|
||||
cl.tid = syscall(SYS_gettid);
|
||||
cl.vma = 0;
|
||||
cl.code_addr = static_cast<u64>(reinterpret_cast<uintptr_t>(ptr));
|
||||
cl.code_size = static_cast<u64>(size);
|
||||
cl.code_index = s_jitdump_record_id++;
|
||||
std::fwrite(&cl, sizeof(cl), 1, s_jitdump_file);
|
||||
std::fwrite(symbol, namelen, 1, s_jitdump_file);
|
||||
std::fwrite(ptr, size, 1, s_jitdump_file);
|
||||
std::fflush(s_jitdump_file);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(__linux__) && (defined(ProfileWithPerf) || defined(ProfileWithPerfJitDump))
|
||||
|
||||
void PerfScope::Register(const void* ptr, size_t size, const char* symbol)
|
||||
{
|
||||
char full_symbol[128];
|
||||
if (HasPrefix())
|
||||
std::snprintf(full_symbol, std::size(full_symbol), "%s_%s", m_prefix, symbol);
|
||||
else
|
||||
StringUtil::Strlcpy(full_symbol, symbol, std::size(full_symbol));
|
||||
RegisterMethod(ptr, size, full_symbol);
|
||||
}
|
||||
|
||||
void PerfScope::RegisterPC(const void* ptr, size_t size, u32 pc)
|
||||
{
|
||||
char full_symbol[128];
|
||||
if (HasPrefix())
|
||||
std::snprintf(full_symbol, std::size(full_symbol), "%s_%08X", m_prefix, pc);
|
||||
else
|
||||
std::snprintf(full_symbol, std::size(full_symbol), "%08X", pc);
|
||||
RegisterMethod(ptr, size, full_symbol);
|
||||
}
|
||||
|
||||
void PerfScope::RegisterKey(const void* ptr, size_t size, const char* prefix, u64 key)
|
||||
{
|
||||
char full_symbol[128];
|
||||
if (HasPrefix())
|
||||
std::snprintf(full_symbol, std::size(full_symbol), "%s_%s%016" PRIX64, m_prefix, prefix, key);
|
||||
else
|
||||
std::snprintf(full_symbol, std::size(full_symbol), "%s%016" PRIX64, prefix, key);
|
||||
RegisterMethod(ptr, size, full_symbol);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void PerfScope::Register(const void* ptr, size_t size, const char* symbol)
|
||||
{
|
||||
}
|
||||
void PerfScope::RegisterPC(const void* ptr, size_t size, u32 pc)
|
||||
{
|
||||
}
|
||||
void PerfScope::RegisterKey(const void* ptr, size_t size, const char* prefix, u64 key)
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
20
src/common/perf_scope.h
Normal file
20
src/common/perf_scope.h
Normal file
@ -0,0 +1,20 @@
|
||||
// SPDX-FileCopyrightText: 2023 Connor McLaughlin <stenzek@gmail.com>, PCSX2 Team
|
||||
// SPDX-License-Identifier: GPL-3.0
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "types.h"
|
||||
|
||||
class PerfScope
|
||||
{
|
||||
public:
|
||||
constexpr PerfScope(const char* prefix) : m_prefix(prefix) {}
|
||||
bool HasPrefix() const { return (m_prefix && m_prefix[0]); }
|
||||
|
||||
void Register(const void* ptr, size_t size, const char* symbol);
|
||||
void RegisterPC(const void* ptr, size_t size, u32 pc);
|
||||
void RegisterKey(const void* ptr, size_t size, const char* prefix, u64 key);
|
||||
|
||||
private:
|
||||
const char* m_prefix;
|
||||
};
|
Reference in New Issue
Block a user