Optimize RPCS3.log and limit it to 64 MiB

Use memory-mapped file for writing
This commit is contained in:
Nekotekina 2017-08-23 20:44:31 +03:00
parent 1716db14ed
commit 025a09ed87
3 changed files with 51 additions and 5 deletions

View File

@ -764,7 +764,13 @@ fs::file::file(const std::string& path, bs_t<open_mode> mode)
disp = test(mode & fs::trunc) ? TRUNCATE_EXISTING : OPEN_EXISTING; disp = test(mode & fs::trunc) ? TRUNCATE_EXISTING : OPEN_EXISTING;
} }
const HANDLE handle = CreateFileW(to_wchar(path).get(), access, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, disp, FILE_ATTRIBUTE_NORMAL, NULL); DWORD share = 0;
if (!test(mode & fs::unshare))
{
share |= FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
}
const HANDLE handle = CreateFileW(to_wchar(path).get(), access, share, NULL, disp, FILE_ATTRIBUTE_NORMAL, NULL);
if (handle == INVALID_HANDLE_VALUE) if (handle == INVALID_HANDLE_VALUE)
{ {

View File

@ -25,6 +25,7 @@ namespace fs
create, create,
trunc, trunc,
excl, excl,
unshare,
__bitset_enum_max __bitset_enum_max
}; };
@ -35,6 +36,7 @@ namespace fs
constexpr auto create = +open_mode::create; // Create file if it doesn't exist constexpr auto create = +open_mode::create; // Create file if it doesn't exist
constexpr auto trunc = +open_mode::trunc; // Clear opened file if it's not empty constexpr auto trunc = +open_mode::trunc; // Clear opened file if it's not empty
constexpr auto excl = +open_mode::excl; // Failure if the file already exists (used with `create`) constexpr auto excl = +open_mode::excl; // Failure if the file already exists (used with `create`)
constexpr auto unshare = +open_mode::unshare; // Prevent opening the file twice
constexpr auto rewrite = open_mode::write + open_mode::create + open_mode::trunc; constexpr auto rewrite = open_mode::write + open_mode::create + open_mode::trunc;

View File

@ -9,9 +9,11 @@
#include <unordered_map> #include <unordered_map>
#ifdef _WIN32 #ifdef _WIN32
#define NOMINMAX
#include <Windows.h> #include <Windows.h>
#else #else
#include <chrono> #include <chrono>
#include <sys/mman.h>
#endif #endif
static std::string empty_string() static std::string empty_string()
@ -45,15 +47,22 @@ void fmt_class_string<logs::level>::format(std::string& out, u64 arg)
namespace logs namespace logs
{ {
constexpr std::size_t s_log_size = 64 * 1024 * 1024;
class file_writer class file_writer
{ {
// Could be memory-mapped file
fs::file m_file; fs::file m_file;
#ifdef _WIN32
::HANDLE m_fmap;
#endif
atomic_t<std::size_t> m_pos{0};
uchar* m_fptr;
public: public:
file_writer(const std::string& name); file_writer(const std::string& name);
virtual ~file_writer() = default; virtual ~file_writer();
// Append raw data // Append raw data
void log(const char* text, std::size_t size); void log(const char* text, std::size_t size);
@ -63,6 +72,8 @@ namespace logs
{ {
file_listener(const std::string& name); file_listener(const std::string& name);
virtual ~file_listener() = default;
// Encode level, current thread name, channel name and write log message // Encode level, current thread name, channel name and write log message
virtual void log(u64 stamp, const message& msg, const std::string& prefix, const std::string& text) override; virtual void log(u64 stamp, const message& msg, const std::string& prefix, const std::string& text) override;
}; };
@ -273,10 +284,17 @@ logs::file_writer::file_writer(const std::string& name)
{ {
try try
{ {
if (!m_file.open(fs::get_config_dir() + name, fs::rewrite + fs::append)) if (!m_file.open(fs::get_config_dir() + name, fs::read + fs::write + fs::create + fs::trunc + fs::unshare))
{ {
fmt::throw_exception("Can't create log file %s (error %s)", name, fs::g_tls_error); fmt::throw_exception("Can't create log file %s (error %s)", name, fs::g_tls_error);
} }
#ifdef _WIN32
m_fmap = CreateFileMappingW(m_file.get_handle(), 0, PAGE_READWRITE, s_log_size >> 32, s_log_size & 0xffffffff, 0);
m_fptr = (uchar*)MapViewOfFile(m_fmap, FILE_MAP_WRITE, 0, 0, 0);
#else
m_fptr = (uchar*)::mmap(0, s_log_size, PROT_READ | PROT_WRITE, MAP_SHARED, m_file.get_handle(), 0);
#endif
} }
catch (...) catch (...)
{ {
@ -284,9 +302,29 @@ logs::file_writer::file_writer(const std::string& name)
} }
} }
logs::file_writer::~file_writer()
{
#ifdef _WIN32
UnmapViewOfFile(m_fptr);
CloseHandle(m_fmap);
m_file.seek(std::min(+m_pos, s_log_size));
SetEndOfFile(m_file.get_handle());
#else
::munmap(m_fptr, s_log_size);
m_file.trunc(std::min(+m_pos, s_log_size));
#endif
}
void logs::file_writer::log(const char* text, std::size_t size) void logs::file_writer::log(const char* text, std::size_t size)
{ {
m_file.write(text, size); // Acquire memory
const auto pos = m_pos.fetch_add(size);
// Write if possible
if (pos + size <= s_log_size)
{
std::memcpy(m_fptr + pos, text, size);
}
} }
logs::file_listener::file_listener(const std::string& name) logs::file_listener::file_listener(const std::string& name)