[Mondrian] Some optimizations based on profiler results
Ajit Vasudeo Joglekar
ajogleka at thoughtworks.com
Thu Oct 18 08:36:13 EDT 2007
We did some profiling on mondrian code base. We have a large catalog with
hundreds of dimensions and measures. Based on the hotspots identified by
the profiler here are some optimizations that make considerable difference
in performance in the evaluation of a single mdx.
We would like to introduce these changes. Inviting comments, suggestions
Thanks,
-Ajit, Ashwin
===================
1) In RolapCubeSchemaReader we have a getCalculatedMembers method that
creates a new list of calculated members based on the role configured in
the Mondrian schema.
In the scenario where we have a huge number of calculated members and no
Role configured this operation becomes quite expensive on multiple
invocations.
We can fix this by returning the original list of calculated members if
the access is the default access
public List<Member> getCalculatedMembers() {
List<Member> list = new ArrayList<Member>();
for (Formula formula : calculatedMembers) {
Member member = formula.getMdxMember();
if (getRole().canAccess(member)) {
list.add(member);
}
}
return list;
}
becomes
public List<Member> getCalculatedMembers() {
if(Access.ALL == getRole().getAccess()){
return calculatedMembers; // indicative - need to
convert [] to list. one option is We can maintain ArrayList and return []
where ever necessary
}
List<Member> list = new ArrayList<Member>();
for (Formula formula : calculatedMembers) {
Member member = formula.getMdxMember();
if (getRole().canAccess(member)) {
list.add(member);
}
}
return list;
}
2) In the RolapMember equals method :
private boolean equals(RolapMember that) {
assert that != null;
return this.getUniqueName().equals(that.getUniqueName());
}
Now if the assert fails it will throw an exception which means equals
will fail with a non boolean value which should not happen and assert is
an expensive operation
when compared to a null check.
it can be changed to:
private boolean equals(RolapMember that) {
if(that == null){
return false;
}
return this.getUniqueName().equals(that.getUniqueName());
}
3) In RolapEvaluator :
public final Member setContext(Member member) {
final RolapMember m = (RolapMember) member;
final int ordinal = m.getDimension().getOrdinal(root.cube);
final Member previous = currentMembers[ordinal];
if (previous.isCalculated()) {
removeCalcMember(previous);
}
currentMembers[ordinal] = m;
if (m.isCalculated()) {
addCalcMember(m);
}
return previous;
}
now we can optimize this by adding an equals to verify that m and
previous are not the same.
public final Member setContext(Member member) {
final RolapMember m = (RolapMember) member;
final int ordinal = m.getDimension().getOrdinal(root.cube);
final Member previous = currentMembers[ordinal];
if (m.equals(previous))
return previous;
if (previous.isCalculated()) {
removeCalcMember(previous);
}
currentMembers[ordinal] = m;
if (m.isCalculated()) {
addCalcMember(m);
}
return previous;
}
this reduces some operations in case of massive number of invocations
to this method.
===================
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.pentaho.org/pipermail/mondrian/attachments/20071018/72a4233f/attachment.html
More information about the Mondrian
mailing list