The private static field EPiServer.Find.LambdaExpressionExtensions._cache keeps growing indefinately even when executing the same query and receiving the same result over and over. This will eventually lead to the worker process running out of memory (in our case, quite frequently).
Below is a code snippet that re-creates the behavior.
// The simplest possible query returning the same result every time will still
// increase the number of entries in the cache.
var cacheField = typeof(LambdaExpressionExtensions)
.GetField("_cache", BindingFlags.NonPublic | BindingFlags.Static);
var cache = cacheField.GetValue(null) as ConcurrentDictionary<Expression, Delegate>;
cache.Clear();
Debug.Assert(cache.Count == 0);
var findClient = ServiceLocator.Current.GetInstance<IClient>();
// Make the simplest possible query to return one hit.
var firstHits = findClient.UnifiedSearch().Take(1).GetResult().Hits.ToList();
Debug.Assert(firstHits.Count == 1);
var firstHitID = firstHits[0].Id;
var firstHitCacheCount = cache.Count;
// The initial query should of course add entries to the cache. About 25 in my case.
Debug.Assert(firstHitCacheCount > 0);
// Make the same query in a loop.
for (var i = 0; i < 10; i++)
{
var loopedHits = findClient.UnifiedSearch().Take(1).GetResult().Hits.ToList();
Debug.Assert(loopedHits.Count == 1);
var loopedHitID = loopedHits[0].Id;
Debug.Assert(loopedHitID == firstHitID);
var loopedHitCacheCount = cache.Count;
// Given the same search query and the same result, the cache should not grow.
// It grows with each iteration.
Debug.Assert(loopedHitCacheCount <= firstHitCacheCount);
}