From f8d551803cfb6c1db3d24f7ef2731c652b9a5313 Mon Sep 17 00:00:00 2001 From: Bastien Bouclet Date: Sun, 20 Oct 2019 09:23:51 +0200 Subject: POSIX: Use fstat instead of fseek / ftell to retrieve file stream sizes fstat is generally faster as is does not cause the IO buffer to be invalidated / refilled. Benchmark results for the startup time of the SCI engine with Gabriel Knight 1 CD: - Linux, glibc, spinning HDD, fseek/ftell: 140 ms - Linux, glibc, spinning HDD, fstat: 100 ms - 3DS, newlib, SD card, fseek/ftell: 68 s - 3DS, newlib, SD card, fstat: 11 s --- backends/fs/posix/posix-fs.cpp | 6 ++-- backends/fs/posix/posix-iostream.cpp | 56 ++++++++++++++++++++++++++++++++++++ backends/fs/posix/posix-iostream.h | 39 +++++++++++++++++++++++++ 3 files changed, 98 insertions(+), 3 deletions(-) create mode 100644 backends/fs/posix/posix-iostream.cpp create mode 100644 backends/fs/posix/posix-iostream.h (limited to 'backends/fs/posix') diff --git a/backends/fs/posix/posix-fs.cpp b/backends/fs/posix/posix-fs.cpp index 82ae597745..a908729dd7 100644 --- a/backends/fs/posix/posix-fs.cpp +++ b/backends/fs/posix/posix-fs.cpp @@ -33,7 +33,7 @@ #define FORBIDDEN_SYMBOL_EXCEPTION_srandom #include "backends/fs/posix/posix-fs.h" -#include "backends/fs/stdiostream.h" +#include "backends/fs/posix/posix-iostream.h" #include "common/algorithm.h" #include @@ -312,11 +312,11 @@ AbstractFSNode *POSIXFilesystemNode::getParent() const { } Common::SeekableReadStream *POSIXFilesystemNode::createReadStream() { - return StdioStream::makeFromPath(getPath(), false); + return PosixIoStream::makeFromPath(getPath(), false); } Common::WriteStream *POSIXFilesystemNode::createWriteStream() { - return StdioStream::makeFromPath(getPath(), true); + return PosixIoStream::makeFromPath(getPath(), true); } bool POSIXFilesystemNode::createDirectory() { diff --git a/backends/fs/posix/posix-iostream.cpp b/backends/fs/posix/posix-iostream.cpp new file mode 100644 index 0000000000..59f14142b5 --- /dev/null +++ b/backends/fs/posix/posix-iostream.cpp @@ -0,0 +1,56 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#define FORBIDDEN_SYMBOL_ALLOW_ALL + +#include "backends/fs/posix/posix-iostream.h" + +#include + +PosixIoStream *PosixIoStream::makeFromPath(const Common::String &path, bool writeMode) { + FILE *handle = fopen(path.c_str(), writeMode ? "wb" : "rb"); + + if (handle) + return new PosixIoStream(handle); + + return nullptr; +} + +PosixIoStream::PosixIoStream(void *handle) : + StdioStream(handle) { +} + +int32 PosixIoStream::size() const { + int fd = fileno((FILE *)_handle); + if (fd == -1) { + return StdioStream::size(); + } + + // Using fstat to obtain the file size is generally faster than fseek / ftell + // because it does not affect the IO buffer. + struct stat st; + if (fstat(fd, &st) == -1) { + return StdioStream::size(); + } + + return st.st_size; +} diff --git a/backends/fs/posix/posix-iostream.h b/backends/fs/posix/posix-iostream.h new file mode 100644 index 0000000000..638d7b17cd --- /dev/null +++ b/backends/fs/posix/posix-iostream.h @@ -0,0 +1,39 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef BACKENDS_FS_POSIX_POSIXIOSTREAM_H +#define BACKENDS_FS_POSIX_POSIXIOSTREAM_H + +#include "backends/fs/stdiostream.h" + +/** + * A file input / output stream using POSIX interfaces + */ +class PosixIoStream : public StdioStream { +public: + static PosixIoStream *makeFromPath(const Common::String &path, bool writeMode); + PosixIoStream(void *handle); + + int32 size() const override; +}; + +#endif -- cgit v1.2.3