From a7e8be1e04382d4497134ce8162dcad823a8c584 Mon Sep 17 00:00:00 2001 From: Sebastian Messmer Date: Tue, 29 Sep 2015 21:47:50 +0200 Subject: [PATCH] Added fspp profiling --- impl/FilesystemImpl.cpp | 99 ++++++++++++++++++++++++++++++++++++++++- impl/FilesystemImpl.h | 41 +++++++++++++++++ impl/Profiler.cpp | 1 + impl/Profiler.h | 28 ++++++++++++ 4 files changed, 168 insertions(+), 1 deletion(-) create mode 100644 impl/Profiler.cpp create mode 100644 impl/Profiler.h diff --git a/impl/FilesystemImpl.cpp b/impl/FilesystemImpl.cpp index 9bf92136..276c6425 100644 --- a/impl/FilesystemImpl.cpp +++ b/impl/FilesystemImpl.cpp @@ -21,14 +21,78 @@ using boost::none; namespace bf = boost::filesystem; +#ifdef FSPP_PROFILE +#include "Profiler.h" +#include +#include +#define PROFILE(name) Profiler profiler_##name(&name); +#else +#define PROFILE(name) +#endif + FilesystemImpl::FilesystemImpl(Device *device) - :_device(device), _open_files() { + : +#ifdef FSPP_PROFILE + _loadFileNanosec(0), _loadDirNanosec(0), _loadSymlinkNanosec(0), _openFileNanosec(0), _flushNanosec(0), + _closeFileNanosec(0), _lstatNanosec(0), _fstatNanosec(0), _chmodNanosec(0), _chownNanosec(0), _truncateNanosec(0), + _ftruncateNanosec(0), _readNanosec(0), _writeNanosec(0), _fsyncNanosec(0), _fdatasyncNanosec(0), _accessNanosec(0), + _createAndOpenFileNanosec(0), _createAndOpenFileNanosec_withoutLoading(0), _mkdirNanosec(0), + _mkdirNanosec_withoutLoading(0), _rmdirNanosec(0), _rmdirNanosec_withoutLoading(0), _unlinkNanosec(0), + _unlinkNanosec_withoutLoading(0), _renameNanosec(0), _readDirNanosec(0), _readDirNanosec_withoutLoading(0), + _utimensNanosec(0), _statfsNanosec(0), _createSymlinkNanosec(0), _createSymlinkNanosec_withoutLoading(0), + _readSymlinkNanosec(0), _readSymlinkNanosec_withoutLoading(0), +#endif + _device(device), _open_files() +{ } FilesystemImpl::~FilesystemImpl() { +#ifdef FSPP_PROFILE + std::cout + << "---------------------------------------------------------------------------\n" + << "Profiler Information\n" + << "---------------------------------------------------------------------------\n" + << std::fixed << std::setprecision(6) + << std::setw(40) << "LoadFile: " << static_cast(_loadFileNanosec)/1000000000 << "\n" + << std::setw(40) << "LoadDir: " << static_cast(_loadDirNanosec)/1000000000 << "\n" + << std::setw(40) << "LoadSymlink: " << static_cast(_loadSymlinkNanosec)/1000000000 << "\n" + << std::setw(40) << "OpenFile: " << static_cast(_openFileNanosec)/1000000000 << "\n" + << std::setw(40) << "Flush: " << static_cast(_flushNanosec)/1000000000 << "\n" + << std::setw(40) << "CloseFile: " << static_cast(_closeFileNanosec)/1000000000 << "\n" + << std::setw(40) << "Lstat: " << static_cast(_lstatNanosec)/1000000000 << "\n" + << std::setw(40) << "Fstat: " << static_cast(_fstatNanosec)/1000000000 << "\n" + << std::setw(40) << "Chmod: " << static_cast(_chmodNanosec)/1000000000 << "\n" + << std::setw(40) << "Chown: " << static_cast(_chownNanosec)/1000000000 << "\n" + << std::setw(40) << "Truncate: " << static_cast(_truncateNanosec)/1000000000 << "\n" + << std::setw(40) << "Ftruncate: " << static_cast(_ftruncateNanosec)/1000000000 << "\n" + << std::setw(40) << "Read: " << static_cast(_readNanosec)/1000000000 << "\n" + << std::setw(40) << "Write: " << static_cast(_writeNanosec)/1000000000 << "\n" + << std::setw(40) << "Fsync: " << static_cast(_fsyncNanosec)/1000000000 << "\n" + << std::setw(40) << "Fdatasync: " << static_cast(_fdatasyncNanosec)/1000000000 << "\n" + << std::setw(40) << "Access: " << static_cast(_accessNanosec)/1000000000 << "\n" + << std::setw(40) << "CreateAndOpenFile: " << static_cast(_createAndOpenFileNanosec)/1000000000 << "\n" + << std::setw(40) << "CreateAndOpenFile (without loading): " << static_cast(_createAndOpenFileNanosec_withoutLoading)/1000000000 << "\n" + << std::setw(40) << "Mkdir: " << static_cast(_mkdirNanosec)/1000000000 << "\n" + << std::setw(40) << "Mkdir (without loading): " << static_cast(_mkdirNanosec_withoutLoading)/1000000000 << "\n" + << std::setw(40) << "Rmdir: " << static_cast(_rmdirNanosec)/1000000000 << "\n" + << std::setw(40) << "Rmdir (without loading): " << static_cast(_rmdirNanosec_withoutLoading)/1000000000 << "\n" + << std::setw(40) << "Unlink: " << static_cast(_unlinkNanosec)/1000000000 << "\n" + << std::setw(40) << "Unlink (without loading): " << static_cast(_unlinkNanosec_withoutLoading)/1000000000 << "\n" + << std::setw(40) << "Rename: " << static_cast(_renameNanosec)/1000000000 << "\n" + << std::setw(40) << "ReadDir: " << static_cast(_readDirNanosec)/1000000000 << "\n" + << std::setw(40) << "ReadDir (without loading): " << static_cast(_readDirNanosec_withoutLoading)/1000000000 << "\n" + << std::setw(40) << "Utimens: " << static_cast(_utimensNanosec)/1000000000 << "\n" + << std::setw(40) << "Statfs: " << static_cast(_statfsNanosec)/1000000000 << "\n" + << std::setw(40) << "CreateSymlink: " << static_cast(_createSymlinkNanosec)/1000000000 << "\n" + << std::setw(40) << "CreateSymlink (without loading): " << static_cast(_createSymlinkNanosec_withoutLoading)/1000000000 << "\n" + << std::setw(40) << "ReadSymlink: " << static_cast(_readSymlinkNanosec)/1000000000 << "\n" + << std::setw(40) << "ReadSymlink (without loading): " << static_cast(_readSymlinkNanosec_withoutLoading)/1000000000 << "\n" + << "---------------------------------------------------------------------------\n" << std::flush; +#endif } unique_ref FilesystemImpl::LoadFile(const bf::path &path) { + PROFILE(_loadFileNanosec); auto node = _device->Load(path); if (node == none) { throw fuse::FuseErrnoException(EIO); @@ -41,6 +105,7 @@ unique_ref FilesystemImpl::LoadFile(const bf::path &path) { } unique_ref FilesystemImpl::LoadDir(const bf::path &path) { + PROFILE(_loadDirNanosec); auto node = _device->Load(path); if (node == none) { throw fuse::FuseErrnoException(EIO); @@ -53,6 +118,7 @@ unique_ref FilesystemImpl::LoadDir(const bf::path &path) { } unique_ref FilesystemImpl::LoadSymlink(const bf::path &path) { + PROFILE(_loadSymlinkNanosec); auto node = _device->Load(path); if (node == none) { throw fuse::FuseErrnoException(EIO); @@ -70,18 +136,22 @@ int FilesystemImpl::openFile(const bf::path &path, int flags) { } int FilesystemImpl::openFile(const File &file, int flags) { + PROFILE(_openFileNanosec); return _open_files.open(file.open(flags)); } void FilesystemImpl::flush(int descriptor) { + PROFILE(_flushNanosec); _open_files.get(descriptor)->flush(); } void FilesystemImpl::closeFile(int descriptor) { + PROFILE(_closeFileNanosec); _open_files.close(descriptor); } void FilesystemImpl::lstat(const bf::path &path, struct ::stat *stbuf) { + PROFILE(_lstatNanosec); auto node = _device->Load(path); if(node == none) { throw fuse::FuseErrnoException(ENOENT); @@ -91,10 +161,12 @@ void FilesystemImpl::lstat(const bf::path &path, struct ::stat *stbuf) { } void FilesystemImpl::fstat(int descriptor, struct ::stat *stbuf) { + PROFILE(_fstatNanosec); _open_files.get(descriptor)->stat(stbuf); } void FilesystemImpl::chmod(const boost::filesystem::path &path, mode_t mode) { + PROFILE(_chmodNanosec); auto node = _device->Load(path); if(node == none) { throw fuse::FuseErrnoException(ENOENT); @@ -104,6 +176,7 @@ void FilesystemImpl::chmod(const boost::filesystem::path &path, mode_t mode) { } void FilesystemImpl::chown(const boost::filesystem::path &path, uid_t uid, gid_t gid) { + PROFILE(_chownNanosec); auto node = _device->Load(path); if(node == none) { throw fuse::FuseErrnoException(ENOENT); @@ -113,30 +186,37 @@ void FilesystemImpl::chown(const boost::filesystem::path &path, uid_t uid, gid_t } void FilesystemImpl::truncate(const bf::path &path, off_t size) { + PROFILE(_truncateNanosec); LoadFile(path)->truncate(size); } void FilesystemImpl::ftruncate(int descriptor, off_t size) { + PROFILE(_ftruncateNanosec); _open_files.get(descriptor)->truncate(size); } int FilesystemImpl::read(int descriptor, void *buf, size_t count, off_t offset) { + PROFILE(_readNanosec); return _open_files.get(descriptor)->read(buf, count, offset); } void FilesystemImpl::write(int descriptor, const void *buf, size_t count, off_t offset) { + PROFILE(_writeNanosec); _open_files.get(descriptor)->write(buf, count, offset); } void FilesystemImpl::fsync(int descriptor) { + PROFILE(_fsyncNanosec); _open_files.get(descriptor)->fsync(); } void FilesystemImpl::fdatasync(int descriptor) { + PROFILE(_fdatasyncNanosec); _open_files.get(descriptor)->fdatasync(); } void FilesystemImpl::access(const bf::path &path, int mask) { + PROFILE(_accessNanosec); auto node = _device->Load(path); if(node == none) { throw fuse::FuseErrnoException(ENOENT); @@ -148,27 +228,36 @@ void FilesystemImpl::access(const bf::path &path, int mask) { int FilesystemImpl::createAndOpenFile(const bf::path &path, mode_t mode, uid_t uid, gid_t gid) { //TODO Creating the file opens and closes it. We then reopen it afterwards. // This is slow. Improve! + PROFILE(_createAndOpenFileNanosec); auto dir = LoadDir(path.parent_path()); + PROFILE(_createAndOpenFileNanosec_withoutLoading); auto file = dir->createAndOpenFile(path.filename().native(), mode, uid, gid); return _open_files.open(std::move(file)); } void FilesystemImpl::mkdir(const bf::path &path, mode_t mode, uid_t uid, gid_t gid) { + PROFILE(_mkdirNanosec); auto dir = LoadDir(path.parent_path()); + PROFILE(_mkdirNanosec_withoutLoading); dir->createDir(path.filename().native(), mode, uid, gid); } void FilesystemImpl::rmdir(const bf::path &path) { + PROFILE(_rmdirNanosec); auto dir = LoadDir(path); + PROFILE(_rmdirNanosec_withoutLoading); dir->remove(); } void FilesystemImpl::unlink(const bf::path &path) { + PROFILE(_unlinkNanosec); auto file = LoadFile(path); + PROFILE(_unlinkNanosec_withoutLoading); file->remove(); } void FilesystemImpl::rename(const bf::path &from, const bf::path &to) { + PROFILE(_renameNanosec); auto node = _device->Load(from); if(node == none) { throw fuse::FuseErrnoException(ENOENT); @@ -178,11 +267,14 @@ void FilesystemImpl::rename(const bf::path &from, const bf::path &to) { } unique_ref> FilesystemImpl::readDir(const bf::path &path) { + PROFILE(_readDirNanosec); auto dir = LoadDir(path); + PROFILE(_readDirNanosec_withoutLoading); return dir->children(); } void FilesystemImpl::utimens(const bf::path &path, const timespec times[2]) { + PROFILE(_utimensNanosec); auto node = _device->Load(path); if(node == none) { throw fuse::FuseErrnoException(ENOENT); @@ -192,16 +284,21 @@ void FilesystemImpl::utimens(const bf::path &path, const timespec times[2]) { } void FilesystemImpl::statfs(const bf::path &path, struct statvfs *fsstat) { + PROFILE(_statfsNanosec); _device->statfs(path, fsstat); } void FilesystemImpl::createSymlink(const bf::path &to, const bf::path &from, uid_t uid, gid_t gid) { + PROFILE(_createSymlinkNanosec); auto parent = LoadDir(from.parent_path()); + PROFILE(_createSymlinkNanosec_withoutLoading); parent->createSymlink(from.filename().native(), to, uid, gid); } void FilesystemImpl::readSymlink(const bf::path &path, char *buf, size_t size) { + PROFILE(_readSymlinkNanosec); string target = LoadSymlink(path)->target().native(); + PROFILE(_readSymlinkNanosec_withoutLoading); std::memcpy(buf, target.c_str(), std::min(target.size()+1, size)); buf[size-1] = '\0'; } diff --git a/impl/FilesystemImpl.h b/impl/FilesystemImpl.h index eb78f858..314a985d 100644 --- a/impl/FilesystemImpl.h +++ b/impl/FilesystemImpl.h @@ -6,6 +6,10 @@ #include "../fuse/Filesystem.h" #include +#include + +//Remove this line if you don't want profiling +#define FSPP_PROFILE 1 namespace fspp { class Node; @@ -49,6 +53,43 @@ private: cpputils::unique_ref LoadSymlink(const boost::filesystem::path &path); int openFile(const File &file, int flags); +#ifdef FSPP_PROFILE + std::atomic _loadFileNanosec; + std::atomic _loadDirNanosec; + std::atomic _loadSymlinkNanosec; + std::atomic _openFileNanosec; + std::atomic _flushNanosec; + std::atomic _closeFileNanosec; + std::atomic _lstatNanosec; + std::atomic _fstatNanosec; + std::atomic _chmodNanosec; + std::atomic _chownNanosec; + std::atomic _truncateNanosec; + std::atomic _ftruncateNanosec; + std::atomic _readNanosec; + std::atomic _writeNanosec; + std::atomic _fsyncNanosec; + std::atomic _fdatasyncNanosec; + std::atomic _accessNanosec; + std::atomic _createAndOpenFileNanosec; + std::atomic _createAndOpenFileNanosec_withoutLoading; + std::atomic _mkdirNanosec; + std::atomic _mkdirNanosec_withoutLoading; + std::atomic _rmdirNanosec; + std::atomic _rmdirNanosec_withoutLoading; + std::atomic _unlinkNanosec; + std::atomic _unlinkNanosec_withoutLoading; + std::atomic _renameNanosec; + std::atomic _readDirNanosec; + std::atomic _readDirNanosec_withoutLoading; + std::atomic _utimensNanosec; + std::atomic _statfsNanosec; + std::atomic _createSymlinkNanosec; + std::atomic _createSymlinkNanosec_withoutLoading; + std::atomic _readSymlinkNanosec; + std::atomic _readSymlinkNanosec_withoutLoading; +#endif + Device *_device; FuseOpenFileList _open_files; diff --git a/impl/Profiler.cpp b/impl/Profiler.cpp new file mode 100644 index 00000000..ebab91c1 --- /dev/null +++ b/impl/Profiler.cpp @@ -0,0 +1 @@ +#include "Profiler.h" diff --git a/impl/Profiler.h b/impl/Profiler.h new file mode 100644 index 00000000..a706a7ea --- /dev/null +++ b/impl/Profiler.h @@ -0,0 +1,28 @@ +#ifndef FSPP_IMPL_PROFILER_H +#define FSPP_IMPL_PROFILER_H + +#include +#include + +namespace fspp { + class Profiler { + public: + Profiler(std::atomic_uint_fast64_t *targetForAddingNanosec); + ~Profiler(); + + private: + std::atomic_uint_fast64_t *_targetForAddingNanosec; + std::chrono::high_resolution_clock::time_point _beginTime; + }; + + inline Profiler::Profiler(std::atomic_uint_fast64_t *targetForAddingNanosec) + : _targetForAddingNanosec(targetForAddingNanosec), _beginTime(std::chrono::high_resolution_clock::now()) { + } + + inline Profiler::~Profiler() { + uint64_t timeDiff = std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - _beginTime).count(); + *_targetForAddingNanosec += timeDiff; + } +} + +#endif