Best way is to explicitly define the relationship with a temporal constraint (although there are other ways). E.g.:
when
$dr: DataReading(reading > 10.0) from entry-point "My Stream"
not(DataReading(reading < 10.0, this after[0s,3s] $dr) from entry-point "My Stream")
not(ReconfigEvent( this before[0,5s] $dr ) from entry-point "My Stream")
then
As we evolve the product I believe we can add defaults and other types of policies to the system that will allow for other ways to define these relationships, but the system, at the moment, will use strict temporal logic and if no temporal join is defined, it will cross product like it would with non-temporal constraints... and that means keeping everything in memory.
Ok, well how to make them marry only those alive(<100 years old)
and ensure all those over 100 years old go out of memory?
Chris
On 7/25/2011 2:32 PM, Edson Tirelli wrote:
Chris
That defines the expiration policy for ReconfigEvent, but
it does not define the relationship between ReconfigEvent and
DataReading. Imagine a timeline, dotted with ReconfigEvents...
what your rule is saying is for each DataReading event, match it
with all the "periods where there is no ReconfigEvent", as the
lifetime of DataReading is infinity.
Maybe a simpler way of understanding it (without using the
"not" for simplification) is think about this:
declare Man
@livesUpTo( 100 years )
end
rule "marriage"
when
$w : Woman( age > 18 )
$m : Man( )
then
// marry woman and man
end
The rule above defines that each woman will merry every
existing man, even if each of them only lives for 100 years.
declare ReconfigEvent
@role( event )
@expires ( 5s )
end
would cover that, meaning that every ReconfigEvent would
expire after 5s, thus causing to no longer be needed by
the engine.
Thanks,
Chris
On 7/25/2011 12:17 PM, Edson Tirelli wrote:
Chris,
I haven't tried your code, but just looking
at the rule, there is no temporal correlation
between DataReading and ReconfigEvent, so if I am
not mistaken, that will create a required interval
of infinite time when the temporal reasoning is
applied, meaning the engine has to keep the
readings in memory forever.
Adding a temporal constraint on the
ReconfigEvent pattern on your rule or defining an
explicit expiration policy for the DataReadings
are ways to work around that.
I am performing a simple test of injecting an
event every 1 millisecond
like so:
for (int x = 0; x < 100000; x++){
DataReading dr = new
DataReading("Reading " + x, 12.0f);
myStream.insert(dr);
ksession.fireAllRules();
Thread.sleep(1);
}
The rule that evaluates this is simple. It
basically delays "then" for
3s to see if a followup reading is inserted
and makes sure that no
ReconfigEvent is active(5s expiration).
So if a reading comes in and a followup
reading is not inserted within 3
seconds and there is is not an existing
ReconfigEvent event alive, then
it should output and insert a ReconfigEvent,
essentially disabling any
DataReading action on those events for the
next 5 seconds or so. This
all works just fine as expected.
My question is, how come I don't get memory
back when all 100,000 of my
events have been inserted. Memory goes up
slowly over the course of
insertions, which I can understand, but once
that loop is finished,
memory never reduces, so essentially, the
application will eventually
run out of memory after some time. I should
not have to explicitly
remove/retract events should I? Shouldn't they
be removed from working
memory as soon as they are no longer viable?
What should I be doing to
reclaim memory from the session/knowledgebase?
I have included the full Main program here and
the Sample.drl file below it.
for (int x = 0; x < 100000; x++){
DataReading dr = new
DataReading("Reading " + x, 12.0f);
myStream.insert(dr);
ksession.fireAllRules();
Thread.sleep(1);
declare ReconfigEvent
@role( event )
@expires ( 5s )
end
rule "Wait for follup reading or no config"
//lock-on-active
when
$dr: DataReading(reading > 10.0) from
entry-point "My Stream"
not(DataReading(reading < 10.0, this
after[0s,3s] $dr) from
entry-point "My Stream")
not(ReconfigEvent() from entry-point "My
Stream")
then
System.err.println("Action: " + new
Date(System.currentTimeMillis()));
System.err.println("Data reading " +
$dr.getName() + " > 10");
ReconfigEvent rce = new ReconfigEvent();
entryPoints["My Stream"].insert( rce );