Parallelize digest(2).txt computation.
Ad-hoc test on MBP with four-core i7 takes us from: digest.txt: Computed digests [rsrcs=344, time=1055ms] digest2.txt: Computed digests [rsrcs=344, time=2068ms] to digest.txt: Computed digests [rsrcs=344, time=328ms] digest2.txt: Computed digests [rsrcs=344, time=832ms]
This commit is contained in:
@@ -5,15 +5,11 @@
|
|||||||
|
|
||||||
package com.threerings.getdown.data;
|
package com.threerings.getdown.data;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.*;
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.OutputStreamWriter;
|
|
||||||
import java.io.PrintWriter;
|
|
||||||
import java.security.MessageDigest;
|
import java.security.MessageDigest;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.util.HashMap;
|
import java.util.*;
|
||||||
import java.util.List;
|
import java.util.concurrent.*;
|
||||||
|
|
||||||
import com.samskivert.io.StreamUtil;
|
import com.samskivert.io.StreamUtil;
|
||||||
import com.samskivert.text.MessageUtil;
|
import com.samskivert.text.MessageUtil;
|
||||||
@@ -51,27 +47,58 @@ public class Digest
|
|||||||
public static void createDigest (int version, List<Resource> resources, File output)
|
public static void createDigest (int version, List<Resource> resources, File output)
|
||||||
throws IOException
|
throws IOException
|
||||||
{
|
{
|
||||||
MessageDigest md = getMessageDigest(version);
|
// first compute the digests for all the resources in parallel
|
||||||
|
Executor exec = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
|
||||||
|
final Map<Resource, String> digests = new ConcurrentHashMap<Resource, String>();
|
||||||
|
final BlockingQueue<Object> completed = new LinkedBlockingQueue<Object>();
|
||||||
|
final int fversion = version;
|
||||||
|
|
||||||
|
long start = System.currentTimeMillis();
|
||||||
|
|
||||||
|
Set<Resource> pending = new HashSet<Resource>(resources);
|
||||||
|
for (final Resource rsrc : resources) {
|
||||||
|
exec.execute(new Runnable() {
|
||||||
|
public void run () {
|
||||||
|
try {
|
||||||
|
MessageDigest md = getMessageDigest(fversion);
|
||||||
|
digests.put(rsrc, rsrc.computeDigest(fversion, md, null));
|
||||||
|
completed.add(rsrc);
|
||||||
|
} catch (Throwable t) {
|
||||||
|
completed.add(new IOException("Error computing digest for: " + rsrc).
|
||||||
|
initCause(t));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
while (pending.size() > 0) {
|
||||||
|
Object done = completed.poll(600, TimeUnit.SECONDS);
|
||||||
|
if (done instanceof IOException) {
|
||||||
|
throw (IOException)done;
|
||||||
|
} else if (done instanceof Resource) {
|
||||||
|
pending.remove((Resource)done);
|
||||||
|
} else {
|
||||||
|
throw new AssertionError("What is this? " + done);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (InterruptedException ie) {
|
||||||
|
throw new IOException("Timeout computing digests. Wow.");
|
||||||
|
}
|
||||||
|
|
||||||
StringBuilder data = new StringBuilder();
|
StringBuilder data = new StringBuilder();
|
||||||
PrintWriter pout = null;
|
PrintWriter pout = null;
|
||||||
try {
|
try {
|
||||||
pout = new PrintWriter(new OutputStreamWriter(new FileOutputStream(output), "UTF-8"));
|
pout = new PrintWriter(new OutputStreamWriter(new FileOutputStream(output), "UTF-8"));
|
||||||
|
|
||||||
// compute and append the digest of each resource in the list
|
// compute and append the digest of each resource in the list
|
||||||
for (Resource rsrc : resources) {
|
for (Resource rsrc : resources) {
|
||||||
String path = rsrc.getPath();
|
String path = rsrc.getPath();
|
||||||
try {
|
String digest = digests.get(rsrc);
|
||||||
String digest = rsrc.computeDigest(version, md, null);
|
|
||||||
note(data, path, digest);
|
note(data, path, digest);
|
||||||
pout.println(path + " = " + digest);
|
pout.println(path + " = " + digest);
|
||||||
} catch (Throwable t) {
|
|
||||||
throw (IOException) new IOException(
|
|
||||||
"Error computing digest for: " + rsrc).initCause(t);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// finally compute and append the digest for the file contents
|
// finally compute and append the digest for the file contents
|
||||||
md.reset();
|
MessageDigest md = getMessageDigest(version);
|
||||||
byte[] contents = data.toString().getBytes("UTF-8");
|
byte[] contents = data.toString().getBytes("UTF-8");
|
||||||
String filename = digestFile(version);
|
String filename = digestFile(version);
|
||||||
pout.println(filename + " = " + StringUtil.hexlate(md.digest(contents)));
|
pout.println(filename + " = " + StringUtil.hexlate(md.digest(contents)));
|
||||||
@@ -79,6 +106,9 @@ public class Digest
|
|||||||
} finally {
|
} finally {
|
||||||
StreamUtil.close(pout);
|
StreamUtil.close(pout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
long elapsed = System.currentTimeMillis() - start;
|
||||||
|
log.debug("Computed digests [rsrcs=" + resources.size() + ", time=" + elapsed + "ms]");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user