cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
Try the Materials Informatics Toolkit, which is designed to easily handle SMILES data. This and other helpful add-ins are available in the JMP® Marketplace
Choose Language Hide Translation Bar

Optimizing list box content update.

Hello JMP community,

 

Lately, I was looking into improve the performance of my internal JSL scripts and I found the following performance issues that I would like to address.

Lets take the following script (JMP 17.2 PRO running on macOS):

 

Names Default To Here( 1 );
dt = Open( "$SAMPLE_DATA/Big Class.jmp" );

values = Column( dt, 1 )[dt << get rows where( Excluded( Row State() ) != 1 )];
new window("test", 
	lb = list box( values, nlines(10), width(100), ),
	b = button box("reset", reset_lb),
	);
	
reset_lb = expr(
	lb << remove all();
	lb << append(values);
	
	Nnames = N Items(values);
	for(i = 1, i <= Nnames, i++,
		lb << set selected(i);
	);
);

In some of my scripts I am using list boxes that are dynamically updated. For changing the content of the list boxes I use the << remove() and << append() functions, they work just fine but I am afraid that this method does not scale very well with the number of rows, another portion that surprisingly runs really slow is the for loop with << set selected(), apparently this is the only method that I could find for selecting all the items in a list box but it scales terribly with the number of rows.

 

My questions is if there are any best known ways to update the content of the list boxes that is not slow performance wise. I am looking for possible alternatives that would do:

  1. optimal method to set the content of the list box.
  2. fast way to select all the items of the list box.

Any feedback or suggestions would be greatly appreciated.

 

1 ACCEPTED SOLUTION

Accepted Solutions
jthi
Super User

Re: Optimizing list box content update.

Both of these methods feel fairly fast in my opinion

Names Default To Here(1);

rowcount = 100000;

dt = New Table("Demo",
	Add Rows(rowcount),
	New Column("Values", Character, Nominal, << Set Each Value(
		Hex(Row()) || Hex(Row()) || Hex(Row())
	))
);

values = Column(dt, 1)[dt << get rows where(Excluded(Row State()) != 1)];
Close(dt, no save);

nw = New Window("test",
	H List Box(
		H List Box(
			lb1 = List Box(values, nlines(10), width(100)),
			Button Box("reset", reset_lb1),			
		)
	),
	H List Box(
		H List Box(
			lb2_collector = V List Box(
				lb2 = List Box(values, nlines(10), width(100)),
			),
			Button Box("reset2", reset_lb2),			
		)
	)
);
	
reset_lb1 = Expr(
	start1 = HP Time();
	lb1 << Set Items(values);
	end1 = HP Time();
	start2 = end1;
	Nnames = N Items(values);
	For(i = 1, i <= Nnames, i++,
		lb1 << set selected(i);
	);
	end2 = HP Time();
	Show((end1 - start1)/1e6, (end2-start2)/1e6, (end2-start1)/1e6);
);

reset_lb2 = Expr(
	start3 = HP Time();
	vlb = V List Box(lb2 = List Box(values, nlines(10), width(100)));
	For Each({val, idx}, values,
		lb2 << set selected(idx);
	);
	While(!IsEmpty(lb2_collector << child),
		(lb2_collector << child) << delete box;
	);
	lb2_collector << Append(vlb);
	end3 = HP Time();
	Show((end3 - start3)/1e6);
);

Write();
-Jarmo

View solution in original post

5 REPLIES 5
jthi
Super User

Re: Optimizing list box content update.

How many items are you expecting to have in the list box? For 1 there is << Set Items() you can use 

 

Edit:

-Jarmo

Re: Optimizing list box content update.

Hello Jarmo,

 

Thanks for the reply, I will try to use << Set Items() and will check if it is faster then <<remove all(), << append().

 

Regarding the number of items, it is about around ~30k, the strange thing is when I load the script it takes much less to populate the lb from scratch then it takes to update contents, I was thinking as a method to delete the list boxes and then create them again but it might be quite difficult to do all these changes in the scripts.

jthi
Super User

Re: Optimizing list box content update.

Both of these methods feel fairly fast in my opinion

Names Default To Here(1);

rowcount = 100000;

dt = New Table("Demo",
	Add Rows(rowcount),
	New Column("Values", Character, Nominal, << Set Each Value(
		Hex(Row()) || Hex(Row()) || Hex(Row())
	))
);

values = Column(dt, 1)[dt << get rows where(Excluded(Row State()) != 1)];
Close(dt, no save);

nw = New Window("test",
	H List Box(
		H List Box(
			lb1 = List Box(values, nlines(10), width(100)),
			Button Box("reset", reset_lb1),			
		)
	),
	H List Box(
		H List Box(
			lb2_collector = V List Box(
				lb2 = List Box(values, nlines(10), width(100)),
			),
			Button Box("reset2", reset_lb2),			
		)
	)
);
	
reset_lb1 = Expr(
	start1 = HP Time();
	lb1 << Set Items(values);
	end1 = HP Time();
	start2 = end1;
	Nnames = N Items(values);
	For(i = 1, i <= Nnames, i++,
		lb1 << set selected(i);
	);
	end2 = HP Time();
	Show((end1 - start1)/1e6, (end2-start2)/1e6, (end2-start1)/1e6);
);

reset_lb2 = Expr(
	start3 = HP Time();
	vlb = V List Box(lb2 = List Box(values, nlines(10), width(100)));
	For Each({val, idx}, values,
		lb2 << set selected(idx);
	);
	While(!IsEmpty(lb2_collector << child),
		(lb2_collector << child) << delete box;
	);
	lb2_collector << Append(vlb);
	end3 = HP Time();
	Show((end3 - start3)/1e6);
);

Write();
-Jarmo
jthi
Super User

Re: Optimizing list box content update.

One thing to note is that << Set Selected will run script associated with list box (if there is one) by default. If you have script associated with it but don't want it to trigger with each set, use << Set Selected(idx, 1, Run Script(0)) (you can trigger it on last set if you need to)

Names Default To Here(1);

rowcount = 100000;

dt = New Table("Demo",
	Add Rows(rowcount),
	New Column("Values", Character, Nominal, << Set Each Value(
		Hex(Row()) || Hex(Row()) || Hex(Row())
	))
);

values = Column(dt, 1)[dt << get rows where(Excluded(Row State()) != 1)];
Close(dt, no save);

nw = New Window("test",
	H List Box(
		lb2_collector = V List Box(
			lb2 = List Box(values, nlines(10), width(100), Show(1)),
		),
		Button Box("reset2", reset_lb2),			
	)
);
	
reset_lb2 = Expr(
	start3 = HP Time();
	vlb = V List Box(lb2 = List Box(values, nlines(10), width(100), Show(1)));
	For(i = 1, i < N Items(values), i++,
		lb2 << set selected(i, 1, Run Script(0));
	);
	lb2 << set selected(N Items(values), 1, Run Script(1));

	While(!IsEmpty(lb2_collector << child),
		(lb2_collector << child) << delete box;
	);
	lb2_collector << Append(vlb);
	end3 = HP Time();
	Show((end3 - start3)/1e6);
);

Write();

 

-Jarmo

Re: Optimizing list box content update.

Thanks a lot for demonstration. On my machine the second method is around 5x faster, and as you can see most of the time from first method is spent for the set selected loop.