Skip to content

Commit

Permalink
copy: profiler practice #33
Browse files Browse the repository at this point in the history
  • Loading branch information
seokjun7410 committed Nov 28, 2023
1 parent 0188b71 commit 32c3158
Show file tree
Hide file tree
Showing 2 changed files with 253 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package practice4;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

import org.jfree.data.xy.XYSeries;


public class ProfileListAdd {

/**
* @param args
*/
public static void main(String[] args) {
profileArrayListAddEnd();
// profileArrayListAddBeginning();
//profileLinkedListAddBeginning();
//profileLinkedListAddEnd();
}

/**
* Characterize the run time of adding to the end of an ArrayList
*/
public static void profileArrayListAddEnd() {
Profiler.Timeable timeable = new Profiler.Timeable() {
List<String> list;

public void setup(int n) {
list = new ArrayList<String>();
}

public void timeMe(int n) {
for (int i=0; i<n; i++) {
list.add("a string");
}
}
};
int startN = 4000;
int endMillis = 1000;
runProfiler("ArrayList add end", timeable, startN, endMillis);
}

/**
* Characterize the run time of adding to the beginning of an ArrayList
*/
public static void profileArrayListAddBeginning() {
// TODO: FILL THIS IN!
}

/**
* Characterize the run time of adding to the beginning of a LinkedList
*/
public static void profileLinkedListAddBeginning() {
// TODO: FILL THIS IN!
}

/**
* Characterize the run time of adding to the end of a LinkedList
*/
public static void profileLinkedListAddEnd() {
// TODO: FILL THIS IN!
}

/**
* Runs the profiles and displays results.
*
* @param timeable
* @param startN
* @param endMillis
*/
private static void runProfiler(String title, Profiler.Timeable timeable, int startN, int endMillis) {
Profiler profiler = new Profiler(title, timeable);
XYSeries series = profiler.timingLoop(startN, endMillis);
profiler.plotResults(series);
}
}
176 changes: 176 additions & 0 deletions book/Think-Data-Structures-In-Java/src/practice4/Profiler.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
package practice4;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;

import org.apache.commons.math3.stat.regression.SimpleRegression;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.LogarithmicAxis;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.data.xy.XYDataItem;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
import org.jfree.ui.ApplicationFrame;
import org.jfree.ui.RefineryUtilities;

/**
* @author downey
*
*/
public class Profiler extends ApplicationFrame {

/**
* This is here because extending ApplicationFrame requires it.
*/
private static final long serialVersionUID = 1L;

/**
* Timeable defines the methods an object must provide to work with Profiler
*
*/
public interface Timeable {
/*
* setup is invoked before the clock starts.
*/
public void setup(int n);

/*
* timeMe does whatever operation we are timing.
*/
public void timeMe(int n);
}

private Timeable timeable;

public Profiler(String title, Timeable timeable) {
super(title);
this.timeable = timeable;
}

/**
* Invokes timeIt with a range of `n` from `startN` until runtime exceeds `endMillis`.
*
* @param data.timeable
* @param n
* @return
*/
public XYSeries timingLoop(int startN, int endMillis) {
final XYSeries series = new XYSeries("Time (ms)");

int n = startN;
for (int i=0; i<20; i++) {
// run it once to warm up
timeIt(n);

// then start timing
long total = 0;

// run 10 times and add up total runtime
for (int j=0; j<10; j++) {
total += timeIt(n);
}
System.out.println(n + ", " + total);

// don't store data until we get to 4ms
if (total > 4) {
series.add(n, total);
}

// stop when the runtime exceeds the end threshold
if (total > endMillis) {
break;
}
// otherwise double the size and continue
n *= 2;
}
return series;
}

/**
* Invokes setup and timeMe on the embedded Timeable.
*
* @param n
* @return
*/
public long timeIt(int n) {
timeable.setup(n);
final long startTime = System.currentTimeMillis();
timeable.timeMe(n);
final long endTime = System.currentTimeMillis();
return endTime - startTime;
}

/**
* Plots the results.
*
* @param series
*/
public void plotResults(XYSeries series) {
double slope = estimateSlope(series);
System.out.println("Estimated slope= " + slope);

final XYSeriesCollection dataset = new XYSeriesCollection();
dataset.addSeries(series);

final JFreeChart chart = ChartFactory.createXYLineChart(
"", // chart title
"", // domain axis label
"", // range axis label
dataset, // data
PlotOrientation.VERTICAL,
false, // include legend
true,
false
);

final XYPlot plot = chart.getXYPlot();
final NumberAxis domainAxis = new LogarithmicAxis("Problem size (n)");
final NumberAxis rangeAxis = new LogarithmicAxis("Runtime (ms)");
plot.setDomainAxis(domainAxis);
plot.setRangeAxis(rangeAxis);
plot.setOutlinePaint(Color.black);
final ChartPanel chartPanel = new ChartPanel(chart);
chartPanel.setPreferredSize(new java.awt.Dimension(1000, 600));
setContentPane(chartPanel);
pack();
RefineryUtilities.centerFrameOnScreen(this);

// customize the appearance of the graph
plot.setBackgroundPaint(Color.white);
int seriesCount = plot.getSeriesCount();

for (int i = 0; i < seriesCount; i++) {
plot.getRenderer().setSeriesStroke(i, new BasicStroke(3));
}
Font font24 = new Font("Dialog", Font.PLAIN, 24);
plot.getDomainAxis().setLabelFont(font24);
plot.getRangeAxis().setLabelFont(font24);
Font font20 = new Font("Dialog", Font.PLAIN, 20);
plot.getDomainAxis().setTickLabelFont(font20);
plot.getRangeAxis().setTickLabelFont(font20);

setVisible(true);
}

/**
* Uses simple regression to estimate the slope of the series.
*
* @param series
* @return
*/
public double estimateSlope(XYSeries series) {
SimpleRegression regression = new SimpleRegression();

for (Object item: series.getItems()) {
XYDataItem xy = (XYDataItem) item;
regression.addData(Math.log(xy.getXValue()), Math.log(xy.getYValue()));
}
return regression.getSlope();
}
}

0 comments on commit 32c3158

Please sign in to comment.