Skip to content

Commit

Permalink
Allow grouping selection in UI
Browse files Browse the repository at this point in the history
This means that for the Flat and Tree views, you can now choose the way
nodes are aggregated : by thread id, name or over threads, and by Frame
method name, methodname + line nr or file + bci (to be reviewed, maybe
it has to be method + bci)

Currently the Ancestor/Descendants tree aggreagations at the bottom of
the Flat View are broken, but they were not quite correct anyway. Should
get fixed next week.
  • Loading branch information
PhRX committed Feb 2, 2017
1 parent 78f0617 commit e395024
Show file tree
Hide file tree
Showing 19 changed files with 367 additions and 64 deletions.
@@ -1,20 +1,12 @@
package com.insightfullogic.honest_profiler.core.aggregation; package com.insightfullogic.honest_profiler.core.aggregation;


import static com.insightfullogic.honest_profiler.core.aggregation.grouping.FrameGrouping.BY_FQMN;
import static com.insightfullogic.honest_profiler.core.aggregation.grouping.ThreadGrouping.ALL_THREADS_TOGETHER;
import static com.insightfullogic.honest_profiler.core.aggregation.grouping.ThreadGrouping.THREADS_BY_NAME;

import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;


import com.insightfullogic.honest_profiler.core.aggregation.aggregator.FlatProfileAggregator; import com.insightfullogic.honest_profiler.core.aggregation.aggregator.FlatProfileAggregator;
import com.insightfullogic.honest_profiler.core.aggregation.aggregator.ProfileAggregator;
import com.insightfullogic.honest_profiler.core.aggregation.aggregator.TreeProfileAggregator; import com.insightfullogic.honest_profiler.core.aggregation.aggregator.TreeProfileAggregator;
import com.insightfullogic.honest_profiler.core.aggregation.grouping.CombinedGrouping; import com.insightfullogic.honest_profiler.core.aggregation.grouping.CombinedGrouping;
import com.insightfullogic.honest_profiler.core.aggregation.result.Aggregation;
import com.insightfullogic.honest_profiler.core.aggregation.result.straight.Entry;
import com.insightfullogic.honest_profiler.core.aggregation.result.straight.Flat; import com.insightfullogic.honest_profiler.core.aggregation.result.straight.Flat;
import com.insightfullogic.honest_profiler.core.aggregation.result.straight.Node;
import com.insightfullogic.honest_profiler.core.aggregation.result.straight.Tree; import com.insightfullogic.honest_profiler.core.aggregation.result.straight.Tree;
import com.insightfullogic.honest_profiler.core.profiles.lean.LeanNode; import com.insightfullogic.honest_profiler.core.profiles.lean.LeanNode;
import com.insightfullogic.honest_profiler.core.profiles.lean.LeanProfile; import com.insightfullogic.honest_profiler.core.profiles.lean.LeanProfile;
Expand All @@ -25,22 +17,24 @@
*/ */
public class AggregationProfile public class AggregationProfile
{ {
private static final ProfileAggregator<Entry> flatAggregator = new FlatProfileAggregator(); private static final FlatProfileAggregator flatAggregator = new FlatProfileAggregator();
private static final ProfileAggregator<Node> treeAggregator = new TreeProfileAggregator(); private static final TreeProfileAggregator treeAggregator = new TreeProfileAggregator();


private final LeanProfile source; private final LeanProfile source;
private final Map<String, FqmnLink> fqmnLinks; private final Map<String, FqmnLink> fqmnLinks;


private final NumericInfo global; private final NumericInfo global;


private Map<ProfileAggregator<?>, Aggregation<?>> cachedAggregations; private Map<CombinedGrouping, Flat> cachedFlats;
private Map<CombinedGrouping, Tree> cachedTrees;


public AggregationProfile(LeanProfile source) public AggregationProfile(LeanProfile source)
{ {
this.source = source; this.source = source;
fqmnLinks = new HashMap<>(); fqmnLinks = new HashMap<>();
global = new NumericInfo(); global = new NumericInfo();
cachedAggregations = new HashMap<>(); cachedFlats = new HashMap<>();
cachedTrees = new HashMap<>();


// ThreadInfo objects are stored separately in the LeanLogCollector (to avoid the assumption that a ThreadMeta // ThreadInfo objects are stored separately in the LeanLogCollector (to avoid the assumption that a ThreadMeta
// will always be emitted before the first sample for the thread comes in), so we put them into the root // will always be emitted before the first sample for the thread comes in), so we put them into the root
Expand Down Expand Up @@ -72,20 +66,14 @@ public Map<String, FqmnLink> getFqmnLinks()
return fqmnLinks; return fqmnLinks;
} }


public Flat getFlat() public Flat getFlat(CombinedGrouping grouping)
{ {
cachedAggregations.putIfAbsent( return cachedFlats.computeIfAbsent(grouping, g -> flatAggregator.aggregate(this, g));
flatAggregator,
flatAggregator.aggregate(this, new CombinedGrouping(ALL_THREADS_TOGETHER, BY_FQMN)));
return (Flat)cachedAggregations.get(flatAggregator);
} }


public Tree getTree() public Tree getTree(CombinedGrouping grouping)
{ {
cachedAggregations.putIfAbsent( return cachedTrees.computeIfAbsent(grouping, g -> treeAggregator.aggregate(this, g));
treeAggregator,
treeAggregator.aggregate(this, new CombinedGrouping(THREADS_BY_NAME, BY_FQMN)));
return (Tree)cachedAggregations.get(treeAggregator);
} }


private void aggregateGlobal() private void aggregateGlobal()
Expand Down
Expand Up @@ -41,6 +41,11 @@ public Tree aggregate(AggregationProfile source, Entry input)
return result; return result;
} }


