mirror of
https://github.com/libretro/opera-libretro.git
synced 2026-11-07 12:37:52 -10:00
Every sector read was a seek and a read through the VFS, and a CHD copied each compressed hunk twice on its way to the decoder: from the file into a 64 KiB request buffer, in pieces of at most 64 KiB, then into the decoder's own staging buffer. - Images are opened with RETRO_VFS_FILE_ACCESS_HINT_FREQUENT_ACCESS, and HAVE_MMAP is now defined for unix, osx and Android, so the local VFS maps them. A BIN/ISO/CUE sector read becomes a copy out of the page cache into the drive's buffer, which is the one copy the emulated drive needs. - CHD: the compressed hunk is lent to the decoder straight from the mapping (rchd_feed_borrow), so it is never copied. Unmapped (a frontend VFS, a platform without mapping, a file too big to map), each hunk is read in one call into a buffer sized to a hunk at open and lent from there, rather than copied in again. The open sequence is still fed by copy. The file position is tracked so a read that continues where the last one stopped does not seek. - On a mapped CHD the OS is asked to bring the next 1 MiB of the file in ahead of the decoder (filestream_prefetch), coalesced so one request covers many hunks; cold pages would otherwise stall the emulation thread on a page fault. - BIN/ISO/CUE: a read that starts where the previous one ended skips the seek. Measured over 20 passes of every sector of a 2400-sector test disc: BIN/CUE went from 75593 read/lseek syscalls to 9 and from 0.57 to 0.22 us per sector; a CHD from 13392 syscalls to 26 (default hunks) and from 1493 to 28 (1 MiB hunks). Unmapped, lseeks on a CHD dropped from 6009 to 26 and 1 MiB-hunk reads from 984 to 264. tools/chd/run.sh now also checks every codec at the largest hunk chdman writes (1 MiB), and passes under ASan/UBSan on both the mapped and the unmapped path.