Skip to content

Commit c59389d

Browse files
committed
implemented merge sorting of items from multiple chunks
1 parent 841c6a4 commit c59389d

File tree

4 files changed

+139
-13
lines changed

4 files changed

+139
-13
lines changed

application/org.openjdk.jmc.flightrecorder.ui/src/main/java/org/openjdk/jmc/flightrecorder/ui/common/DataPageToolkit.java

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved.
33
*
44
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
55
*
@@ -98,6 +98,7 @@
9898
import org.eclipse.ui.forms.widgets.Form;
9999
import org.eclipse.ui.forms.widgets.FormText;
100100
import org.eclipse.ui.forms.widgets.FormToolkit;
101+
import org.openjdk.jmc.common.collection.IteratorToolkit;
101102
import org.openjdk.jmc.common.item.IAggregator;
102103
import org.openjdk.jmc.common.item.IAttribute;
103104
import org.openjdk.jmc.common.item.ICanonicalAccessorFactory;
@@ -643,11 +644,15 @@ public static IXDataRenderer buildSpanRenderer(IItemCollection pathItems, IColor
643644
public static boolean addEndTimeLines(
644645
XYDataRenderer renderer, IItemCollection items, boolean fill, Stream<IAttribute<IQuantity>> yAttributes) {
645646
if (items.hasItems()) {
646-
Iterator<IItemIterable> ii = items.iterator();
647-
IType<IItem> type = ii.hasNext() ? ii.next().getType() : null;
648-
List<IItem> allItems = new ArrayList<>();
649-
items.forEach(itemStream -> itemStream.forEach(allItems::add));
650-
return yAttributes.peek(a -> addEndTimeLine(renderer, allItems.iterator(), type, a, fill))
647+
List<Iterator<IItem>> iterators = new ArrayList<>();
648+
for (IItemIterable ii : items) {
649+
iterators.add(ii.iterator());
650+
}
651+
IType<IItem> type = items.iterator().next().getType();
652+
IMemberAccessor<IQuantity, IItem> accessor = JfrAttributes.END_TIME.getAccessor(type);
653+
Comparator<IItem> comparator = Comparator.comparing(item -> accessor.getMember(item));
654+
return yAttributes.peek(
655+
a -> addEndTimeLine(renderer, IteratorToolkit.mergedSorting(iterators, comparator), type, a, fill))
651656
.mapToLong(a -> 1L).sum() > 0;
652657
}
653658
return false;

application/org.openjdk.jmc.flightrecorder.ui/src/main/java/org/openjdk/jmc/flightrecorder/ui/pages/itemhandler/ItemChart.java

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved.
33
*
44
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
55
*
@@ -36,6 +36,7 @@
3636
import java.util.Arrays;
3737
import java.util.Collection;
3838
import java.util.Collections;
39+
import java.util.Comparator;
3940
import java.util.Iterator;
4041
import java.util.LinkedHashMap;
4142
import java.util.List;
@@ -59,12 +60,14 @@
5960
import org.eclipse.ui.forms.widgets.FormToolkit;
6061
import org.openjdk.jmc.common.IState;
6162
import org.openjdk.jmc.common.IWritableState;
63+
import org.openjdk.jmc.common.collection.IteratorToolkit;
6264
import org.openjdk.jmc.common.item.Aggregators;
6365
import org.openjdk.jmc.common.item.IAggregator;
6466
import org.openjdk.jmc.common.item.IAttribute;
6567
import org.openjdk.jmc.common.item.IItem;
6668
import org.openjdk.jmc.common.item.IItemCollection;
6769
import org.openjdk.jmc.common.item.IItemIterable;
70+
import org.openjdk.jmc.common.item.IMemberAccessor;
6871
import org.openjdk.jmc.common.item.IType;
6972
import org.openjdk.jmc.common.item.ItemFilters;
7073
import org.openjdk.jmc.common.unit.ContentType;
@@ -545,13 +548,17 @@ private Collection<ItemRow> updateLineChart(IItemCollection itemsToChart) {
545548
IItemCollection itemsWithAttributeSomeType = itemsToChart
546549
.apply(ItemFilters.hasAttribute(attribute));
547550
if (itemsWithAttributeSomeType.hasItems()) {
548-
Iterator<IItemIterable> iterator = itemsWithAttributeSomeType.iterator();
549-
IType<IItem> type = iterator.hasNext() ? iterator.next().getType() : null;
550-
List<IItem> allItems = new ArrayList<>();
551-
itemsWithAttributeSomeType.forEach(itemStream -> itemStream.forEach(allItems::add));
551+
List<Iterator<IItem>> iterators = new ArrayList<>();
552+
for (IItemIterable ii : itemsWithAttributeSomeType) {
553+
iterators.add(ii.iterator());
554+
}
555+
IType<IItem> type = itemsWithAttributeSomeType.iterator().next().getType();
556+
IMemberAccessor<IQuantity, IItem> accessor = JfrAttributes.END_TIME.getAccessor(type);
557+
Comparator<IItem> comparator = Comparator.comparing(item -> accessor.getMember(item));
552558
@SuppressWarnings("unchecked")
553559
IAttribute<IQuantity> qAttribute = (IAttribute<IQuantity>) attribute;
554-
DataPageToolkit.addEndTimeLine(xyRenderer, allItems.iterator(), type, qAttribute, fill);
560+
DataPageToolkit.addEndTimeLine(xyRenderer,
561+
IteratorToolkit.mergedSorting(iterators, comparator), type, qAttribute, fill);
555562
}
556563
}
557564
}

core/org.openjdk.jmc.common/src/main/java/org/openjdk/jmc/common/collection/IteratorToolkit.java

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved.
33
*
44
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
55
*
@@ -33,9 +33,13 @@
3333
package org.openjdk.jmc.common.collection;
3434

3535
import java.util.ArrayList;
36+
import java.util.Collection;
37+
import java.util.Comparator;
3638
import java.util.Iterator;
3739
import java.util.List;
3840
import java.util.NoSuchElementException;
41+
import java.util.PriorityQueue;
42+
import java.util.Queue;
3943
import java.util.function.Predicate;
4044

4145
/**
@@ -106,6 +110,41 @@ protected T findNext() {
106110
};
107111
}
108112

113+
/**
114+
* Wrap an iterator in a new iterator that merges values from sorted iterators.
115+
*
116+
* @param <T>
117+
* input iterator type
118+
* @param iterators
119+
* input iterators
120+
* @param comparator
121+
* ordering rule function
122+
* @return a new iterator that contains sorted elements
123+
*/
124+
public static <T> Iterator<T> mergedSorting(
125+
final Collection<? extends Iterator<T>> iterators, final Comparator<T> comparator) {
126+
final Queue<PeekingIterator<T>> priorityQueue = new PriorityQueue<>(
127+
Comparator.comparing(PeekingIterator::peek, comparator));
128+
for (Iterator<T> iterator : iterators) {
129+
if (iterator.hasNext()) {
130+
priorityQueue.add(new PeekingIterator<>(iterator));
131+
}
132+
}
133+
134+
return new AbstractIterator<T>() {
135+
@Override
136+
protected T findNext() {
137+
if (priorityQueue.isEmpty())
138+
return NO_MORE_ELEMENTS;
139+
PeekingIterator<T> minPeekingIterator = priorityQueue.poll();
140+
T result = minPeekingIterator.next();
141+
if (minPeekingIterator.hasNext())
142+
priorityQueue.add(minPeekingIterator);
143+
return result;
144+
}
145+
};
146+
}
147+
109148
/**
110149
* Iterator that iterates over an array. Hopefully faster than Arrays.asList(...).iterator()
111150
* since there are no concurrency checks.
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
/*
2+
* Copyright (c) 2018, 2026 Oracle and/or its affiliates. All rights reserved.
3+
*
4+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5+
*
6+
* The contents of this file are subject to the terms of either the Universal Permissive License
7+
* v 1.0 as shown at https://oss.oracle.com/licenses/upl
8+
*
9+
* or the following license:
10+
*
11+
* Redistribution and use in source and binary forms, with or without modification, are permitted
12+
* provided that the following conditions are met:
13+
*
14+
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions
15+
* and the following disclaimer.
16+
*
17+
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of
18+
* conditions and the following disclaimer in the documentation and/or other materials provided with
19+
* the distribution.
20+
*
21+
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to
22+
* endorse or promote products derived from this software without specific prior written permission.
23+
*
24+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
25+
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
26+
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
27+
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29+
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
30+
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
31+
* WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32+
*/
33+
package org.openjdk.jmc.common.collection;
34+
35+
import java.util.Iterator;
36+
37+
/**
38+
* Iterator wrapper that allows peeking at the next element.
39+
*
40+
* @param <T>
41+
* the type of elements returned by the iterator
42+
*/
43+
public class PeekingIterator<T> implements Iterator<T> {
44+
private final Iterator<T> sourceIterator;
45+
private T peekedElement;
46+
private boolean hasPeeked;
47+
48+
public PeekingIterator(Iterator<T> sourceIterator) {
49+
this.sourceIterator = sourceIterator;
50+
}
51+
52+
public T peek() {
53+
if (!this.hasPeeked) {
54+
this.hasPeeked = true;
55+
this.peekedElement = this.sourceIterator.next();
56+
}
57+
return this.peekedElement;
58+
}
59+
60+
@Override
61+
public T next() {
62+
if (!this.hasPeeked) {
63+
return this.sourceIterator.next();
64+
}
65+
this.hasPeeked = false;
66+
T result = this.peekedElement;
67+
this.peekedElement = null;
68+
return result;
69+
}
70+
71+
@Override
72+
public boolean hasNext() {
73+
return this.hasPeeked || this.sourceIterator.hasNext();
74+
}
75+
}

0 commit comments

Comments
 (0)