Skip to content

Commit

Permalink
Merge pull request #19676 from hrydgard/file-system-perf-part-4
Browse files Browse the repository at this point in the history
File system perf part 4, fix save deletion regression
  • Loading branch information
hrydgard authored Nov 30, 2024
2 parents 5077c7b + 1f108a0 commit 7b0551f
Show file tree
Hide file tree
Showing 27 changed files with 177 additions and 130 deletions.
14 changes: 6 additions & 8 deletions Common/Data/Format/IniFile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ static std::string EscapeHash(std::string_view value) {
return result;
}

void ParsedIniLine::ParseFrom(std::string_view line) {
ParsedIniLine::ParsedIniLine(std::string_view line) {
line = StripSpaces(line);
if (line.empty()) {
key.clear();
Expand Down Expand Up @@ -534,7 +534,7 @@ bool IniFile::Load(std::istream &in) {
while (!(in.eof() || in.fail()))
{
in.getline(templine, MAX_BYTES);
std::string line = templine;
std::string_view line = templine;

// Remove UTF-8 byte order marks.
if (line.substr(0, 3) == "\xEF\xBB\xBF") {
Expand All @@ -543,8 +543,8 @@ bool IniFile::Load(std::istream &in) {

#ifndef _WIN32
// Check for CRLF eol and convert it to LF
if (!line.empty() && line.at(line.size()-1) == '\r') {
line.erase(line.size()-1);
if (!line.empty() && line.at(line.size() - 1) == '\r') {
line = line.substr(line.size() - 1);
}
#endif

Expand All @@ -556,7 +556,7 @@ bool IniFile::Load(std::istream &in) {

if (sectionNameEnd != std::string::npos) {
// New section!
std::string sub = line.substr(1, sectionNameEnd - 1);
std::string_view sub = line.substr(1, sectionNameEnd - 1);
sections.push_back(std::make_unique<Section>(sub));

if (sectionNameEnd + 1 < line.size()) {
Expand All @@ -566,9 +566,7 @@ bool IniFile::Load(std::istream &in) {
if (sections.empty()) {
sections.push_back(std::make_unique<Section>(""));
}
ParsedIniLine parsedLine;
parsedLine.ParseFrom(line);
sections.back()->lines_.push_back(parsedLine);
sections.back()->lines_.emplace_back(line);
}
}
}
Expand Down
5 changes: 2 additions & 3 deletions Common/Data/Format/IniFile.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ class VFSInterface;

class ParsedIniLine {
public:
ParsedIniLine() {}
explicit ParsedIniLine(std::string_view line);

ParsedIniLine(std::string_view key, std::string_view value) {
this->key = key;
this->value = value;
Expand All @@ -32,8 +33,6 @@ class ParsedIniLine {
return ParsedIniLine(std::string_view(), std::string_view(), comment);
}

// Comments only come from "ParseFrom".
void ParseFrom(std::string_view line);
void Reconstruct(std::string *output) const;

// Having these as views allows a more efficient internal representation, like one joint string.
Expand Down
4 changes: 1 addition & 3 deletions Common/Data/Text/I18n.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -131,9 +131,7 @@ Path I18NRepo::GetIniPath(const std::string &languageID) const {

bool I18NRepo::IniExists(const std::string &languageID) const {
File::FileInfo info;
if (!g_VFS.GetFileInfo(GetIniPath(languageID).ToString().c_str(), &info))
return false;
if (!info.exists)
if (!g_VFS.Exists(GetIniPath(languageID).ToString().c_str()))
return false;
return true;
}
Expand Down
6 changes: 3 additions & 3 deletions Common/File/AndroidStorage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ void Android_StorageSetNativeActivity(jobject nativeActivity) {
void Android_RegisterStorageCallbacks(JNIEnv * env, jobject obj) {
openContentUri = env->GetMethodID(env->GetObjectClass(obj), "openContentUri", "(Ljava/lang/String;Ljava/lang/String;)I");
_dbg_assert_(openContentUri);
listContentUriDir = env->GetMethodID(env->GetObjectClass(obj), "listContentUriDir", "(Ljava/lang/String;Ljava/lang/String;)[Ljava/lang/String;");
listContentUriDir = env->GetMethodID(env->GetObjectClass(obj), "listContentUriDir", "(Ljava/lang/String;)[Ljava/lang/String;");
_dbg_assert_(listContentUriDir);
contentUriCreateDirectory = env->GetMethodID(env->GetObjectClass(obj), "contentUriCreateDirectory", "(Ljava/lang/String;Ljava/lang/String;)I");
_dbg_assert_(contentUriCreateDirectory);
Expand Down Expand Up @@ -233,8 +233,7 @@ std::vector<File::FileInfo> Android_ListContentUri(const std::string &uri, const
double start = time_now_d();

jstring param = env->NewStringUTF(uri.c_str());
jstring filter = prefix.empty() ? nullptr : env->NewStringUTF(prefix.c_str());
jobject retval = env->CallObjectMethod(g_nativeActivity, listContentUriDir, param, filter);
jobject retval = env->CallObjectMethod(g_nativeActivity, listContentUriDir, param);

jobjectArray fileList = (jobjectArray)retval;
std::vector<File::FileInfo> items;
Expand All @@ -251,6 +250,7 @@ std::vector<File::FileInfo> Android_ListContentUri(const std::string &uri, const
} else if (ParseFileInfo(line, &info)) {
// We can just reconstruct the URI.
info.fullName = Path(uri) / info.name;
INFO_LOG(Log::FileSystem, "%s", info.name.c_str());
items.push_back(info);
}
}
Expand Down
23 changes: 12 additions & 11 deletions Common/File/DirListing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ static uint64_t FiletimeToStatTime(FILETIME ft) {

bool GetFileInfo(const Path &path, FileInfo * fileInfo) {
if (LOG_IO) {
INFO_LOG(Log::System, "GetFileInfo %s", path.c_str());
INFO_LOG(Log::System, "GetFileInfo %s", path.ToVisualString().c_str());
}
if (SIMULATE_SLOW_IO) {
sleep_ms(300, "slow-io-sim");
Expand Down Expand Up @@ -178,12 +178,14 @@ std::vector<File::FileInfo> ApplyFilter(std::vector<File::FileInfo> files, const
}

auto pred = [&](const File::FileInfo &info) {
// WARNING: Keep in mind that if we return true here, the files is REMOVED from the list.
// It's not retain_if.
if (!startsWith(info.name, prefix)) {
return true;
}
if (info.isDirectory || !extensionFilter)
return false;
std::string ext = info.fullName.GetFileExtension();
if (!startsWith(info.name, prefix)) {
return false;
}
return filters.find(ext) == filters.end();
};
files.erase(std::remove_if(files.begin(), files.end(), pred), files.end());
Expand All @@ -192,7 +194,7 @@ 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 (LOG_IO) {
INFO_LOG(Log::System, "GetFilesInDir %s (ext %s, prefix %.*s)", directory.c_str(), filter, (int)prefix.size(), prefix.data());
INFO_LOG(Log::System, "GetFilesInDir '%s' (ext %s, prefix %.*s)", directory.ToVisualString().c_str(), filter, (int)prefix.size(), prefix.data());
}
if (SIMULATE_SLOW_IO) {
sleep_ms(300, "slow-io-sim");
Expand All @@ -202,8 +204,10 @@ bool GetFilesInDir(const Path &directory, std::vector<FileInfo> *files, const ch
bool exists = false;
// TODO: Move prefix filtering over to the Java side for more speed.
std::vector<File::FileInfo> fileList = Android_ListContentUri(directory.ToString(), std::string(prefix), &exists);
*files = ApplyFilter(fileList, filter, "");
int beforeFilter = (int)fileList.size();
*files = ApplyFilter(fileList, filter, prefix);
std::sort(files->begin(), files->end());
DEBUG_LOG(Log::System, "GetFilesInDir: Found %d entries (%d before filter)", (int)files->size(), beforeFilter);
return exists;
}

Expand Down Expand Up @@ -276,12 +280,9 @@ 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");
if (LOG_IO) {
// INFO_LOG(Log::System, "GetFilesInDir item %s", virtualName.c_str());
}
*/

FileInfo info;
info.name = virtualName;
Expand Down
10 changes: 4 additions & 6 deletions Common/File/FileUtil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -420,7 +420,7 @@ 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());
INFO_LOG(Log::System, "Exists %s", path.ToVisualString().c_str());
}
if (SIMULATE_SLOW_IO) {
sleep_ms(200, "slow-io-sim");
Expand Down Expand Up @@ -631,7 +631,7 @@ bool CreateDir(const Path &path) {
// Creates the full path of fullPath returns true on success
bool CreateFullPath(const Path &path) {
if (File::Exists(path)) {
DEBUG_LOG(Log::Common, "CreateFullPath: path exists %s", path.c_str());
DEBUG_LOG(Log::Common, "CreateFullPath: path exists %s", path.ToVisualString().c_str());
return true;
}

Expand All @@ -640,7 +640,7 @@ bool CreateFullPath(const Path &path) {
case PathType::CONTENT_URI:
break; // OK
default:
ERROR_LOG(Log::Common, "CreateFullPath(%s): Not yet supported", path.c_str());
ERROR_LOG(Log::Common, "CreateFullPath(%s): Not yet supported", path.ToVisualString().c_str());
return false;
}

Expand All @@ -665,9 +665,7 @@ bool CreateFullPath(const Path &path) {
Path curPath = root;
for (auto part : parts) {
curPath /= part;
if (!File::Exists(curPath)) {
File::CreateDir(curPath);
}
File::CreateDir(curPath);
}

return true;
Expand Down
5 changes: 5 additions & 0 deletions Common/File/VFS/DirectoryReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ bool DirectoryReader::GetFileInfo(const char *path, File::FileInfo *info) {
return File::GetFileInfo(new_path, info);
}

bool DirectoryReader::Exists(const char *path) {
Path new_path = Path(path).StartsWith(path_) ? Path(path) : path_ / path;
return File::Exists(new_path);
}

class DirectoryReaderFileReference : public VFSFileReference {
public:
Path path;
Expand Down
1 change: 1 addition & 0 deletions Common/File/VFS/DirectoryReader.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ class DirectoryReader : public VFSBackend {

bool GetFileListing(const char *path, std::vector<File::FileInfo> *listing, const char *filter) override;
bool GetFileInfo(const char *path, File::FileInfo *info) override;
bool Exists(const char *path) override;
std::string toString() const override {
return path_.ToString();
}
Expand Down
26 changes: 26 additions & 0 deletions Common/File/VFS/VFS.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,3 +118,29 @@ bool VFS::GetFileInfo(const char *path, File::FileInfo *info) {
} // Otherwise, the file was just missing. No need to log.
return false;
}

bool VFS::Exists(const char *path) {
if (IsLocalAbsolutePath(path)) {
// Local path, not VFS.
// INFO_LOG(Log::IO, "Not a VFS path: %s . Getting local file info.", path);
return File::Exists(Path(std::string(path)));
}

bool fileSystemFound = false;
int fn_len = (int)strlen(path);
for (const auto &entry : entries_) {
int prefix_len = (int)strlen(entry.prefix);
if (prefix_len >= fn_len) continue;
if (0 == memcmp(path, entry.prefix, prefix_len)) {
fileSystemFound = true;
if (entry.reader->Exists(path + prefix_len))
return true;
else
continue;
}
}
if (!fileSystemFound) {
ERROR_LOG(Log::IO, "Missing filesystem for '%s'", path);
} // Otherwise, the file was just missing. No need to log.
return false;
}
12 changes: 6 additions & 6 deletions Common/File/VFS/VFS.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ class VFSBackend : public VFSInterface {

// Filter support is optional but nice to have
virtual bool GetFileInfo(const char *path, File::FileInfo *info) = 0;
virtual bool Exists(const char *path) {
File::FileInfo info{};
return GetFileInfo(path, &info) && info.exists;
}

virtual std::string toString() const = 0;
};
Expand All @@ -70,14 +74,10 @@ class VFS : public VFSInterface {
// Always allocates an extra zero byte at the end, so that it
// can be used for text like shader sources.
uint8_t *ReadFile(const char *filename, size_t *size) override;
bool GetFileInfo(const char *filename, File::FileInfo *fileInfo);
bool GetFileListing(const char *path, std::vector<File::FileInfo> *listing, const char *filter = nullptr) override;

// Shortcut for cleaner code
bool Exists(const char *path) {
File::FileInfo info{};
return GetFileInfo(path, &info);
}
bool GetFileInfo(const char *filename, File::FileInfo *fileInfo);
bool Exists(const char *path);

private:
struct VFSEntry {
Expand Down
2 changes: 1 addition & 1 deletion Common/File/VFS/ZipFileReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ ZipFileReader *ZipFileReader::Create(const Path &zipFile, const char *inZipPath,
if (!path.empty() && path.back() != '/') {
path.push_back('/');
}
return new ZipFileReader(zip_file, path);
return new ZipFileReader(zip_file, zipFile, path);
}

ZipFileReader::~ZipFileReader() {
Expand Down
10 changes: 8 additions & 2 deletions Common/File/VFS/ZipFileReader.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,21 @@ class ZipFileReader : public VFSBackend {
bool GetFileListing(const char *path, std::vector<File::FileInfo> *listing, const char *filter) override;
bool GetFileInfo(const char *path, File::FileInfo *info) override;
std::string toString() const override {
return inZipPath_;
std::string retval = zipPath_.ToVisualString();
if (!inZipPath_.empty()) {
retval += ": ";
retval += inZipPath_;
}
return retval;
}

private:
ZipFileReader(zip *zip_file, const std::string &inZipPath) : zip_file_(zip_file), inZipPath_(inZipPath) {}
ZipFileReader(zip *zip_file, const Path &zipPath, const std::string &inZipPath) : zip_file_(zip_file), zipPath_(zipPath), inZipPath_(inZipPath) {}
// Path has to be either an empty string, or a string ending with a /.
bool GetZipListings(const std::string &path, std::set<std::string> &files, std::set<std::string> &directories);

zip *zip_file_ = nullptr;
std::mutex lock_;
std::string inZipPath_;
Path zipPath_;
};
2 changes: 1 addition & 1 deletion Common/Log/LogManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ void LogManager::LogLine(LogLevel level, Log type, const char *file, int line, c
const char *threadName;
#if PPSSPP_PLATFORM(WINDOWS) || PPSSPP_PLATFORM(MAC)
const char *hostThreadName = GetCurrentThreadName();
if (strcmp(hostThreadName, "EmuThread") != 0 || !hleCurrentThreadName) {
if (hostThreadName && strcmp(hostThreadName, "EmuThread") != 0 || !hleCurrentThreadName) {
// Use the host thread name.
threadName = hostThreadName;
} else {
Expand Down
Loading

0 comments on commit 7b0551f

Please sign in to comment.