// private void addAncestors(AggregationProfile source, Node child, Tree tree)
// {
// child.getAggregatedNodes().stream().map(node -> node.getParent()).collect(collector);
// }

private void addAncestors(AggregationProfile source, Node parent, Tree tree, private void addAncestors(AggregationProfile source, Node parent, Tree tree,
Set<String> processed) Set<String> processed)
{ {
Expand Down
@@ -1,5 +1,6 @@
package com.insightfullogic.honest_profiler.core.aggregation.grouping; package com.insightfullogic.honest_profiler.core.aggregation.grouping;


import java.util.Objects;
import java.util.function.BiFunction; import java.util.function.BiFunction;


import com.insightfullogic.honest_profiler.core.aggregation.AggregationProfile; import com.insightfullogic.honest_profiler.core.aggregation.AggregationProfile;
Expand All @@ -8,10 +9,16 @@


public class CombinedGrouping implements BiFunction<AggregationProfile, LeanNode, String> public class CombinedGrouping implements BiFunction<AggregationProfile, LeanNode, String>
{ {
public static final CombinedGrouping combine(ThreadGrouping threadGrouping,
FrameGrouping frameGrouping)
{
return new CombinedGrouping(threadGrouping, frameGrouping);
}

private ThreadGrouping threadGrouping; private ThreadGrouping threadGrouping;
private FrameGrouping frameGrouping; private FrameGrouping frameGrouping;


public CombinedGrouping(ThreadGrouping threadGrouping, FrameGrouping frameGrouping) private CombinedGrouping(ThreadGrouping threadGrouping, FrameGrouping frameGrouping)
{ {
super(); super();
this.threadGrouping = threadGrouping; this.threadGrouping = threadGrouping;
Expand All @@ -31,4 +38,20 @@ public String apply(AggregationProfile profile, LeanNode node)
return (node instanceof LeanThreadNode) ? threadGrouping.apply((LeanThreadNode)node) return (node instanceof LeanThreadNode) ? threadGrouping.apply((LeanThreadNode)node)
: frameGrouping.apply(profile, node); : frameGrouping.apply(profile, node);
} }

public boolean equals(CombinedGrouping other)
{
return (threadGrouping == other.threadGrouping) && (frameGrouping == other.frameGrouping);
}

public int hashcode()
{
return Objects.hash(threadGrouping, frameGrouping);
}

@Override
public String toString()
{
return threadGrouping + " - " + frameGrouping;
}
} }
Expand Up @@ -7,12 +7,13 @@
public enum ThreadGrouping implements Function<LeanThreadNode, String> public enum ThreadGrouping implements Function<LeanThreadNode, String>
{ {


ALL_THREADS_TOGETHER(node -> "All Threads"), ALL_TOGETHER(node -> "All Threads"),
THREADS_BY_NAME(node -> node.getThreadInfo() == null BY_NAME(node -> node.getThreadInfo() == null
|| node.getThreadInfo().getName() == null || node.getThreadInfo().getName() == null
|| node.getThreadInfo().getName().isEmpty() ? "Unknown Thread(s)" || node.getThreadInfo().getName().isEmpty() ? "Unknown Thread(s)"
: node.getThreadInfo().getName()), : node.getThreadInfo().getName()),
THREADS_BY_ID(node -> node.getThreadInfo().getIdentification()); BY_ID(node -> node.getThreadInfo() == null ? "Unknown Thread <Unknown ID>"
: node.getThreadInfo().getIdentification());


private Function<LeanThreadNode, String> function; private Function<LeanThreadNode, String> function;


Expand Down
Expand Up @@ -7,6 +7,8 @@


import java.util.function.Function; import java.util.function.Function;


import com.insightfullogic.honest_profiler.core.aggregation.grouping.FrameGrouping;
import com.insightfullogic.honest_profiler.core.aggregation.grouping.ThreadGrouping;
import com.insightfullogic.honest_profiler.core.aggregation.result.ItemType; import com.insightfullogic.honest_profiler.core.aggregation.result.ItemType;
import com.insightfullogic.honest_profiler.ports.javafx.model.ProfileContext; import com.insightfullogic.honest_profiler.ports.javafx.model.ProfileContext;


Expand All @@ -16,6 +18,8 @@
import javafx.beans.property.SimpleObjectProperty; import javafx.beans.property.SimpleObjectProperty;
import javafx.scene.Node; import javafx.scene.Node;
import javafx.scene.control.Button; import javafx.scene.control.Button;
import javafx.scene.control.ChoiceBox;
import javafx.scene.control.Label;
import javafx.scene.control.TableColumn; import javafx.scene.control.TableColumn;
import javafx.scene.control.TextField; import javafx.scene.control.TextField;
import javafx.scene.control.TreeTableColumn; import javafx.scene.control.TreeTableColumn;
Expand Down Expand Up @@ -66,9 +70,19 @@ public abstract class AbstractProfileDiffViewController<T, U> extends AbstractVi
*/ */
@Override @Override
protected void initialize(Button filterButton, Button quickFilterButton, protected void initialize(Button filterButton, Button quickFilterButton,
TextField quickFilterText, ItemType type) TextField quickFilterText, ItemType type, Label threadGroupingLabel,
ChoiceBox<ThreadGrouping> threadGrouping, Label frameGroupingLabel,
ChoiceBox<FrameGrouping> frameGrouping)
{ {
super.initialize(filterButton, quickFilterButton, quickFilterText, type); super.initialize(
filterButton,
quickFilterButton,
quickFilterText,
type,
threadGroupingLabel,
threadGrouping,
frameGroupingLabel,
frameGrouping);


baseTarget = new SimpleObjectProperty<>(); baseTarget = new SimpleObjectProperty<>();
newTarget = new SimpleObjectProperty<>(); newTarget = new SimpleObjectProperty<>();
Expand Down
Expand Up @@ -4,6 +4,8 @@


import java.util.function.Function; import java.util.function.Function;


import com.insightfullogic.honest_profiler.core.aggregation.grouping.FrameGrouping;
import com.insightfullogic.honest_profiler.core.aggregation.grouping.ThreadGrouping;
import com.insightfullogic.honest_profiler.core.aggregation.result.ItemType; import com.insightfullogic.honest_profiler.core.aggregation.result.ItemType;
import com.insightfullogic.honest_profiler.ports.javafx.model.ProfileContext; import com.insightfullogic.honest_profiler.ports.javafx.model.ProfileContext;


Expand All @@ -13,6 +15,8 @@
import javafx.beans.property.SimpleObjectProperty; import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.value.ObservableObjectValue; import javafx.beans.value.ObservableObjectValue;
import javafx.scene.control.Button; import javafx.scene.control.Button;
import javafx.scene.control.ChoiceBox;
import javafx.scene.control.Label;
import javafx.scene.control.TextField; import javafx.scene.control.TextField;


/** /**
Expand Down Expand Up @@ -55,9 +59,19 @@ public abstract class AbstractProfileViewController<T, U> extends AbstractViewCo
*/ */
@Override @Override
protected void initialize(Button filterButton, Button quickFilterButton, protected void initialize(Button filterButton, Button quickFilterButton,
TextField quickFilterText, ItemType type) TextField quickFilterText, ItemType type, Label threadGroupingLabel,
ChoiceBox<ThreadGrouping> threadGrouping, Label frameGroupingLabel,
ChoiceBox<FrameGrouping> frameGrouping)
{ {
super.initialize(filterButton, quickFilterButton, quickFilterText, type); super.initialize(
filterButton,
quickFilterButton,
quickFilterText,
type,
threadGroupingLabel,
threadGrouping,
frameGroupingLabel,
frameGrouping);


target = new SimpleObjectProperty<>(); target = new SimpleObjectProperty<>();
target.addListener((property, oldValue, newValue) -> refresh()); target.addListener((property, oldValue, newValue) -> refresh());
Expand Down Expand Up @@ -107,7 +121,10 @@ protected T getTarget()
public void bind(ObservableObjectValue<? extends Object> source, public void bind(ObservableObjectValue<? extends Object> source,
Function<Object, T> targetExtractor) Function<Object, T> targetExtractor)
{ {
sourceBinding = createObjectBinding(() -> targetExtractor.apply(source.get()), source); sourceBinding = createObjectBinding(
() -> targetExtractor.apply(source.get()),
source,
getGrouping());
} }


// Activation // Activation
Expand Down

0 comments on commit e395024

Please sign in to comment.