From: Lucian Grijincu Date: Wed, 8 Apr 2015 18:14:28 +0000 (-0700) Subject: folly: MemoryMapping: add offset/size params to advise X-Git-Tag: v0.35.0~5 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=51026ab6092a4bd8d7dc295d4b19245d63babdc6;p=folly.git folly: MemoryMapping: add offset/size params to advise Test Plan: ran it Reviewed By: philipp@fb.com Subscribers: folly-diffs@, yfeldblum, chalfant FB internal diff: D1974936 Signature: t1:1974936:1428453023:1a83ed8336f75b745bffc633b8471231423b0fb0 --- diff --git a/folly/MemoryMapping.cpp b/folly/MemoryMapping.cpp index 43889257..3d8e3a55 100644 --- a/folly/MemoryMapping.cpp +++ b/folly/MemoryMapping.cpp @@ -15,8 +15,12 @@ */ #include + +#include +#include +#include + #include -#include #ifdef __linux__ #include @@ -240,9 +244,8 @@ bool MemoryMapping::mlock(LockMode lock) { return true; } - auto msg(folly::format( - "mlock({}) failed at {}", - mapLength_, amountSucceeded).str()); + auto msg = + folly::sformat("mlock({}) failed at {}", mapLength_, amountSucceeded); if (lock == LockMode::TRY_LOCK && (errno == EPERM || errno == ENOMEM)) { PLOG(WARNING) << msg; @@ -283,17 +286,35 @@ MemoryMapping::~MemoryMapping() { size_t amountSucceeded = 0; if (!memOpInChunks(::munmap, mapStart_, mapLength_, options_.pageSize, amountSucceeded)) { - PLOG(FATAL) << folly::format( - "munmap({}) failed at {}", - mapLength_, amountSucceeded).str(); + PLOG(FATAL) << folly::format("munmap({}) failed at {}", + mapLength_, amountSucceeded); } } } -void MemoryMapping::advise(int advice) const { - if (mapLength_ && ::madvise(mapStart_, mapLength_, advice)) { - PLOG(WARNING) << "madvise()"; +void MemoryMapping::advise(int advice) const { advise(advice, 0, mapLength_); } + +void MemoryMapping::advise(int advice, size_t offset, size_t length) const { + CHECK_LE(offset + length, mapLength_) + << " offset: " << offset + << " length: " << length + << " mapLength_: " << mapLength_; + + if (length == 0) { + return; + } + + auto offMisalign = offset % options_.pageSize; + if (offMisalign != 0) { + offset -= offMisalign; + length += offMisalign; } + + length = (length + options_.pageSize - 1) & ~(options_.pageSize - 1); + length = std::min(length, mapLength_ - offset); + + char* mapStart = static_cast(mapStart_) + offset; + PLOG_IF(WARNING, ::madvise(mapStart, length, advice)) << "madvise"; } MemoryMapping& MemoryMapping::operator=(MemoryMapping other) { diff --git a/folly/MemoryMapping.h b/folly/MemoryMapping.h index 158b62ac..a1ca7444 100644 --- a/folly/MemoryMapping.h +++ b/folly/MemoryMapping.h @@ -157,6 +157,7 @@ class MemoryMapping : boost::noncopyable { * Advise the kernel about memory access. */ void advise(int advice) const; + void advise(int advice, size_t offset, size_t length) const; /** * A bitwise cast of the mapped bytes as range of values. Only intended for diff --git a/folly/test/MemoryMappingTest.cpp b/folly/test/MemoryMappingTest.cpp index 9d11fbb3..70ecc719 100644 --- a/folly/test/MemoryMappingTest.cpp +++ b/folly/test/MemoryMappingTest.cpp @@ -14,9 +14,11 @@ * limitations under the License. */ +#include #include -#include +#include #include +#include namespace folly { @@ -145,4 +147,29 @@ TEST(MemoryMapping, ZeroLength) { EXPECT_EQ(0, m.data().size()); } +TEST(MemoryMapping, Advise) { + File f = File::temporary(); + size_t kPageSize = 4096; + size_t size = kPageSize + 10; // unaligned file size + PCHECK(ftruncateNoInt(f.fd(), size) == 0) << size; + + MemoryMapping m(File(f.fd())); + + // NOTE: advise crashes on bad input. + + m.advise(MADV_NORMAL, 0, kPageSize); + m.advise(MADV_NORMAL, 1, kPageSize); + m.advise(MADV_NORMAL, 0, 2); + m.advise(MADV_NORMAL, 1, 2); + + m.advise(MADV_NORMAL, kPageSize, 0); + m.advise(MADV_NORMAL, kPageSize, 1); + m.advise(MADV_NORMAL, kPageSize, size - kPageSize); + + auto off = kPageSize + 1; + m.advise(MADV_NORMAL, off, size - off); + + EXPECT_DEATH(m.advise(MADV_NORMAL, off, size - off + 1), ""); +} + } // namespace folly