Skip to content

Instantly share code, notes, and snippets.

@hageldave
Last active April 29, 2026 10:04
Show Gist options
  • Select an option

  • Save hageldave/ace9c3bebca24704201e3f2041e77bd3 to your computer and use it in GitHub Desktop.

Select an option

Save hageldave/ace9c3bebca24704201e3f2041e77bd3 to your computer and use it in GitHub Desktop.
import java.util.ArrayList;
/**
* BilloProfiler is a low fidelity manual profiling utility.
* Billo = Billig (German slang) = cheap/tacky.
* <br>
* You need to manually put {@link #start()} and {@link #stop()} at the piece of code you like to profile,
* and sprinkle {@link #split(String)} inbetween to get timings for different sections.
* Then you can simply print the profiler to get the total time and fractions of the time for the sections.
* You can use the global {@link #instance} to facilitate profiling over multiple classes.
*/
public class BilloProfiler {
public static final BilloProfiler instance = new BilloProfiler();
static class Pair<T1,T2> {
public final T1 first;
public final T2 second;
public Pair(T1 first, T2 second) {
this.first = first;
this.second = second;
}
public static <T1,T2> Pair<T1,T2> of(T1 first, T2 second) {
return new Pair<>(first, second);
}
}
ArrayList<Pair<String, Long>> timings = new ArrayList<>(100);
public BilloProfiler clear() {
timings.clear();
return this;
}
public BilloProfiler start() {
this.clear();
timings.add(Pair.of("start", System.nanoTime()));
return this;
}
public BilloProfiler stop() {
timings.add(Pair.of("stop", System.nanoTime()));
return this;
}
public BilloProfiler split(String identifier) {
timings.add(Pair.of(identifier, System.nanoTime()));
return this;
}
public long time(int i) {
return timings.get(i).second.longValue();
}
public String identifier(int i) {
return timings.get(i).first;
}
public long total() {
if(timings.size() < 2)
return 0;
else return time(timings.size()-1) - time(0);
}
public long[] deltas() {
long[] deltas = new long[timings.size()-1];
for(int i=0; i<deltas.length; i++) {
deltas[i] = time(i+1)-time(i);
}
return deltas;
}
@Override
public String toString() {
long total = total();
if(total == 0) {
return "[]";
}
double divByTotal = 1.0/total;
StringBuilder sb = new StringBuilder();
sb.append("[total ms ");
sb.append(String.format("%.3f ", total*0.000001));
sb.append('\n');
long[] deltas = deltas();
for(int i=0; i<deltas.length; i++) {
sb.append(identifier(i));
sb.append('\n');
sb.append(String.format(" %.2f ", deltas[i]*divByTotal*100));
sb.append('\n');
}
sb.append(identifier(timings.size()-1));
sb.append("]");
return sb.toString();
}
}
@hageldave

hageldave commented Apr 29, 2026

Copy link
Copy Markdown
Author

Example Usage:

	public void testConvergence(){
		ColorSpaceTransformation[] toTest = {
				ColorSpaceTransformation.RGB_2_LAB,
				ColorSpaceTransformation.RGB_2_HSV,
				ColorSpaceTransformation.RGB_2_YCbCr
		};
		BilloProfiler.instance.start();
		{ // discrete
			Img ref = getTestImg();
			Img img = new Img(ref.getDimension());
			for(ColorSpaceTransformation cst : toTest){
				ref.copyArea(0, 0, img.getWidth(), img.getHeight(), img, 0, 0);
				BilloProfiler.instance.split("Start "+cst.name());
				for(int i = 0; i < 2+greyErrorThreshold; i++){
					img.forEach(true, cst);
					img.forEach(true, cst.inverse());
				}
				BilloProfiler.instance.split("End "+cst.name());
				int[] error = getMaxGreyError(ref, img);
				assertTrue(error[0]< greyErrorThreshold);
			}
		}
		BilloProfiler.instance.stop();
		System.out.println(BilloProfiler.instance);
	}

Output:

[total ms 5023.971 
start
 2.02 
Start RGB_2_LAB
 65.25 
End RGB_2_LAB
 1.58 
Start RGB_2_HSV
 17.11 
End RGB_2_HSV
 1.22 
Start RGB_2_YCbCr
 11.89 
End RGB_2_YCbCr
 0.93 
stop]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment