Limit the number of recycled fibers.

This allows the process to free up memory after heavy load spikes, while not impacting performance negatively.
This commit is contained in:
Sönke Ludwig 2017-05-30 11:00:37 +02:00
parent 0aed5664ef
commit 99a5b882d8
No known key found for this signature in database
GPG key ID: D95E8DB493EE314C
2 changed files with 28 additions and 2 deletions

View file

@ -1,7 +1,7 @@
/** /**
This module contains the core functionality of the vibe.d framework. This module contains the core functionality of the vibe.d framework.
Copyright: © 2012-2016 RejectedSoftware e.K. Copyright: © 2012-2017 RejectedSoftware e.K.
License: Subject to the terms of the MIT license, as written in the included LICENSE.txt file. License: Subject to the terms of the MIT license, as written in the included LICENSE.txt file.
Authors: Sönke Ludwig Authors: Sönke Ludwig
*/ */
@ -763,7 +763,7 @@ unittest {
} }
/// Compatibility overload - use a `@safe nothrow` callback instead. /// Compatibility overload - use a `@safe nothrow` callback instead.
deprecated("Use anothrow callback as argument to setTimer.") deprecated("Use an @safe nothrow callback as argument to setTimer.")
Timer setTimer(Duration timeout, void delegate() callback, bool periodic = false) Timer setTimer(Duration timeout, void delegate() callback, bool periodic = false)
@safe nothrow { @safe nothrow {
return setTimer(timeout, () @trusted nothrow { return setTimer(timeout, () @trusted nothrow {
@ -1108,6 +1108,7 @@ private {
TaskScheduler s_scheduler; TaskScheduler s_scheduler;
FixedRingBuffer!TaskFiber s_availableFibers; FixedRingBuffer!TaskFiber s_availableFibers;
size_t s_maxRecycledFibers = 100;
string s_privilegeLoweringUserName; string s_privilegeLoweringUserName;
string s_privilegeLoweringGroupName; string s_privilegeLoweringGroupName;
@ -1124,6 +1125,16 @@ package @property ref TaskScheduler taskScheduler() @safe nothrow @nogc { return
package void recycleFiber(TaskFiber fiber) package void recycleFiber(TaskFiber fiber)
@safe nothrow { @safe nothrow {
if (s_availableFibers.length >= s_maxRecycledFibers) {
auto fl = s_availableFibers.front;
s_availableFibers.popFront();
fl.shutdown();
() @trusted {
try destroy(fl);
catch (Exception e) logWarn("Failed to destroy fiber: %s", e.msg);
} ();
}
if (s_availableFibers.full) if (s_availableFibers.full)
s_availableFibers.capacity = 2 * s_availableFibers.capacity; s_availableFibers.capacity = 2 * s_availableFibers.capacity;

View file

@ -293,6 +293,7 @@ final package class TaskFiber : Fiber {
ThreadInfo m_tidInfo; ThreadInfo m_tidInfo;
shared size_t m_taskCounter; shared size_t m_taskCounter;
shared bool m_running; shared bool m_running;
bool m_shutdown = false;
shared(ManualEvent) m_onExit; shared(ManualEvent) m_onExit;
@ -352,6 +353,7 @@ final package class TaskFiber : Fiber {
logWarn("CoreTaskFiber was resumed with exception but without active task!"); logWarn("CoreTaskFiber was resumed with exception but without active task!");
logDiagnostic("Full error: %s", e.toString().sanitize()); logDiagnostic("Full error: %s", e.toString().sanitize());
} }
if (m_shutdown) return;
} }
TaskFuncInfo task; TaskFuncInfo task;
@ -431,6 +433,19 @@ final package class TaskFiber : Fiber {
@property size_t taskCounter() const @safe nothrow { return m_taskCounter; } @property size_t taskCounter() const @safe nothrow { return m_taskCounter; }
/** Shuts down the task handler loop.
*/
void shutdown()
@safe nothrow {
assert(!m_running);
m_shutdown = true;
while (state != Fiber.State.TERM)
() @trusted {
try call(Fiber.Rethrow.no);
catch (Exception e) assert(false, e.msg);
} ();
}
/** Blocks until the task has ended. /** Blocks until the task has ended.
*/ */
void join(bool interruptiple)(size_t task_counter) void join(bool interruptiple)(size_t task_counter)