-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
0188b71
commit 32c3158
Showing
2 changed files
with
253 additions
and
0 deletions.
There are no files selected for viewing
77 changes: 77 additions & 0 deletions
77
book/Think-Data-Structures-In-Java/src/practice4/ProfileListAdd.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
176
book/Think-Data-Structures-In-Java/src/practice4/Profiler.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); | ||
} | ||
} |