Permalink
Browse files

Add run-time information for fiber pool

There was a bug report a while back about fibers being slow but was
ultimately caused by the user accidentally keeping way too many fibers
around. It would have been easier to identify the problem with the
ability to inspect and alter node-fiber's underlying coroutine cache.
This adds two static properties to Fiber, `fibersCreated` and `poolSize`
which should give more information about what's happening under the
hood. Documentation for these to come.
  • Loading branch information...
laverdet committed Feb 8, 2012
1 parent a7be6ca commit 42f7111ecb86587715bd8350cc6cc405fcdfb33a
Showing with 36 additions and 4 deletions.
  1. +8 −3 src/coroutine.cc
  2. +7 −0 src/coroutine.h
  3. +20 −0 src/fibers.cc
  4. +1 −1 test/pool.js
View
@@ -6,17 +6,17 @@
#include <stack>
#include <vector>
-#define MAX_POOL_SIZE 120
-
#include <iostream>
using namespace std;
static pthread_key_t floor_thread_key = NULL;
static pthread_key_t ceil_thread_key = NULL;
static size_t stack_size = 0;
+static size_t coroutines_created_ = 0;
static vector<Coroutine*> fiber_pool;
static Coroutine* delete_me = NULL;
+size_t Coroutine::pool_size = 120;
/**
* Coroutine class definition
@@ -49,6 +49,10 @@ void Coroutine::set_stack_size(size_t size) {
stack_size = size;
}
+size_t Coroutine::coroutines_created() {
+ return coroutines_created_;
+}
+
void Coroutine::trampoline(void* that) {
#ifdef CORO_PTHREAD
pthread_setspecific(ceil_thread_key, that);
@@ -80,6 +84,7 @@ Coroutine& Coroutine::create_fiber(entry_t* entry, void* arg) {
fiber.reset(entry, arg);
return fiber;
}
+ ++coroutines_created_;
return *new Coroutine(*entry, arg);
}
@@ -142,7 +147,7 @@ void Coroutine::finish(Coroutine& next) {
{
assert(&next != this);
assert(&current() == this);
- if (fiber_pool.size() < MAX_POOL_SIZE) {
+ if (fiber_pool.size() < pool_size) {
fiber_pool.push_back(this);
} else {
// TODO?: This assumes that we didn't capture any keys with dtors. This may not always be
View
@@ -41,6 +41,8 @@ class Coroutine {
void transfer(Coroutine& next);
public:
+ static size_t pool_size;
+
/**
* Returns the currently-running fiber.
*/
@@ -62,6 +64,11 @@ class Coroutine {
*/
static void set_stack_size(size_t size);
+ /**
+ * Get the number of coroutines that have been created.
+ */
+ static size_t coroutines_created();
+
/**
* Start or resume execution in this fiber. Note there is no explicit yield() function,
* you must manually run another fiber.
View
@@ -448,6 +448,24 @@ class Fiber {
}
}
+ /**
+ * Allow access to coroutine pool size
+ */
+ static Handle<Value> GetPoolSize(Local<String> property, const AccessorInfo& info) {
+ return Number::New(Coroutine::pool_size);
+ }
+
+ static void SetPoolSize(Local<String> property, Local<Value> value, const AccessorInfo& info) {
+ Coroutine::pool_size = value->ToNumber()->Value();
+ }
+
+ /**
+ * Return number of fibers that have been created
+ */
+ static Handle<Value> GetFibersCreated(Local<String> property, const AccessorInfo& info) {
+ return Number::New(Coroutine::coroutines_created());
+ }
+
public:
/**
* Initialize the Fiber library.
@@ -489,6 +507,8 @@ class Fiber {
Handle<Function> fn = tmpl->GetFunction();
fn->Set(sym_yield, yield);
fn->SetAccessor(String::NewSymbol("current"), GetCurrent);
+ fn->SetAccessor(String::NewSymbol("poolSize"), GetPoolSize, SetPoolSize);
+ fn->SetAccessor(String::NewSymbol("fibersCreated"), GetFibersCreated);
// Global Fiber
target->Set(String::NewSymbol("Fiber"), fn, ReadOnly);
View
@@ -1,7 +1,7 @@
require('fibers');
-var fibers = [];
for (var jj = 0; jj < 10; ++jj) {
+ var fibers = [];
for (var ii = 0; ii < 200; ++ii) {
var fn = Fiber(function() {
yield();

0 comments on commit 42f7111

Please sign in to comment.