super align + nosync opts
This commit is contained in:
parent
629dc72de7
commit
254dccf6e7
|
|
@ -13,6 +13,7 @@
|
|||
#include "common/fs/fs_android.h"
|
||||
#endif
|
||||
#include "common/logging/log.h"
|
||||
#include "common/literals.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <io.h>
|
||||
|
|
@ -273,18 +274,59 @@ void IOFile::Open(const fs::path& path, FileAccessMode mode, FileType type, File
|
|||
} else {
|
||||
file = std::fopen(path.c_str(), AccessModeToStr(mode, type));
|
||||
}
|
||||
#elif defined(__unix__) && !defined(__HAIKU__) && !defined(__managarm__)
|
||||
#elif defined(__HAIKU__) || defined(__managarm__) || defined(__OPENORBIS__)
|
||||
file = std::fopen(path.c_str(), AccessModeToStr(mode, type));
|
||||
#else
|
||||
if (type == FileType::BinaryFile && mode == FileAccessMode::Read) {
|
||||
struct stat st;
|
||||
mmap_fd = open(path.c_str(), O_RDONLY);
|
||||
fstat(mmap_fd, &st);
|
||||
mmap_size = st.st_size;
|
||||
mmap_base = (u8*)mmap(nullptr, mmap_size, PROT_READ, MAP_PRIVATE, mmap_fd, 0);
|
||||
} else {
|
||||
|
||||
int map_flags = MAP_PRIVATE;
|
||||
#ifdef MAP_PREFAULT_READ
|
||||
// Prefaults reads so the final resulting pagetable from this big stupid mmap()
|
||||
// isn't comically lazily loaded, we just coalesce everything in-place for our
|
||||
// lovely mmap flags; if we didn't prefault the reads the page table will be
|
||||
// constructed in-place (i.e on a read-by-read basis) causing lovely soft-faults
|
||||
// which would nuke any performance gains.
|
||||
//
|
||||
// This of course incurs a cost in the initial mmap(2) call, but that is fine.
|
||||
map_flags |= MAP_PREFAULT_READ;
|
||||
#endif
|
||||
#ifdef MAP_NOSYNC
|
||||
// This causes physical media to not be synched to our file/memory
|
||||
// This means that if the read-only file is written to, we won't see changes
|
||||
// or we may see changes which are just funnily scattered, in any case
|
||||
// this presumes the files won't be changed during execution
|
||||
//
|
||||
// Do not ever use this on write files (if we ever support that); this will create
|
||||
// a fun amount of fragmentation on the disk.
|
||||
map_flags |= MAP_NOSYNC;
|
||||
#endif
|
||||
#ifdef MAP_ALIGNED_SUPER
|
||||
// File must be big enough that it's worth to super align. We can't just super-align every
|
||||
// file otherwise we will run out of alignments for actually important files :)
|
||||
// System doesn't guarantee a super alignment, but if it's available it will delete
|
||||
// about 3 layers(?) of the TLB tree for each read/write.
|
||||
// Again the cost of faults may make this negligible gains, but hey, we gotta work
|
||||
// what we gotta work with.
|
||||
using namespace Common::Literals;
|
||||
u64 big_file_threshold = 512_MiB;
|
||||
map_flags |= u64(st.st_size) >= big_file_threshold ? MAP_ALIGNED_SUPER : 0;
|
||||
#endif
|
||||
mmap_base = (u8*)mmap(nullptr, mmap_size, PROT_READ, map_flags, mmap_fd, 0);
|
||||
if (mmap_base == MAP_FAILED) {
|
||||
close(mmap_fd);
|
||||
mmap_fd = -1;
|
||||
} else {
|
||||
posix_madvise(mmap_base, mmap_size, POSIX_MADV_WILLNEED);
|
||||
}
|
||||
}
|
||||
// mmap(2) failed or simply we can't use it
|
||||
if (mmap_fd == -1) {
|
||||
file = std::fopen(path.c_str(), AccessModeToStr(mode, type));
|
||||
}
|
||||
#else
|
||||
file = std::fopen(path.c_str(), AccessModeToStr(mode, type));
|
||||
#endif
|
||||
if (!IsOpen()) {
|
||||
const auto ec = std::error_code{errno, std::generic_category()};
|
||||
|
|
@ -340,11 +382,7 @@ bool IOFile::Flush() const {
|
|||
#endif
|
||||
if (file) {
|
||||
errno = 0;
|
||||
#ifdef _WIN32
|
||||
const auto flush_result = std::fflush(file) == 0;
|
||||
#else
|
||||
const auto flush_result = std::fflush(file) == 0;
|
||||
#endif
|
||||
auto const flush_result = std::fflush(file) == 0;
|
||||
if (!flush_result) {
|
||||
const auto ec = std::error_code{errno, std::generic_category()};
|
||||
LOG_ERROR(Common_Filesystem, "Failed to flush the file at path={}, ec_message={}",
|
||||
|
|
|
|||
Loading…
Reference in New Issue