Uploaded image for project: 'Pentaho Analysis - Mondrian'
  1. Pentaho Analysis - Mondrian
  2. MONDRIAN-639

RolapNamedSetEvaluator anon classes implement Iterable, causing performance regression from 2.4 in FunUtil.count()


    • Type: Bug
    • Status: Closed
    • Severity: Unknown
    • Resolution: Fixed
    • Affects Version/s: 3.1 GA, 3.1.1 GA, 3.1.2 GA
    • Component/s: None
    • Labels:
    • Notice:
      When an issue is open, the "Fix Version/s" field conveys a target, not necessarily a commitment. When an issue is closed, the "Fix Version/s" field conveys the version that the issue was fixed in.


      The "includeEmpty == true" path within FunUtil.count() tests to see if the provided iterable implements Collection. If so, it simply calls the size() method to return the count; otherwise, it iterates through each element of the iterable to get the count.

      In older versions of Mondrian (2.4, for example) the iterable passed in usually implemented List, so actually iterating was rare. However, when RolapNamedSetEvaluator was introduced, the iterable became one of two anonymous classes, both of which implement Iterable rather than Collection. This can result in a lot of unnecessary iterations.

      Since both inner classes use a List internally, there's no reason they can't implement the Collection interface as well. I have a change that does exactly this.

      Sample code that illustrates the issue is below. On my mac mini, it takes 233 seconds to execute as-is, and only 4.5 to execute with the proposed fix:

      public void testIteratingCount() {
      // On my mac mini:
      // takes 233 seconds before bug fixed
      // takes 4.5 seconds after bug fixed
      long start = System.currentTimeMillis();
      Result result = executeQuery(
      "WITH SET [cjoin] AS " +
      "crossjoin(customers.members, [store type].[store type].members) " +
      "MEMBER [Measures].[total_available_count] AS Format(COUNT([cjoin]), \"#####\") " +
      "SELECT" +


      ON COLUMNS, " +


      ON ROWS " +
      "FROM sales");
      System.out.println("elapsed time: " + (System.currentTimeMillis() - start));
      assertEquals(62442, result.getAxes()[0].getPositions().size());
      assertEquals(1, result.getAxes()[1].getPositions().size());




            • Assignee:
              project admin Triage
              emcdermid Eric McDermid
            • Votes:
              0 Vote for this issue
              0 Start watching this issue


              • Created: