facebook/hhvm — pull request #4265 by tstarling (2014-11-18 06:10:56+00:00)
Title: PCRE synchronized cache

Commit 1: Fix runtime modification of shared pcre_extra

set_extra_limits() is apparently trying to account for
ini_set('pcre.recursion_limit', ...) etc., but it makes a horrible mess
of it, since it modifies the limits in the global PCRE cache entry, thus
making such an ini_set() immediately affect all threads which are using
the same cache entry.

Instead, use a pcre_extra allocated on the stack, as suggested by the
FIXME comment. If there is a shared pcre_extra, copy the relevant
pointers (study_data, executable_jit) into the local struct using
memcpy().

Use tl_ prefix for thread-local variables.

Commit 2: Thread-safe LRU PCRE cache

When the PCRE cache fills up, memory is leaked since the static string
created by insert_cached_pcre() cannot be freed. Also, queueing cached
regexes for deletion on request termination is not good policy -- it
is effectively a memory leak for long-running scripts.

Also, when the PCRE cache is full, new regexes need to be recompiled on
every call to preg_match() etc. so the performance of an app using
dynamically-generated regex strings will degrade once the limit is
reached.

* Developed a new thread-safe LRU container class, published to
https://github.com/tstarling/thread-safe-lru and copied here. Apache
license chosen to allow future inclusion into Folly if necessary.
* Made container class choice a runtime option, with two new classes
plus the old AtomicHashArray solution.
* Reorganised PCRE cache code, made it OOP.
* In the AtomicHashArray case, use reference counting to destroy
temporary objects, instead of deferring destruction until the end of
the request. Remove m_overflow-related housekeeping.