[rules-users] Analysing OutOfMemory, too many RightTuple

Wolfgang Laun wolfgang.laun at gmail.com
Thu Jun 12 03:50:30 EDT 2014


Before I say something, I should know:


* If an EvemetierCalculDHF "accompanies" an EvemetierData object: is
this a 1:1 relationship or are there several EvemetierData objects
tied to a single EvemetierCalculDHF?

* Is EvemetierCalculDHF.evemetier a Collection? (Probably "yes" if the
answer to the first question is "several".

* Why is the (custom) evaluator sumWithNulls used here? One would
think that DIVIDE can be written so as never to return null.

* The extra CE "Object(...) from WRAP_NULL($acc1)" looks contrived. A
constraint on $acc1/sumWithNulls can be written within the accumulate.

* Personally, I abhor grappling with null (UN/WRAP_NULL). One should
think that it is possible to design objects in a way that avoids null
being returned by its getters. (Frequently, it is just a matter of a
little extra effort to think up a reasonable default value and write
the object initialisation accordingly.)

I can say one thing right away:

  $obj: EvemetierData() from $evCalcDHF.evemetier
  accumulate (  $src: EvemetierData (
     pere == $obj.niveau,... )

The first CE picks out *some* EvemetierData object (from a Collection
(?) see Q1). The accumulate collects lots of partially equal
EvemetierData objects. Now, if there is more than one EvemetierData in
that collection, a similar thing will happen, very likely, over and
over again, with the same subset of EvemetierData facts.

If a "representative" is required for matching a set of similar facts
in an accumulate, it is best practice to pick the representative using
a restrictive constraint, e.g., if it has a unique integer id
attribute, pick the one with the smallest id.

-W




On 11/06/2014, bvoisin <benoit.voisin at igc-erp.com> wrote:
> To help me understand what is happening in the WM, I've just made a analysis
> method (see below), scrutating all the RightTuples from the WM facts and
> showing some stats on the 5 biggest ones :
>
> I call it every 100 matchFired and it shows me info like:
>
> Biggest RightTuple types :
>  - EvemetierData: RightTuple/NotNode[niveau == $niveau, suffixe == $suffixe]
> x *209346*
>  - SuffixeMapDHF: RightTuple/JoinNode[id == $ev.suffixe] x 17610
>  - EvemetierData: RightTuple/AccumulateNode[this == $obj.father] x 14145
>  - EvemetierData: RightTuple/AccumulateNode[niveau == $obj.niveau,
> affperiode == $obj.affperiode, typeeve_id == $obj.typeeve_id, dteve ==
> $obj.dteve, $suffixeMap.toPhaseTOT != null && ( $suffixeMap.toPhaseTOT !=
> null && suffixe == $suffixeMap.toPhaseTOT.id )] x 14145
>  - EvemetierData: RightTuple/NotNode[niveau == $niveau, suffixe == $suffixe,
> sources contains $source3] x 11316
>
> I clearly found my suspect N°1. Is there any pre-existing and better written
> methods to do this kind of research in drools ?
>
> Regards,
> Benoît
>
> Method to be called after each/N match fired or ... It uses Guava for the
> collections :
>
>       private void analyzeWorkingMemoryTuples()
>         {
>             Multiset<String> keys = HashMultiset.create();
>
>             for(FactHandle handle:kieSession.getFactHandles())
>             {
>                 DefaultFactHandle factHandle = (DefaultFactHandle)handle;
>                 String
> factType=factHandle.getObject().getClass().getSimpleName();
>
>                 RightTuple rightTuple = factHandle.getFirstRightTuple();
>                 while(rightTuple!=null)
>                 {
>                     String key = factType + ": RightTuple";
>                     BetaNode sink =
> (BetaNode)rightTuple.getRightTupleSink();
>                     if (sink!=null) {
>                         key+= "/" + sink.getClass().getSimpleName();
>                         key+=Arrays.toString(sink.getConstraints());
>                     }
>                     keys.add(key);
>                     rightTuple = rightTuple.getHandleNext();
>                 }
>             }
>
>             ArrayList<Multiset.Entry&lt;String>> entries =
> Lists.newArrayList(keys.entrySet());
>             Collections.sort(entries, new
> Comparator<Multiset.Entry&lt;String>>(){
>                 @Override
>                 public int compare(Entry<String> o1, Entry<String> o2)
>                 {
>                     return -Integer.compare(o1.getCount(), o2.getCount());
>                 }
>             });
>             String analysis = Joiner.on("\n -
> ").join(Iterables.limit(entries, 5));
>             if (!analysis.equals(previousAnalysis))
>             {
>                 logger.info("Biggest RightTuple types :\n - " + analysis);
>
>                 previousAnalysis = analysis;
>             }
>         }
>
>
>
>
> --
> View this message in context:
> http://drools.46999.n3.nabble.com/Analysing-OutOfMemory-too-many-RightTuple-tp4029988p4029993.html
> Sent from the Drools: User forum mailing list archive at Nabble.com.
>
> _______________________________________________
> rules-users mailing list
> rules-users at lists.jboss.org
> https://lists.jboss.org/mailman/listinfo/rules-users



More information about the rules-users mailing list