Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

File system perf, part 3 #19672

Merged
merged 7 commits into from
Nov 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 16 additions & 2 deletions Common/File/DirListing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,12 @@
#endif // HAVE_LIBNX

// NOTE: There's another one in FileUtil.cpp.
#ifdef _WIN32
constexpr bool SIMULATE_SLOW_IO = false;
#else
constexpr bool SIMULATE_SLOW_IO = false;
#endif
constexpr bool LOG_IO = false;

namespace File {

Expand All @@ -57,8 +62,10 @@ static uint64_t FiletimeToStatTime(FILETIME ft) {
#endif

bool GetFileInfo(const Path &path, FileInfo * fileInfo) {
if (SIMULATE_SLOW_IO) {
if (LOG_IO) {
INFO_LOG(Log::System, "GetFileInfo %s", path.c_str());
}
if (SIMULATE_SLOW_IO) {
sleep_ms(300, "slow-io-sim");
}

Expand Down Expand Up @@ -184,8 +191,10 @@ std::vector<File::FileInfo> ApplyFilter(std::vector<File::FileInfo> files, const
}

bool GetFilesInDir(const Path &directory, std::vector<FileInfo> *files, const char *filter, int flags, std::string_view prefix) {
if (SIMULATE_SLOW_IO) {
if (LOG_IO) {
INFO_LOG(Log::System, "GetFilesInDir %s (ext %s, prefix %.*s)", directory.c_str(), filter, (int)prefix.size(), prefix.data());
}
if (SIMULATE_SLOW_IO) {
sleep_ms(300, "slow-io-sim");
}

Expand Down Expand Up @@ -267,10 +276,12 @@ bool GetFilesInDir(const Path &directory, std::vector<FileInfo> *files, const ch
continue;
}

/*
if (SIMULATE_SLOW_IO) {
INFO_LOG(Log::System, "GetFilesInDir item %s", virtualName.c_str());
sleep_ms(50, "slow-io-sim");
}
*/

FileInfo info;
info.name = virtualName;
Expand Down Expand Up @@ -345,6 +356,9 @@ bool GetFilesInDir(const Path &directory, std::vector<FileInfo> *files, const ch
closedir(dirp);
#endif
std::sort(files->begin(), files->end());
if (LOG_IO) {
INFO_LOG(Log::System, "GetFilesInDir: Found %d files", (int)files->size());
}
return true;
}

Expand Down
3 changes: 2 additions & 1 deletion Common/File/DiskFree.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@
#include "Common/File/Path.h"

// If this fails, false is returned and space is negative.
// Try to avoid calling this from the main thread, if possible. Can be SLOW.
// Try to avoid calling this from the main thread, if possible. Not super fast,
// but is also not allowed to do things like scan the entire disk.
bool free_disk_space(const Path &path, int64_t &space);
41 changes: 32 additions & 9 deletions Common/File/FileUtil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,12 @@
#include <sys/stat.h>

// NOTE: There's another one in DirListing.cpp.
#ifdef _WIN32
constexpr bool SIMULATE_SLOW_IO = false;
#else
constexpr bool SIMULATE_SLOW_IO = false;
#endif
constexpr bool LOG_IO = false;

#ifndef S_ISDIR
#define S_ISDIR(m) (((m)&S_IFMT) == S_IFDIR)
Expand All @@ -115,8 +120,10 @@ constexpr bool SIMULATE_SLOW_IO = false;
namespace File {

FILE *OpenCFile(const Path &path, const char *mode) {
if (SIMULATE_SLOW_IO) {
if (LOG_IO) {
INFO_LOG(Log::System, "OpenCFile %s, %s", path.c_str(), mode);
}
if (SIMULATE_SLOW_IO) {
sleep_ms(300, "slow-io-sim");
}
switch (path.Type()) {
Expand Down Expand Up @@ -217,8 +224,10 @@ static std::string OpenFlagToString(OpenFlag flags) {
}

int OpenFD(const Path &path, OpenFlag flags) {
if (SIMULATE_SLOW_IO) {
if (LOG_IO) {
INFO_LOG(Log::System, "OpenFD %s, %d", path.c_str(), flags);
}
if (SIMULATE_SLOW_IO) {
sleep_ms(300, "slow-io-sim");
}

Expand Down Expand Up @@ -315,8 +324,10 @@ static bool ResolvePathVista(const std::wstring &path, wchar_t *buf, DWORD bufSi
#endif

std::string ResolvePath(const std::string &path) {
if (SIMULATE_SLOW_IO) {
if (LOG_IO) {
INFO_LOG(Log::System, "ResolvePath %s", path.c_str());
}
if (SIMULATE_SLOW_IO) {
sleep_ms(100, "slow-io-sim");
}

Expand Down Expand Up @@ -408,9 +419,11 @@ bool ExistsInDir(const Path &path, const std::string &filename) {
}

bool Exists(const Path &path) {
if (LOG_IO) {
INFO_LOG(Log::System, "Exists %s", path.c_str());
}
if (SIMULATE_SLOW_IO) {
sleep_ms(200, "slow-io-sim");
INFO_LOG(Log::System, "Exists %s", path.c_str());
}

if (path.Type() == PathType::CONTENT_URI) {
Expand Down Expand Up @@ -445,9 +458,11 @@ bool Exists(const Path &path) {

// Returns true if filename exists and is a directory
bool IsDirectory(const Path &path) {
if (LOG_IO) {
INFO_LOG(Log::System, "IsDirectory %s", path.c_str());
}
if (SIMULATE_SLOW_IO) {
sleep_ms(100, "slow-io-sim");
INFO_LOG(Log::System, "IsDirectory %s", path.c_str());
}

switch (path.Type()) {
Expand Down Expand Up @@ -660,9 +675,11 @@ bool CreateFullPath(const Path &path) {

// renames file srcFilename to destFilename, returns true on success
bool Rename(const Path &srcFilename, const Path &destFilename) {
if (LOG_IO) {
INFO_LOG(Log::System, "Rename %s -> %s", srcFilename.c_str(), destFilename.c_str());
}
if (SIMULATE_SLOW_IO) {
sleep_ms(100, "slow-io-sim");
INFO_LOG(Log::System, "Rename %s -> %s", srcFilename.c_str(), destFilename.c_str());
}

if (srcFilename.Type() != destFilename.Type()) {
Expand Down Expand Up @@ -713,9 +730,11 @@ bool Rename(const Path &srcFilename, const Path &destFilename) {

// copies file srcFilename to destFilename, returns true on success
bool Copy(const Path &srcFilename, const Path &destFilename) {
if (LOG_IO) {
INFO_LOG(Log::System, "Copy %s -> %s", srcFilename.c_str(), destFilename.c_str());
}
if (SIMULATE_SLOW_IO) {
sleep_ms(100, "slow-io-sim");
INFO_LOG(Log::System, "Copy %s -> %s", srcFilename.c_str(), destFilename.c_str());
}
switch (srcFilename.Type()) {
case PathType::NATIVE:
Expand Down Expand Up @@ -857,9 +876,11 @@ bool MoveIfFast(const Path &srcFilename, const Path &destFilename) {
// Returns the size of file (64bit)
// TODO: Add a way to return an error.
uint64_t GetFileSize(const Path &filename) {
if (LOG_IO) {
INFO_LOG(Log::System, "GetFileSize %s", filename.c_str());
}
if (SIMULATE_SLOW_IO) {
sleep_ms(100, "slow-io-sim");
INFO_LOG(Log::System, "GetFileSize %s", filename.c_str());
}
switch (filename.Type()) {
case PathType::NATIVE:
Expand Down Expand Up @@ -967,9 +988,11 @@ bool CreateEmptyFile(const Path &filename) {
// Deletes an empty directory, returns true on success
// WARNING: On Android with content URIs, it will delete recursively!
bool DeleteDir(const Path &path) {
if (LOG_IO) {
INFO_LOG(Log::System, "DeleteDir %s", path.c_str());
}
if (SIMULATE_SLOW_IO) {
sleep_ms(100, "slow-io-sim");
INFO_LOG(Log::System, "DeleteDir %s", path.c_str());
}
switch (path.Type()) {
case PathType::NATIVE:
Expand Down
4 changes: 2 additions & 2 deletions Common/Thread/ThreadManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -130,10 +130,10 @@ bool ThreadManager::TeardownTask(Task *task, bool enqueue) {

static void WorkerThreadFunc(GlobalThreadContext *global, TaskThreadContext *thread) {
if (thread->type == TaskType::CPU_COMPUTE) {
snprintf(thread->name, sizeof(thread->name), "PoolWorker %d", thread->index);
snprintf(thread->name, sizeof(thread->name), "PoolW %d", thread->index);
} else {
_assert_(thread->type == TaskType::IO_BLOCKING);
snprintf(thread->name, sizeof(thread->name), "PoolWorkerIO %d", thread->index);
snprintf(thread->name, sizeof(thread->name), "PoolW IO %d", thread->index);
}
SetCurrentThreadName(thread->name);

Expand Down
17 changes: 11 additions & 6 deletions Core/Dialog/SavedataParam.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,7 @@ bool SavedataParam::Delete(SceUtilitySavedataParam* param, int saveId) {
}

// Sanity check, preventing full delete of savedata/ in MGS PW demo (!)
if (!strlen(param->gameName) && param->mode != SCE_UTILITY_SAVEDATA_TYPE_LISTALLDELETE) {
if (!strnlen(param->gameName, sizeof(param->gameName)) && param->mode != SCE_UTILITY_SAVEDATA_TYPE_LISTALLDELETE) {
ERROR_LOG(Log::sceUtility, "Bad param with gameName empty - cannot delete save directory");
return false;
}
Expand Down Expand Up @@ -1119,17 +1119,15 @@ inline std::string FmtPspTime(const ScePspDateTime &dt) {
return StringFromFormat("%04d-%02d-%02d %02d:%02d:%02d.%06d", dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second, dt.microsecond);
}

int SavedataParam::GetSizes(SceUtilitySavedataParam *param)
{
int SavedataParam::GetSizes(SceUtilitySavedataParam *param) {
if (!param) {
return SCE_UTILITY_SAVEDATA_ERROR_SIZES_NO_DATA;
}

int ret = 0;

if (param->msFree.IsValid())
{
const u64 freeBytes = MemoryStick_FreeSpace();
const u64 freeBytes = MemoryStick_FreeSpace(GetGameName(param));
param->msFree->clusterSize = (u32)MemoryStick_SectorSize();
param->msFree->freeClusters = (u32)(freeBytes / MemoryStick_SectorSize());
param->msFree->freeSpaceKB = (u32)(freeBytes / 0x400);
Expand Down Expand Up @@ -1230,6 +1228,8 @@ bool SavedataParam::GetList(SceUtilitySavedataParam *param)

std::vector<PSPFileInfo> validDir;
std::vector<PSPFileInfo> sfoFiles;

// TODO: Here we can filter by prefix - only the savename in param is likely to be a regex.
std::vector<PSPFileInfo> allDir = pspFileSystem.GetDirListing(savePath);

std::string searchString = GetGameName(param) + GetSaveName(param);
Expand Down Expand Up @@ -1419,7 +1419,7 @@ bool SavedataParam::GetSize(SceUtilitySavedataParam *param) {

if (param->sizeInfo.IsValid()) {
auto listing = pspFileSystem.GetDirListing(saveDir, &exists);
const u64 freeBytes = MemoryStick_FreeSpace();
const u64 freeBytes = MemoryStick_FreeSpace(GetGameName(param));

s64 overwriteBytes = 0;
s64 writeBytes = 0;
Expand Down Expand Up @@ -1511,6 +1511,11 @@ int SavedataParam::SetPspParam(SceUtilitySavedataParam *param)
return 0;
}

std::string gameName = GetGameName(param);
if (!gameName.empty()) {
MemoryStick_NotifyGameName(gameName);
}

if (param->mode == SCE_UTILITY_SAVEDATA_TYPE_LISTALLDELETE) {
Clear();
int realCount = 0;
Expand Down
11 changes: 7 additions & 4 deletions Core/FileSystems/DirectoryFileSystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -366,12 +366,15 @@ size_t DirectoryFileHandle::Write(const u8* pointer, s64 size)
g_OSD.Show(OSDType::MESSAGE_ERROR, err->T("Disk full while writing data"), 0.0f, "diskfull");
// We only return an error when the disk is actually full.
// When writing this would cause the disk to be full, so it wasn't written, we return 0.
if (MemoryStick_FreeSpace() == 0) {
// Sign extend on 64-bit.
return (size_t)(s64)(s32)SCE_KERNEL_ERROR_ERRNO_DEVICE_NO_FREE_SPACE;
Path saveFolder = GetSysDirectory(DIRECTORY_SAVEDATA);
int64_t space;
if (free_disk_space(saveFolder, space)) {
if (space < size) {
// Sign extend to a 64-bit value.
return (size_t)(s64)(s32)SCE_KERNEL_ERROR_ERRNO_DEVICE_NO_FREE_SPACE;
}
}
}

return bytesWritten;
}

Expand Down
6 changes: 6 additions & 0 deletions Core/FileSystems/MetaFileSystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -682,3 +682,9 @@ int64_t MetaFileSystem::ComputeRecursiveDirectorySize(const std::string &filenam
return false;
}
}

bool MetaFileSystem::ComputeRecursiveDirSizeIfFast(const std::string &path, int64_t *size) {
// Shouldn't be called. Can't recurse MetaFileSystem.
_dbg_assert_(false);
return false;
}
11 changes: 1 addition & 10 deletions Core/FileSystems/MetaFileSystem.h
Original file line number Diff line number Diff line change
Expand Up @@ -144,16 +144,7 @@ class MetaFileSystem : public IHandleAllocator, public IFileSystem {

int64_t ComputeRecursiveDirectorySize(const std::string &dirPath);

// Shouldn't ever be called, but meh.
bool ComputeRecursiveDirSizeIfFast(const std::string &path, int64_t *size) override {
int64_t sizeTemp = ComputeRecursiveDirectorySize(path);
if (sizeTemp >= 0) {
*size = sizeTemp;
return true;
} else {
return false;
}
}
bool ComputeRecursiveDirSizeIfFast(const std::string &path, int64_t *size) override;

void Describe(char *buf, size_t size) const override { snprintf(buf, size, "Meta"); }

Expand Down
Loading
Loading