mirror of
https://git.eden-emu.dev/eden-emu/eden
synced 2026-05-13 17:28:35 +02:00
super align + nosync opts
This commit is contained in:
parent
4e042ad3a7
commit
aefed3f0c2
1 changed files with 48 additions and 10 deletions
|
|
@ -13,6 +13,7 @@
|
||||||
#include "common/fs/fs_android.h"
|
#include "common/fs/fs_android.h"
|
||||||
#endif
|
#endif
|
||||||
#include "common/logging.h"
|
#include "common/logging.h"
|
||||||
|
#include "common/literals.h"
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include <io.h>
|
#include <io.h>
|
||||||
|
|
@ -273,18 +274,59 @@ void IOFile::Open(const fs::path& path, FileAccessMode mode, FileType type, File
|
||||||
} else {
|
} else {
|
||||||
file = std::fopen(path.c_str(), AccessModeToStr(mode, type));
|
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) {
|
if (type == FileType::BinaryFile && mode == FileAccessMode::Read) {
|
||||||
struct stat st;
|
struct stat st;
|
||||||
mmap_fd = open(path.c_str(), O_RDONLY);
|
mmap_fd = open(path.c_str(), O_RDONLY);
|
||||||
fstat(mmap_fd, &st);
|
fstat(mmap_fd, &st);
|
||||||
mmap_size = st.st_size;
|
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));
|
file = std::fopen(path.c_str(), AccessModeToStr(mode, type));
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
file = std::fopen(path.c_str(), AccessModeToStr(mode, type));
|
|
||||||
#endif
|
#endif
|
||||||
if (!IsOpen()) {
|
if (!IsOpen()) {
|
||||||
const auto ec = std::error_code{errno, std::generic_category()};
|
const auto ec = std::error_code{errno, std::generic_category()};
|
||||||
|
|
@ -340,11 +382,7 @@ bool IOFile::Flush() const {
|
||||||
#endif
|
#endif
|
||||||
if (file) {
|
if (file) {
|
||||||
errno = 0;
|
errno = 0;
|
||||||
#ifdef _WIN32
|
auto const flush_result = std::fflush(file) == 0;
|
||||||
const auto flush_result = std::fflush(file) == 0;
|
|
||||||
#else
|
|
||||||
const auto flush_result = std::fflush(file) == 0;
|
|
||||||
#endif
|
|
||||||
if (!flush_result) {
|
if (!flush_result) {
|
||||||
const auto ec = std::error_code{errno, std::generic_category()};
|
const auto ec = std::error_code{errno, std::generic_category()};
|
||||||
LOG_ERROR(Common_Filesystem, "Failed to flush the file at path={}, ec_message={}",
|
LOG_ERROR(Common_Filesystem, "Failed to flush the file at path={}, ec_message={}",
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue