mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-07 23:41:26 +12:00
Clear disk cache if it grows too large (dev_hdd1/cache) (#5411)
* Clear disk cache automatically * Add disk cache to UI
This commit is contained in:
parent
b99a88afe2
commit
eba364c64c
6 changed files with 153 additions and 1 deletions
|
@ -494,8 +494,85 @@ bool Emulator::BootRsxCapture(const std::string& path)
|
|||
return true;
|
||||
}
|
||||
|
||||
void Emulator::LimitCacheSize()
|
||||
{
|
||||
const std::string cache_location = Emulator::GetHdd1Dir() + "/cache";
|
||||
if (!fs::is_dir(cache_location))
|
||||
{
|
||||
LOG_WARNING(GENERAL, "Cache does not exist (%s)", cache_location);
|
||||
return;
|
||||
}
|
||||
|
||||
const u64 size = fs::get_dir_size(cache_location);
|
||||
const u64 max_size = static_cast<u64>(g_cfg.vfs.cache_max_size) * 1024 * 1024;
|
||||
|
||||
if (max_size == 0) // Everything must go, so no need to do checks
|
||||
{
|
||||
fs::remove_all(cache_location, false);
|
||||
LOG_SUCCESS(GENERAL, "Cleared disk cache");
|
||||
return;
|
||||
}
|
||||
|
||||
if (size <= max_size)
|
||||
{
|
||||
LOG_TRACE(GENERAL, "Cache size below limit: %llu/%llu", size, max_size);
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_SUCCESS(GENERAL, "Cleaning disk cache...");
|
||||
std::vector<fs::dir_entry> file_list{};
|
||||
fs::dir cache_dir{};
|
||||
if (!cache_dir.open(cache_location))
|
||||
{
|
||||
LOG_ERROR(GENERAL, "Could not open cache directory");
|
||||
return;
|
||||
}
|
||||
|
||||
// retrieve items to delete
|
||||
for (const auto &item : cache_dir)
|
||||
{
|
||||
if (item.name != "." && item.name != "..")
|
||||
file_list.push_back(item);
|
||||
}
|
||||
cache_dir.close();
|
||||
|
||||
// sort oldest first
|
||||
std::sort(file_list.begin(), file_list.end(), [](auto left, auto right)
|
||||
{
|
||||
return left.mtime < right.mtime;
|
||||
});
|
||||
|
||||
// keep removing until cache is empty or enough bytes have been cleared
|
||||
// cache is cleared down to 80% of limit to increase interval between clears
|
||||
const u64 to_remove = static_cast<u64>(size - max_size * 0.8);
|
||||
u64 removed = 0;
|
||||
for (const auto &item : file_list)
|
||||
{
|
||||
const std::string &name = cache_location + "/" + item.name;
|
||||
const u64 item_size = fs::is_dir(name) ? fs::get_dir_size(name) : item.size;
|
||||
|
||||
if (fs::is_dir(name))
|
||||
{
|
||||
fs::remove_all(name, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
fs::remove_file(name);
|
||||
}
|
||||
|
||||
removed += item_size;
|
||||
if (removed >= to_remove)
|
||||
break;
|
||||
}
|
||||
|
||||
LOG_SUCCESS(GENERAL, "Cleaned disk cache, removed %.2f MB", size / 1024.0 / 1024.0);
|
||||
}
|
||||
|
||||
bool Emulator::BootGame(const std::string& path, bool direct, bool add_only)
|
||||
{
|
||||
if (g_cfg.vfs.limit_cache_size)
|
||||
LimitCacheSize();
|
||||
|
||||
static const char* boot_list[] =
|
||||
{
|
||||
"/PS3_GAME/USRDIR/EBOOT.BIN",
|
||||
|
@ -571,6 +648,11 @@ std::string Emulator::GetHddDir()
|
|||
return fmt::replace_all(g_cfg.vfs.dev_hdd0, "$(EmulatorDir)", GetEmuDir());
|
||||
}
|
||||
|
||||
std::string Emulator::GetHdd1Dir()
|
||||
{
|
||||
return fmt::replace_all(g_cfg.vfs.dev_hdd1, "$(EmulatorDir)", GetEmuDir());
|
||||
}
|
||||
|
||||
std::string Emulator::GetSfoDirFromGamePath(const std::string& game_path, const std::string& user)
|
||||
{
|
||||
if (fs::is_file(game_path + "/PS3_DISC.SFB"))
|
||||
|
|
|
@ -318,6 +318,9 @@ public:
|
|||
|
||||
private:
|
||||
static std::string GetEmuDir();
|
||||
static std::string GetHdd1Dir();
|
||||
|
||||
void LimitCacheSize();
|
||||
public:
|
||||
static std::string GetHddDir();
|
||||
static std::string GetSfoDirFromGamePath(const std::string& game_path, const std::string& user);
|
||||
|
@ -405,6 +408,9 @@ struct cfg_root : cfg::node
|
|||
cfg::_bool host_root{this, "Enable /host_root/"};
|
||||
cfg::_bool init_dirs{this, "Initialize Directories", true};
|
||||
|
||||
cfg::_bool limit_cache_size{this, "Limit disk cache size", false};
|
||||
cfg::_int<0, 10240> cache_max_size{this, "Disk cache maximum size (MB)", 5120};
|
||||
|
||||
} vfs{this};
|
||||
|
||||
struct node_video : cfg::node
|
||||
|
|
|
@ -140,6 +140,7 @@
|
|||
"system": {
|
||||
"sysLangBox": "Some games may fail to boot if the system language is not available in the game itself.\nOther games will switch language automatically to what is selected here.\nIt is recommended leaving this on a language supported by the game.",
|
||||
"enterButtonAssignment": "The button used for enter/accept/confirm in system dialogs.\nChange this to use the circle button instead, which is the default configuration on japanese systems and in many japanese games.\nIn these cases having the cross button assigned can often lead to confusion.",
|
||||
"enableHostRoot": "Required for some Homebrew.\nIf unsure, don't use this option."
|
||||
"enableHostRoot": "Required for some Homebrew.\nIf unsure, don't use this option.",
|
||||
"limitCacheSize": "Automatically removes older files from disk cache on boot if it grows larger than the specified value.\nGames can use the cache folder to temporarily store data outside of system memory. It is not used for long term storage."
|
||||
}
|
||||
}
|
||||
|
|
|
@ -128,6 +128,8 @@ public:
|
|||
Language,
|
||||
EnterButtonAssignment,
|
||||
EnableHostRoot,
|
||||
LimitCacheSize,
|
||||
MaximumCacheSize,
|
||||
|
||||
// Virtual File System
|
||||
emulatorLocation,
|
||||
|
@ -330,6 +332,8 @@ private:
|
|||
{ Language, { "System", "Language"}},
|
||||
{ EnterButtonAssignment, { "System", "Enter button assignment"}},
|
||||
{ EnableHostRoot, { "VFS", "Enable /host_root/"}},
|
||||
{ LimitCacheSize, { "VFS", "Limit disk cache size"}},
|
||||
{ MaximumCacheSize, { "VFS", "Disk cache maximum size (MB)"}},
|
||||
|
||||
// Virtual File System
|
||||
{ emulatorLocation, { "VFS", "$(EmulatorDir)"}},
|
||||
|
|
|
@ -784,6 +784,16 @@ settings_dialog::settings_dialog(std::shared_ptr<gui_settings> guiSettings, std:
|
|||
xemu_settings->EnhanceCheckBox(ui->enableHostRoot, emu_settings::EnableHostRoot);
|
||||
SubscribeTooltip(ui->enableHostRoot, json_sys["enableHostRoot"].toString());
|
||||
|
||||
xemu_settings->EnhanceCheckBox(ui->enableCacheClearing, emu_settings::LimitCacheSize);
|
||||
SubscribeTooltip(ui->enableCacheClearing, json_sys["limitCacheSize"].toString());
|
||||
connect(ui->enableCacheClearing, &QCheckBox::stateChanged, ui->maximumCacheSize, &QSlider::setEnabled);
|
||||
|
||||
// Sliders
|
||||
|
||||
EnhanceSlider(emu_settings::MaximumCacheSize, ui->maximumCacheSize, ui->maximumCacheSizeLabel, tr("Maximum size: %0 MB"));
|
||||
SubscribeTooltip(ui->maximumCacheSize, json_sys["limitCacheSize"].toString());
|
||||
ui->maximumCacheSize->setEnabled(ui->enableCacheClearing->isChecked());
|
||||
|
||||
// Radio Buttons
|
||||
|
||||
SubscribeTooltip(ui->gb_enterButtonAssignment, json_sys["enterButtonAssignment"].toString());
|
||||
|
|
|
@ -1149,6 +1149,55 @@
|
|||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_18" stretch="1,1,1">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="gb_DiskCacheClearing">
|
||||
<property name="title">
|
||||
<string>Disk cache</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_73">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="enableCacheClearing">
|
||||
<property name="text">
|
||||
<string>Clear cache automatically</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="maximumCacheSizeLabel">
|
||||
<property name="text">
|
||||
<string>Cache size: 3072 MB</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSlider" name="maximumCacheSize">
|
||||
<property name="pageStep">
|
||||
<number>512</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="tickPosition">
|
||||
<enum>QSlider::TicksBelow</enum>
|
||||
</property>
|
||||
<property name="tickInterval">
|
||||
<number>1024</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QWidget" name="widget_14" native="true"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QWidget" name="widget_15" native="true"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_8">
|
||||
<property name="orientation">
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue