DeflateComparison.java
- package gov.usgs.earthquake.distribution;
- import gov.usgs.earthquake.product.FileContent;
- import gov.usgs.earthquake.product.Product;
- import gov.usgs.earthquake.product.ProductId;
- import gov.usgs.earthquake.product.io.BinaryProductHandler;
- import gov.usgs.earthquake.product.io.ObjectProductSource;
- import gov.usgs.util.StreamUtils;
- import java.io.ByteArrayInputStream;
- import java.io.ByteArrayOutputStream;
- import java.io.File;
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.OutputStream;
- import java.net.URL;
- import java.util.Date;
- import java.util.zip.Deflater;
- import java.util.zip.DeflaterOutputStream;
- public class DeflateComparison {
- /**
- * Deflate an input stream.
- *
- * @param level
- * deflate level.
- * @param in
- * input stream to deflate.
- * @return output length in bytes.
- * @throws IOException if IO error occurs
- */
- public long deflateStream(final int level, final InputStream in)
- throws IOException {
- CountingOutputStream cos = new CountingOutputStream();
- DeflaterOutputStream dos = new DeflaterOutputStream(cos, new Deflater(
- level));
- StreamUtils.transferStream(in, new StreamUtils.UnclosableOutputStream(
- dos));
- dos.finish();
- dos.close();
- return cos.getTotalBytes();
- }
- /**
- * Transfer an input stream.
- *
- * @param in
- * input stream to transfer.
- * @return output length in bytes.
- * @throws IOException if IO error occurs
- */
- public long transferStream(final InputStream in) throws IOException {
- CountingOutputStream cos = new CountingOutputStream();
- StreamUtils.transferStream(in, cos);
- return cos.getTotalBytes();
- }
- /**
- * Test different compression levels and speeds for a file.
- *
- * Reads file into memory to avoid disk io overhead.
- *
- * @param file
- * file to test.
- * @throws IllegalArgumentException if illegal arg
- * @throws IOException if IO error occurs
- */
- public void testFile(final File file) throws IllegalArgumentException,
- IOException {
- // read into memory to avoid disk io overhead
- byte[] fileContent = StreamUtils.readStream(StreamUtils
- .getInputStream(file));
- testByteArray(file.getCanonicalPath(), fileContent);
- }
- /**
- * Test different compression levels and speeds for a byte array.
- *
- * @param name
- * given name
- * @param content
- * content to test.
- * @throws IllegalArgumentException if illegal arg
- * @throws IOException if IO error occurs
- */
- public void testByteArray(final String name, final byte[] content)
- throws IOException {
- Date start;
- long totalBytes = content.length;
- System.err.println(name + ", length = " + totalBytes + " bytes");
- System.err.println("no compression");
- start = new Date();
- long noCompression = transferStream(new ByteArrayInputStream(content));
- long noCompressionTime = new Date().getTime() - start.getTime();
- formatResult(totalBytes, noCompression, noCompressionTime);
- System.err.println("default compression (-1)");
- start = new Date();
- long deflateDefault = deflateStream(Deflater.DEFAULT_COMPRESSION,
- new ByteArrayInputStream(content));
- long deflateDefaultTime = new Date().getTime() - start.getTime();
- formatResult(totalBytes, deflateDefault, deflateDefaultTime);
- System.err.println("best speed (1)");
- start = new Date();
- long deflateBestSpeed = deflateStream(Deflater.BEST_SPEED,
- new ByteArrayInputStream(content));
- long deflateBestSpeedTime = new Date().getTime() - start.getTime();
- formatResult(totalBytes, deflateBestSpeed, deflateBestSpeedTime);
- System.err.println("best compression (9)");
- start = new Date();
- long deflateBestCompression = deflateStream(Deflater.BEST_COMPRESSION,
- new ByteArrayInputStream(content));
- long deflateBestCompressionTime = new Date().getTime()
- - start.getTime();
- formatResult(totalBytes, deflateBestCompression,
- deflateBestCompressionTime);
- }
- /**
- * For calculating for properly formatting the results
- *
- * @param totalBytes totalBytes
- * @param transferredBytes Bytes transferred
- * @param elapsedTime total elapsed time
- */
- protected void formatResult(final long totalBytes,
- final long transferredBytes, final long elapsedTime) {
- long savedBytes = totalBytes - transferredBytes;
- System.err.printf("\t%.3fs, %.1f%% reduction (%d fewer bytes)%n",
- elapsedTime / 1000.0,
- 100 * (savedBytes / ((double) totalBytes)), savedBytes);
- }
- /**
- * An output stream that counts how many bytes are written, and otherwise
- * ignores output.
- */
- private static class CountingOutputStream extends OutputStream {
- // number of bytes output
- private long totalBytes = 0L;
- public long getTotalBytes() {
- return totalBytes;
- }
- @Override
- public void write(byte[] b) {
- totalBytes += b.length;
- }
- @Override
- public void write(byte[] b, int offset, int length) {
- totalBytes += length;
- }
- @Override
- public void write(int arg0) throws IOException {
- totalBytes++;
- }
- }
- /**
- * A main method for accessing tests using custom files.
- *
- * @param args
- * a list of files or directorys to include in compression
- * comparison.
- * @throws Exception if error occurs
- */
- public static void main(final String[] args) throws Exception {
- if (args.length == 0) {
- System.err.println("Usage: DeflateComparison FILE [FILE ...]");
- System.err
- .println("where FILE is a file or directory to include in comparison");
- System.exit(1);
- }
- Product product = new Product(new ProductId("test", "test", "test"));
- try {
- product.setTrackerURL(new URL("http://localhost/tracker"));
- } catch (Exception e) {
- // ignore
- }
- // treat all arguments as files or directories to be added as content
- for (String arg : args) {
- File file = new File(arg);
- if (!file.exists()) {
- System.err.println(file.getCanonicalPath() + " does not exist");
- System.exit(1);
- }
- if (file.isDirectory()) {
- product.getContents().putAll(
- FileContent.getDirectoryContents(file));
- } else {
- product.getContents()
- .put(file.getName(), new FileContent(file));
- }
- }
- // convert product to byte array in binary format
- System.err.println("Reading files into memory");
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- new ObjectProductSource(product)
- .streamTo(new BinaryProductHandler(baos));
- new DeflateComparison().testByteArray("product contents",
- baos.toByteArray());
- }
- }