Fix GuardPageAllocator to do mprotect lazily
authorAndrii Grynenko <andrii@fb.com>
Thu, 14 Apr 2016 04:30:45 +0000 (21:30 -0700)
committerFacebook Github Bot 1 <facebook-github-bot-1-bot@fb.com>
Thu, 14 Apr 2016 04:35:22 +0000 (21:35 -0700)
Summary:Currently GuargPageAllocator mmap's a memory block enough for 100 fiber stacks and then protects a bottom page for each stack. If FiberManager is used to process a single task, protecting 100 stacks doesn't make much sense, but is costly.

This change makes sure we protect a bottom page of every stack the first time given stack is requested.

Reviewed By: alikhtarov

Differential Revision: D3139944

fb-gh-sync-id: d9d724eaa0e65a227eac1d09a33018e6cb098aae
fbshipit-source-id: d9d724eaa0e65a227eac1d09a33018e6cb098aae

folly/experimental/fibers/GuardPageAllocator.cpp
folly/experimental/fibers/test/FibersTest.cpp

index 0a732ae1febd972dc9dd31331e92aa7fecb0fc9e..f4ff2015ed0235bb794c3c235b561b270bf423f5 100644 (file)
@@ -64,8 +64,7 @@ class StackCache {
     /* Protect the bottommost page of every stack allocation */
     for (size_t i = 0; i < kNumGuarded; ++i) {
       auto allocBegin = storage_ + allocSize_ * i;
-      freeList_.push_back(allocBegin);
-      PCHECK(0 == ::mprotect(allocBegin, pagesize(), PROT_NONE));
+      freeList_.emplace_back(allocBegin, /* protected= */ false);
     }
   }
 
@@ -79,7 +78,10 @@ class StackCache {
       return nullptr;
     }
 
-    auto p = freeList_.back();
+    auto p = freeList_.back().first;
+    if (!freeList_.back().second) {
+      PCHECK(0 == ::mprotect(p, pagesize(), PROT_NONE));
+    }
     freeList_.pop_back();
 
     /* We allocate minimum number of pages required, plus a guard page.
@@ -112,7 +114,7 @@ class StackCache {
 
     assert(as == allocSize_);
     assert((p - storage_) % allocSize_ == 0);
-    freeList_.push_back(p);
+    freeList_.emplace_back(p, /* protected= */ true);
     return true;
   }
 
@@ -127,9 +129,9 @@ class StackCache {
   size_t allocSize_{0};
 
   /**
-   * LIFO free list
+   * LIFO free list. Each pair contains stack pointer and protected flag.
    */
-  std::vector<unsigned char*> freeList_;
+  std::vector<std::pair<unsigned char*, bool>> freeList_;
 
   static size_t pagesize() {
     static const size_t pagesize = sysconf(_SC_PAGESIZE);
index f2c5ba97d2052dc5b8218571268fe68c9c00fb90..4fe936455ef7046d80e3ba7a139653e7546172e8 100644 (file)
@@ -1628,6 +1628,15 @@ BENCHMARK(FiberManagerBasicFiveAwaits, iters) {
   runBenchmark(5, iters);
 }
 
+BENCHMARK(FiberManagerCreateDestroy, iters) {
+  for (size_t i = 0; i < iters; ++i) {
+    folly::EventBase evb;
+    auto& fm = folly::fibers::getFiberManager(evb);
+    fm.addTask([]() {});
+    evb.loop();
+  }
+}
+
 BENCHMARK(FiberManagerAllocateDeallocatePattern, iters) {
   static const size_t kNumAllocations = 10000;