|
Test details:
The index has 500,000 docs and 3191625 unique terms. To construct the queries I used terms with 1000<df<3000, the index has 3880 of them. I combined the terms randomly. Each query has at least one hit. The AND queries have 25 hits on average, the OR queries 5641. The LRU cache was pretty small with a size of just 20. The index is unoptimized with 11 segments. The searcher was warmed for the tests, thus benefiting from FS caching, which Thinking about a common use in Solr: doing a query and faceting that query by a field... would blow out the cache (due to iterating over all the terms in a single field) if it's a global cache? Is there a good way to prevent that from happening (perhaps just change lucene's existing single -entry thread local cache to a multi-entry thread local cache?)
No, but consider the case of one thread iterating over all the terms in a field (due to faceting, a range query, prefix query, etc) That would tend to destroy the cache for other threads doing simple queries unless a way could be found to bypass the cache during enumeration somehow, or make each cache thread specific. Here is the simple patch. The cache is only used in TermInfosReader.get(Term).
So if for example a RangeQuery gets a TermEnum from the IndexReader, then The LRUCache itself is not synchronized. It might happen that multiple I set the default cache size to 1024. A cache entry is a (Term, TermInfo) All core & contrib tests pass.
Michael Busch made changes - 27/Feb/08 07:31 PM
Unfortunately, it needs to be... no getting around it.
But for each term, TermDocs.seek() will be called, and that will do a TermInfosReader.get(Term), replacing items in the cache.
You're right, and I'm stupid There's higher level synchronization too (ensuring that two different threads don't generate the same cache entry at the same time), and I agree that should not be done in this case.
Just use Collections.synchronizedMap(), it will be the same speed, more readable, and can be easily replaced later anyway. Changes in the patch:
I reran the same performance experiments and it turns out that the speedup is still the same and I also ran similar performance tests on a bigger index with about 4.3 million documents. The All unit tests pass.
Michael Busch made changes - 21/May/08 08:37 AM
In the previous patch was a silly thread-safety problem that I fixed now.
Some threads in the TestIndexReaderReopen test occasionally hit errors (I fixed the testcase to fail now whenever an error is hit). I made some other changes to the TermInfosReader. I'm not using Furthermore I got rid of the private scanEnum() method and inlined I reran the same performance test that I ran for the first patch and All tests pass, including the improved OK I think this patch is ready now, I'm planning to commit it in a
Michael Busch made changes - 23/May/08 02:18 AM
Michael Busch made changes - 23/May/08 07:43 AM
Michael Busch made changes - 23/May/08 05:22 PM
Hmmm, clever, and pretty much free. It doesn't seem like it would eliminate something like a RangeQuery adding to the cache, but does reduce the amount of pollution. Seems like about 1/64th of the terms would be added to the cache? (every 128th term and the term following that... due to "numScans > 1" check). Still, it would take a range query covering 64K terms to completely wipe the cache, and as long as that range query is slow relative to the term lookups, I suppose it doesn't matter much if the cache gets wiped anyway. A single additional hash lookup per term probably shouldn't slow the execution of something like a range query that much either. A "safe" ThreadLocal that can be used for more deterministic memory usage.
Probably a bit slower than the JDK ThreadLocal, due to the synchronization. Offers a "purge()" method to force the cleanup of stale entries. Probably most useful in code like this: SomeLargeObject slo; // maybe a RAMDirectory?
robert engels made changes - 11/Sep/08 03:12 AM
Also, SafeThreadLocal can be trivially changed to reduce the synchronization times, by using a synchronized map - then only the access is sync'd.
Since a ThreadLocal in Lucene is primarily read (after initial creation), a 1.5 lock designed for read often, write rarely would be best.
Michael McCandless made changes - 11/Oct/08 12:49 PM
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
I assume this is on a non-optimized index?
One of the unexpected things I've seen in Solr is that enumerating over all the terms of a non-optimized index is a very significant component of the total time (including iterating over termdocs when necessary). This was with terms with a relatively low df though.