| ILOG JRules User Guide > Optimizing Execution > Tasks > Improving RetePlus Execution Mode Performance > Instrumenting Join Tests with Finders |
Instrumenting Join Tests with Finders |
PREVIOUS NEXT |
Finders allow you to speed up the execution of rules by providing the engine with application-specific code that enables it to perform more efficient pattern matching on specific classes.
The finder mechanism is derived from the relation feature. This feature allows navigation through the object model using the keywords from and in. Relations are typically used for two reasons:
When relations are used simply for an optimization purpose, they force you to write rules in a way that is not natural and breaks the abstraction of rule-based programming.
For example, suppose that the model of our application defines a Customer class with two fields, zipcode and age:
class Customer {
public int zipcode;
public int age;
};
The simplest way of writing a condition that matches a Customer with a given zipcode and age would be:
?c: Customer(zipcode == 80; age == 20);
But this can be very inefficient if there are many customers. The inefficiency arises because all the customers need to be added and the conditions must be tested for all of them.
To address this problem, you could write Java code that retrieves a list of customers from their zip code using a hash table. We could then add a static lookup method in the Customer class like this:
class Customer {
...
public static Customer[] findByZipCode (int zipcode)
{ <Java retrieval code> }
};
Then you could rewrite the previous condition so it uses this method:
?c: Customer(age == 20) in Customer.findByZipCode(80);
This makes the rule much more efficient because it restricts the number of objects on which the pattern matching occurs. Moreover, the customers do not need to be added at all.
Unfortunately, this optimization is intrusive because it requires rewriting each rule that matched a customer from his or her zip code. If the optimization support provided by the application evolves, for example with the addition of new lookup methods, the rules have to be changed.
Using finders enables you to achieve the same goal but in a nonintrusive way. To benefit from the finder mechanism, the programmer simply declares finder methods such as findByZipCode in a dedicated file processed by the engine.
Due to these declarations, the engine detects these methods and automatically uses them in rules as if the rule were used an explicit in statement.
Suppose a class ClassX of the object model contains a method with the following signature:
static ClassX[] findBySomething(type1 name1,..., typeN nameN)
where the names and types of the arguments match some fields of Class, and this method is declared as a finder. The engine then internally rewrites any condition of the form:
ClassX(name1 eq value1, .., nameN eq valueN; other tests);
as:
ClassX(other conditions) in findBySomething(value1, ..., valueN)
For example, if the definition of the class Customer contains a finder with the following signature:
class Customer {
...
public static Customer[] findByZipCode(int zipcode)
{ <Java retrieval code> }
};
then the condition:
?c: Customer(zipcode == 80; age == 20);
is internally rewritten by the engine as:
?c: Customer(age == 20) in Customer.findByZipCode(80);
A finder method can also return a single object, in which case the engine internally rewrites the rule using the from construct. A finder may be declared as inaccurate, in which case the engine considers that the finder returns a superset of the matching objects and that the equality conditions still require a verification of the objects. The valid keywords for a finder result are the following:
single--means that the finder result is a unique object. In the case of the zip code example, the from keyword is used instead of the in keyword. In other words, if you search for a town by its zip code, the result is always a single town, so it is always unique. However, if you search for employees by their department, you will obtain a list of objects, and the finder result will not be single.
final--indicates that the result does not change. The zip code example can be final, since a zip code always returns the same town object. For the example of employees and their departments, the finder result can not be final because the set of employees could change.
A finder can optimize a rule condition when the attributes linked to the finder arguments appear in equality tests of the condition and can be invoked from the condition. Other requirements depend on the type of the finder. There are three types:
IlrContext method
Although the finder invocation is always possible in a static or an IlrContext method, an instance method requires a simple condition to exist (not, exists, and collect conditions excluded) from which the finder class is assignable.
When several finders can be used to optimize a rule condition, the engine determines the best one. The criteria involved in the finder evaluation are listed by priority:
| Note |
| In the case of equivalent finders, the engine choice should be considered as nondeterministic. |
The returned type of an N-ary finder may be either a Vector, an Enumeration, or an array of elements whose type is the same as the condition type. The engine assumes that in the case of Vector or Enumeration, the type returned is compatible with the condition type.
| Copyright © 1987-2008 ILOG S.A. All rights reserved. Legal terms. Documentation homepage. | PREVIOUS NEXT |