2525
2626package org .graalvm .visualvm .heapviewer .utils ;
2727
28+ import java .awt .event .ActionEvent ;
2829import java .text .Format ;
2930import java .util .Iterator ;
3031import java .util .List ;
32+ import java .util .Random ;
33+ import java .util .SortedSet ;
34+ import java .util .TreeSet ;
3135import javax .swing .SortOrder ;
36+ import org .graalvm .visualvm .heapviewer .HeapContext ;
3237import org .graalvm .visualvm .lib .jfluid .heap .Heap ;
3338import org .graalvm .visualvm .lib .ui .Formatters ;
3439import org .graalvm .visualvm .heapviewer .model .DataType ;
3540import org .graalvm .visualvm .heapviewer .model .HeapViewerNode ;
3641import org .graalvm .visualvm .heapviewer .model .HeapViewerNodeFilter ;
3742import org .graalvm .visualvm .heapviewer .model .MoreNodesNode ;
3843import org .graalvm .visualvm .heapviewer .model .Progress ;
44+ import org .graalvm .visualvm .heapviewer .model .RootNode ;
3945import org .graalvm .visualvm .heapviewer .model .TextNode ;
46+ import org .graalvm .visualvm .heapviewer .ui .HeapViewerActions ;
47+ import org .graalvm .visualvm .heapviewer .ui .HeapViewerNodeAction ;
4048import org .graalvm .visualvm .heapviewer .ui .UIThresholds ;
4149import org .openide .util .NbBundle ;
50+ import org .openide .util .lookup .ServiceProvider ;
4251
4352/**
4453 *
@@ -294,10 +303,9 @@ private HeapViewerNode[] computeChildren(int containerIndex, Heap heap, String v
294303// }
295304 }
296305
297- private HeapViewerNode [] computeSampleChildren (int count , Heap heap , String viewID , HeapViewerNodeFilter viewFilter , List <DataType > dataTypes , List <SortOrder > sortOrders , Progress progress ) throws InterruptedException {
306+ private HeapViewerNode [] computeSampleChildren (int type , int count , Heap heap , String viewID , HeapViewerNodeFilter viewFilter , List <DataType > dataTypes , List <SortOrder > sortOrders , Progress progress ) throws InterruptedException {
298307 // TODO: use random-access for indexable version
299308 int index = 0 ;
300- int nextHit = 0 ;
301309 int step = objectsCount / (count - 1 );
302310
303311 HeapViewerNode [] nodes ;
@@ -306,14 +314,28 @@ private HeapViewerNode[] computeSampleChildren(int count, Heap heap, String view
306314 progress .setupKnownSteps (iteratorObjectsCount );
307315
308316 int i = 0 ;
317+ Integer [] indexes = new Integer [count ];
318+ if (type == 0 ) {
319+ int hitIndex = 0 ;
320+ for (int j = 0 ; j < count ; j ++) {
321+ indexes [j ] = hitIndex ;
322+ hitIndex = j == count - 2 ? objectsCount - 1 : hitIndex + step ;
323+ }
324+ } else {
325+ Random r = new Random (type *7 );
326+ SortedSet <Integer > idSet = new TreeSet ();
327+ while (idSet .size () < count ) {
328+ idSet .add (r .nextInt (objectsCount ));
329+ }
330+ idSet .toArray (indexes );
331+ }
309332 nodes = new HeapViewerNode [count ];
310333 Iterator <T > objectsIt = objectsIterator (0 , progress );
311- while (i < objectsCount && objectsIt .hasNext ()) {
334+ while (index < count && i < objectsCount && objectsIt .hasNext ()) {
312335 T object = objectsIt .next ();
313336
314- if (i == nextHit ) {
337+ if (i == indexes [ index ] ) {
315338 nodes [index ++] = createNode (object );
316- nextHit = index == count - 1 ? objectsCount - 1 : nextHit + step ;
317339 }
318340
319341 i ++;
@@ -331,6 +353,7 @@ private HeapViewerNode[] computeSampleChildren(int count, Heap heap, String view
331353 private class SampleContainer extends TextNode {
332354
333355 private final int count ;
356+ private int type ;
334357
335358 SampleContainer (String text , int count ) {
336359 super (text );
@@ -339,11 +362,60 @@ private class SampleContainer extends TextNode {
339362 }
340363
341364 protected HeapViewerNode [] lazilyComputeChildren (Heap heap , String viewID , HeapViewerNodeFilter viewFilter , List <DataType > dataTypes , List <SortOrder > sortOrders , Progress progress ) throws InterruptedException {
342- return MoreObjectsNode .this .computeSampleChildren (count , heap , viewID , viewFilter , dataTypes , sortOrders , progress );
365+ return MoreObjectsNode .this .computeSampleChildren (type , count , heap , viewID , viewFilter , dataTypes , sortOrders , progress );
343366 }
344367
368+ void incrementType () {
369+ type ++;
370+ resetChildren ();
371+ RootNode root = RootNode .get (this );
372+ if (root != null ) {
373+ // clear node cache
374+ root .retrieveChildren (this );
375+ root .updateChildren (root );
376+ }
377+ }
345378 }
346379
380+ @ ServiceProvider (service =HeapViewerNodeAction .Provider .class )
381+ public static class ShuffleActionProvider extends HeapViewerNodeAction .Provider {
382+
383+ @ Override
384+ public boolean supportsView (HeapContext context , String viewID ) {
385+ return true ;
386+ }
387+
388+ @ Override
389+ public HeapViewerNodeAction [] getActions (HeapViewerNode node , HeapContext context , HeapViewerActions actions ) {
390+ if (node instanceof MoreObjectsNode .SampleContainer ) {
391+ return new HeapViewerNodeAction []{new ShuffleAction ((MoreObjectsNode .SampleContainer )node )};
392+ }
393+ return null ;
394+ }
395+ }
396+
397+ @ NbBundle .Messages ("MoreObjectsNode_ShuffleAction=Different Sample" )
398+ private static class ShuffleAction extends HeapViewerNodeAction {
399+
400+ private final MoreObjectsNode .SampleContainer node ;
401+
402+ ShuffleAction (MoreObjectsNode .SampleContainer node ) {
403+ super (org .graalvm .visualvm .heapviewer .utils .Bundle .MoreObjectsNode_ShuffleAction (), 110 );
404+ this .node = node ;
405+ setEnabled (!node .isLeaf ());
406+ }
407+
408+ public boolean isMiddleButtonDefault (ActionEvent e ) {
409+ int modifiers = e .getModifiers ();
410+ return (modifiers & ActionEvent .CTRL_MASK ) == ActionEvent .CTRL_MASK &&
411+ (modifiers & ActionEvent .SHIFT_MASK ) != ActionEvent .SHIFT_MASK ;
412+ }
413+
414+ public void actionPerformed (ActionEvent e ) {
415+ node .incrementType ();
416+ }
417+ }
418+
347419 private class ObjectsContainer extends TextNode {
348420
349421 private final int containerIndex ;
0 commit comments