aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorRobin Haberkorn <robin.haberkorn@googlemail.com>2013-01-22 18:04:19 +0100
committerRobin Haberkorn <robin.haberkorn@googlemail.com>2013-01-22 18:39:32 +0100
commit8d2362930fb5b998fbb0a638e51b1ca74a2a1c1a (patch)
tree750e718baf266e58ca58ba75c3e36301e724ca66
parent821c61e9967e62fd81038e4b879c5452bffe2dfb (diff)
This reverts commit 821c61e9967e62fd81038e4b879c5452bffe2dfb.
memory mapping the entire file has been benchmarked to be less efficient than the old implementation (because of more than doubling page faults). A lengthy comment has been written to discuss different implementations of file reading.
-rw-r--r--src/ring.cpp39
1 files changed, 30 insertions, 9 deletions
diff --git a/src/ring.cpp b/src/ring.cpp
index ed9e77c..2656ae9 100644
--- a/src/ring.cpp
+++ b/src/ring.cpp
@@ -102,27 +102,48 @@ Buffer::UndoTokenClose::run(void)
delete buffer;
}
+/*
+ * The following simple implementation of file reading is actually the
+ * most efficient and useful in the common case of editing small files,
+ * since
+ * a) it works with minimal number of syscalls and
+ * b) small files cause little temporary memory overhead.
+ * Reading large files however could be very inefficient since the file
+ * must first be read into memory and then copied in-memory. Also it could
+ * result in thrashing.
+ * Alternatively we could iteratively read into a smaller buffer trading
+ * in speed against (temporary) memory consumption.
+ * The best way to do it could be memory mapping the file as we could
+ * let Scintilla copy from the file's virtual memory directly.
+ * Unfortunately since every page of the mapped file is
+ * only touched once by Scintilla TLB caching is useless and the TLB is
+ * effectively thrashed with entries of the mapped file.
+ * This results in the doubling of page faults and weighs out the other
+ * advantages of memory mapping (has been benchmarked).
+ *
+ * So in the future, the following approach could be implemented:
+ * 1.) On Unix/Posix, mmap() one page at a time, hopefully preventing
+ * TLB thrashing.
+ * 2.) On other platforms read into and copy from a statically sized buffer
+ * (perhaps page-sized)
+ */
bool
Buffer::load(const gchar *filename)
{
- GMappedFile *file;
- gsize length;
+ gchar *contents;
+ gsize size;
- file = g_mapped_file_new(filename, FALSE, NULL);
- if (!file)
+ if (!g_file_get_contents(filename, &contents, &size, NULL))
return false;
- length = g_mapped_file_get_length(file);
edit();
interface.ssm(SCI_BEGINUNDOACTION);
interface.ssm(SCI_CLEARALL);
- if (length > 0)
- interface.ssm(SCI_APPENDTEXT, length,
- (sptr_t)g_mapped_file_get_contents(file));
+ interface.ssm(SCI_APPENDTEXT, size, (sptr_t)contents);
interface.ssm(SCI_ENDUNDOACTION);
- g_mapped_file_unref(file);
+ g_free(contents);
/* NOTE: currently buffer cannot be dirty */
#if 0