summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2020-01-19 13:58:16 +0100
committerAndreas Kling <kling@serenityos.org>2020-01-19 14:01:32 +0100
commit167b57a6b7b9f63a5f17e7a958269921cc692480 (patch)
treea27993684285db206b7287bd681fcf0d021ddd4b
parent1d02ac35fc1d9ff98603db27016d5bfa0af1e1fc (diff)
downloadserenity-167b57a6b7b9f63a5f17e7a958269921cc692480.zip
TmpFS: Grow the underlying inode buffer with 2x factor when written to
Before this, we would end up in memcpy() churn hell when a program was doing repeated write() calls to a file in /tmp. An even better solution will be to only grow the VM allocation of the underlying buffer and keep using the same physical pages. This would eliminate all the memcpy() work. I've benchmarked this using g++ to compile Kernel/Process.cpp. With these changes, compilation goes from ~35 sec to ~31 sec. :^)
-rw-r--r--Kernel/FileSystem/TmpFS.cpp10
1 files changed, 9 insertions, 1 deletions
diff --git a/Kernel/FileSystem/TmpFS.cpp b/Kernel/FileSystem/TmpFS.cpp
index 719073bdeb..eb7e3ce545 100644
--- a/Kernel/FileSystem/TmpFS.cpp
+++ b/Kernel/FileSystem/TmpFS.cpp
@@ -208,7 +208,15 @@ ssize_t TmpFSInode::write_bytes(off_t offset, ssize_t size, const u8* buffer, Fi
if (m_content.has_value() && m_content.value().capacity() >= (size_t)new_size) {
m_content.value().set_size(new_size);
} else {
- auto tmp = KBuffer::create_with_size(new_size);
+ // Grow the content buffer 2x the new sizeto accomodate repeating write() calls.
+ // Note that we're not actually committing physical memory to the buffer
+ // until it's needed. We only grow VM here.
+
+ // FIXME: Fix this so that no memcpy() is necessary, and we can just grow the
+ // KBuffer and it will add physical pages as needed while keeping the
+ // existing ones.
+ auto tmp = KBuffer::create_with_size(new_size * 2);
+ tmp.set_size(new_size);
if (m_content.has_value())
memcpy(tmp.data(), m_content.value().data(), old_size);
m_content = move(tmp);