-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Optimization of concurrent fact indexer (#27)
* Add fact indexer tests * Possibly an optimization of the concurrent fact indexer The concurrent fact indexer maintains a coarse and fine index of facts, where the coarse index is on the predicate symbol and the fine index is on the predicate symbol, argument index and constant at that argument. The fact indexer returns an overapproximation of the set of facts that might match the input query but tries to minimize the returned fact set using a heuristic which picks from the fine index the fact set maintained at the argument position for which the most distinct constants have been seen so far. Under the assumption that the fact sets are roughly of equal size for each constant this is a sound strategy, but it is easy to imagine worst cases where fact sets that are much too large are returned. E.g. consider f(a, x, b) f(b, x, b) f(c, x1, b) f(c, x2, b) ... f(c, x10000, b) f(c, x, d) and the query f(c, _, d)? Two fine indexes will be considered as candidates; the first and the third. The first index has three distinct constants and the third has only two. The candidate fact set returned is thus the 10,001 element set { f(c, x1, b), ..., f(c, x10000, b), f(c, x, d) } rather than the singleton set { f(c, x, d) } The fact indexer cannot evaluate the size of the underlying container since it has to work for all Iterable containers, including ConcurrentLinkedBag which cannot implement the Container interface for efficiency reasons. It is however quite easy to add a size method to this collection type and pass it as a lambda to the fact indexer. The fact indexer can then just pick the smallest set from the fine index instead of relying on a heuristic. * Use :: syntax for methods. --------- Co-authored-by: Ulrik Rasmussen <[email protected]> Co-authored-by: Aaron Bembenek <[email protected]>
- Loading branch information
1 parent
4e25a86
commit 10229d9
Showing
5 changed files
with
80 additions
and
16 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
47 changes: 47 additions & 0 deletions
47
src/test/java/edu/harvard/seas/pl/abcdatalog/util/datastructures/FactIndexerTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
package edu.harvard.seas.pl.abcdatalog.util.datastructures; | ||
|
||
import edu.harvard.seas.pl.abcdatalog.ast.*; | ||
import edu.harvard.seas.pl.abcdatalog.engine.AbstractTests; | ||
import org.junit.Assert; | ||
import org.junit.Test; | ||
import org.junit.runner.RunWith; | ||
import org.junit.runners.Suite; | ||
|
||
import java.util.function.Supplier; | ||
|
||
@RunWith(Suite.class) | ||
@Suite.SuiteClasses({ | ||
FactIndexerTest.SetTests.class, | ||
FactIndexerTest.ConcurrentLinkedBagTests.class | ||
}) | ||
public class FactIndexerTest { | ||
public static class SetTests extends AbstractFactIndexerTests { | ||
public SetTests() { super(FactIndexerFactory::createConcurrentSetFactIndexer); } | ||
} | ||
|
||
public static class ConcurrentLinkedBagTests extends AbstractFactIndexerTests { | ||
public ConcurrentLinkedBagTests() { super(FactIndexerFactory::createConcurrentQueueFactIndexer); } | ||
} | ||
|
||
public static abstract class AbstractFactIndexerTests extends AbstractTests { | ||
private final Supplier<FactIndexer> factIndexerFactory; | ||
|
||
public AbstractFactIndexerTests(Supplier<FactIndexer> factIndexerFactory) { | ||
super(() -> { throw new Error("Tests do not use engine="); }); | ||
this.factIndexerFactory = factIndexerFactory; | ||
} | ||
|
||
@Test | ||
public void testSmallestFactSetIsReturnedFromFineIndex() { | ||
FactIndexer indexer = factIndexerFactory.get(); | ||
indexer.addAll(parseFacts("f(a,x,b). f(b,x,b). f(c,x1,b). f(c,x2,b). f(c,x,d).")); | ||
|
||
Iterable<PositiveAtom> result = indexer.indexInto(parseQuery("f(c,_,d)?")); | ||
int size = 0; | ||
for (PositiveAtom ignored : result) { | ||
++size; | ||
} | ||
Assert.assertEquals(1, size); | ||
} | ||
} | ||
} |