mirror of
https://github.com/RPCS3/rpcs3.git
synced 2026-04-05 22:46:56 +00:00
RPCS3: Notify RAM shortage, Log current and peak RAM usage
This commit is contained in:
parent
2702417192
commit
a4523651c7
7 changed files with 70 additions and 45 deletions
|
|
@ -2879,6 +2879,16 @@ void thread_base::exec()
|
|||
}
|
||||
}
|
||||
|
||||
if (auto [total, current] = utils::get_memory_usage(); total - current <= 256 * 1024 * 1024)
|
||||
{
|
||||
if (reason_buf.empty())
|
||||
{
|
||||
reason_buf = std::string{reason};
|
||||
}
|
||||
|
||||
fmt::append(reason_buf, " (Possible RAM deficiency: free RAM: %dMB)", (total - current) / (1024 * 1024));
|
||||
}
|
||||
|
||||
if (!reason_buf.empty())
|
||||
{
|
||||
reason = reason_buf;
|
||||
|
|
|
|||
|
|
@ -8615,7 +8615,7 @@ spu_program spu_recompiler_base::analyse(const be_t<u32>* ls, u32 entry_point, s
|
|||
// Blocks starting from 0x0 or invalid instruction won't be compiled, may need special interpreter fallback
|
||||
}
|
||||
|
||||
if (!m_patterns.empty())
|
||||
if (!m_patterns.empty() && g_cfg.core.spu_debug)
|
||||
{
|
||||
std::string out_dump;
|
||||
dump(result, out_dump);
|
||||
|
|
|
|||
|
|
@ -900,10 +900,8 @@ lv2_file::open_raw_result_t lv2_file::open_raw(const std::string& local_path, s3
|
|||
switch (auto error = fs::g_tls_error)
|
||||
{
|
||||
case fs::error::noent: return {CELL_ENOENT};
|
||||
default: sys_fs.error("lv2_file::open(): unknown error %s", error); break;
|
||||
default: fmt::throw_exception("unknown error %s", error);
|
||||
}
|
||||
|
||||
return {CELL_EIO};
|
||||
}
|
||||
|
||||
if (flags & CELL_FS_O_MSELF && !verify_mself(file))
|
||||
|
|
@ -1374,8 +1372,7 @@ error_code sys_fs_opendir(ppu_thread& ppu, vm::cptr<char> path, vm::ptr<u32> fd)
|
|||
}
|
||||
default:
|
||||
{
|
||||
sys_fs.error("sys_fs_opendir(): unknown error %s", error);
|
||||
return {CELL_EIO, path};
|
||||
fmt::throw_exception("unknown error %s", error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1597,8 +1594,7 @@ error_code sys_fs_stat(ppu_thread& ppu, vm::cptr<char> path, vm::ptr<CellFsStat>
|
|||
}
|
||||
default:
|
||||
{
|
||||
sys_fs.error("sys_fs_stat(): unknown error %s", error);
|
||||
return {CELL_EIO, path};
|
||||
fmt::throw_exception("unknown error %s", error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1732,10 +1728,8 @@ error_code sys_fs_mkdir(ppu_thread& ppu, vm::cptr<char> path, s32 mode)
|
|||
{
|
||||
return {sys_fs.warning, CELL_EEXIST, path};
|
||||
}
|
||||
default: sys_fs.error("sys_fs_mkdir(): unknown error %s", error);
|
||||
default: fmt::throw_exception("unknown error %s", error);
|
||||
}
|
||||
|
||||
return {CELL_EIO, path}; // ???
|
||||
}
|
||||
|
||||
sys_fs.notice("sys_fs_mkdir(): directory %s created", path);
|
||||
|
|
@ -1797,10 +1791,8 @@ error_code sys_fs_rename(ppu_thread& ppu, vm::cptr<char> from, vm::cptr<char> to
|
|||
{
|
||||
case fs::error::noent: return {CELL_ENOENT, from};
|
||||
case fs::error::exist: return {CELL_EEXIST, to};
|
||||
default: sys_fs.error("sys_fs_rename(): unknown error %s", error);
|
||||
default: fmt::throw_exception("unknown error %s", error);
|
||||
}
|
||||
|
||||
return {CELL_EIO, from}; // ???
|
||||
}
|
||||
|
||||
sys_fs.notice("sys_fs_rename(): %s renamed to %s", from, to);
|
||||
|
|
@ -1852,10 +1844,8 @@ error_code sys_fs_rmdir(ppu_thread& ppu, vm::cptr<char> path)
|
|||
{
|
||||
case fs::error::noent: return {CELL_ENOENT, path};
|
||||
case fs::error::notempty: return {CELL_ENOTEMPTY, path};
|
||||
default: sys_fs.error("sys_fs_rmdir(): unknown error %s", error);
|
||||
default: fmt::throw_exception("unknown error %s", error);
|
||||
}
|
||||
|
||||
return {CELL_EIO, path}; // ???
|
||||
}
|
||||
|
||||
sys_fs.notice("sys_fs_rmdir(): directory %s removed", path);
|
||||
|
|
@ -1910,10 +1900,8 @@ error_code sys_fs_unlink(ppu_thread& ppu, vm::cptr<char> path)
|
|||
{
|
||||
return {mp == &g_mp_sys_dev_hdd1 ? sys_fs.warning : sys_fs.error, CELL_ENOENT, path};
|
||||
}
|
||||
default: sys_fs.error("sys_fs_unlink(): unknown error %s", error);
|
||||
default: fmt::throw_exception("unknown error %s", error);
|
||||
}
|
||||
|
||||
return {CELL_EIO, path}; // ???
|
||||
}
|
||||
|
||||
sys_fs.notice("sys_fs_unlink(): file %s deleted", path);
|
||||
|
|
@ -2632,10 +2620,8 @@ error_code sys_fs_lseek(ppu_thread& ppu, u32 fd, s64 offset, s32 whence, vm::ptr
|
|||
switch (auto error = fs::g_tls_error)
|
||||
{
|
||||
case fs::error::inval: return {CELL_EINVAL, "fd=%u, offset=0x%x, whence=%d", fd, offset, whence};
|
||||
default: sys_fs.error("sys_fs_lseek(): unknown error %s", error);
|
||||
default: fmt::throw_exception("unknown error %s", error);
|
||||
}
|
||||
|
||||
return CELL_EIO; // ???
|
||||
}
|
||||
|
||||
lock.unlock();
|
||||
|
|
@ -2751,10 +2737,8 @@ error_code sys_fs_get_block_size(ppu_thread& ppu, vm::cptr<char> path, vm::ptr<u
|
|||
{
|
||||
case fs::error::exist: return {CELL_EISDIR, path};
|
||||
case fs::error::noent: return {CELL_ENOENT, path};
|
||||
default: sys_fs.error("sys_fs_get_block_size(): unknown error %s", error);
|
||||
default: fmt::throw_exception("unknown error %s", error);
|
||||
}
|
||||
|
||||
return {CELL_EIO, path}; // ???
|
||||
}
|
||||
|
||||
static_cast<void>(ppu.test_stopped());
|
||||
|
|
@ -2809,10 +2793,8 @@ error_code sys_fs_truncate(ppu_thread& ppu, vm::cptr<char> path, u64 size)
|
|||
{
|
||||
return {mp == &g_mp_sys_dev_hdd1 ? sys_fs.warning : sys_fs.error, CELL_ENOENT, path};
|
||||
}
|
||||
default: sys_fs.error("sys_fs_truncate(): unknown error %s", error);
|
||||
default: fmt::throw_exception("unknown error %s", error);
|
||||
}
|
||||
|
||||
return {CELL_EIO, path}; // ???
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
|
|
@ -2858,10 +2840,8 @@ error_code sys_fs_ftruncate(ppu_thread& ppu, u32 fd, u64 size)
|
|||
switch (auto error = fs::g_tls_error)
|
||||
{
|
||||
case fs::error::ok:
|
||||
default: sys_fs.error("sys_fs_ftruncate(): unknown error %s", error);
|
||||
default: fmt::throw_exception("unknown error %s", error);
|
||||
}
|
||||
|
||||
return CELL_EIO; // ???
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
|
|
@ -3057,10 +3037,8 @@ error_code sys_fs_utime(ppu_thread& ppu, vm::cptr<char> path, vm::cptr<CellFsUti
|
|||
{
|
||||
return {mp == &g_mp_sys_dev_hdd1 ? sys_fs.warning : sys_fs.error, CELL_ENOENT, path};
|
||||
}
|
||||
default: sys_fs.error("sys_fs_utime(): unknown error %s", error);
|
||||
default: fmt::throw_exception("unknown error %s", error);
|
||||
}
|
||||
|
||||
return {CELL_EIO, path}; // ???
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
|
|
|
|||
|
|
@ -4,14 +4,18 @@
|
|||
#include "Emu/System.h"
|
||||
#include "Emu/Cell/timers.hpp"
|
||||
#include "util/cpu_stats.hpp"
|
||||
#include "util/sysinfo.hpp"
|
||||
#include "Utilities/Thread.h"
|
||||
|
||||
LOG_CHANNEL(perf_log, "PERF");
|
||||
|
||||
void perf_monitor::operator()()
|
||||
{
|
||||
constexpr u64 update_interval_us = 1000000; // Update every second
|
||||
constexpr u64 log_interval_us = 10000000; // Log every 10 seconds
|
||||
constexpr u64 update_interval_us = 500000; // Update every half second
|
||||
constexpr u64 log_interval_us_max = 10000000; // Log at minimum every 10 seconds
|
||||
constexpr u64 log_interval_us_min = 500000; // Log at maximum every half a second (catching possible memory leak)
|
||||
constexpr u64 log_mem_increase = 50 * (1024 * 1024); // Log when memory usage increased by this amount
|
||||
|
||||
u64 elapsed_us = 0;
|
||||
|
||||
utils::cpu_stats stats;
|
||||
|
|
@ -19,26 +23,28 @@ void perf_monitor::operator()()
|
|||
|
||||
u32 logged_pause = 0;
|
||||
u64 last_pause_time = umax;
|
||||
u64 max_memory_usage = 0;
|
||||
|
||||
std::vector<double> per_core_usage;
|
||||
std::string msg;
|
||||
|
||||
for (u64 sleep_until = get_system_time(); thread_ctrl::state() != thread_state::aborting;)
|
||||
for (u64 sleep_until = get_system_time();;)
|
||||
{
|
||||
thread_ctrl::wait_until(&sleep_until, update_interval_us);
|
||||
elapsed_us += update_interval_us;
|
||||
|
||||
if (thread_ctrl::state() == thread_state::aborting)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
double total_usage = 0.0;
|
||||
|
||||
stats.get_per_core_usage(per_core_usage, total_usage);
|
||||
|
||||
if (elapsed_us >= log_interval_us)
|
||||
const u64 current_mem_use = utils::get_memory_usage().second;
|
||||
const u64 mem_use_increase = current_mem_use >= max_memory_usage ? current_mem_use - max_memory_usage : 0;
|
||||
|
||||
const u64 log_interval = (mem_use_increase >= log_mem_increase ? log_interval_us_min : log_interval_us_max);
|
||||
|
||||
if (elapsed_us >= log_interval || thread_ctrl::state() == thread_state::aborting)
|
||||
{
|
||||
max_memory_usage = std::max<u64>(current_mem_use, max_memory_usage);
|
||||
elapsed_us = 0;
|
||||
|
||||
const bool is_paused = Emu.IsPaused();
|
||||
|
|
@ -76,7 +82,18 @@ void perf_monitor::operator()()
|
|||
fmt::append(msg, "%s %.1f%%", i > 0 ? "," : "", per_core_usage[i]);
|
||||
}
|
||||
|
||||
if (max_memory_usage)
|
||||
{
|
||||
fmt::append(msg, ", RAM Usage: %dMB (Peak: %dMB)", current_mem_use / (1024 * 1024), max_memory_usage / (1024 * 1024));
|
||||
}
|
||||
|
||||
perf_log.notice("%s", msg);
|
||||
|
||||
if (thread_ctrl::state() == thread_state::aborting)
|
||||
{
|
||||
// Log once before terminating
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -197,6 +197,10 @@ std::set<std::string> get_one_drive_paths()
|
|||
|
||||
fmt::append(buf, "\nBuild: \"%s\"", rpcs3::get_verbose_version());
|
||||
fmt::append(buf, "\nDate: \"%s\"", std::chrono::system_clock::now());
|
||||
|
||||
const auto [total, current] = utils::get_memory_usage();
|
||||
|
||||
fmt::append(buf, "\nRAM Usage: %dMB/%dMB (%dMB free)", current / (1024 * 1024), total / (1024 * 1024), (total - current) / (1024 * 1024));
|
||||
}
|
||||
|
||||
std::string_view text = s_is_error_launch ? _text : buf;
|
||||
|
|
|
|||
|
|
@ -736,6 +736,20 @@ std::string utils::get_firmware_version()
|
|||
return {};
|
||||
}
|
||||
|
||||
std::pair<u64, u64> utils::get_memory_usage()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
::MEMORYSTATUSEX status{};
|
||||
status.dwLength = sizeof(status);
|
||||
::GlobalMemoryStatusEx(&status);
|
||||
return { status.ullTotalPhys, status.ullTotalPhys - status.ullAvailPhys };
|
||||
|
||||
#else
|
||||
// TODO
|
||||
return { get_total_memory(), 0 };
|
||||
#endif
|
||||
}
|
||||
|
||||
utils::OS_version utils::get_OS_version()
|
||||
{
|
||||
OS_version res {};
|
||||
|
|
@ -1087,7 +1101,7 @@ static const bool s_tsc_freq_evaluated = []() -> bool
|
|||
u64 utils::get_total_memory()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
::MEMORYSTATUSEX memInfo;
|
||||
::MEMORYSTATUSEX memInfo{};
|
||||
memInfo.dwLength = sizeof(memInfo);
|
||||
::GlobalMemoryStatusEx(&memInfo);
|
||||
return memInfo.ullTotalPhys;
|
||||
|
|
|
|||
|
|
@ -71,6 +71,8 @@ namespace utils
|
|||
|
||||
std::string get_firmware_version();
|
||||
|
||||
std::pair<u64, u64> get_memory_usage();
|
||||
|
||||
struct OS_version
|
||||
{
|
||||
std::string type;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue