Fixed POWEngine and improved test.
(Locks can't be released from a different thread, we need to use a semaphore)
This commit is contained in:
parent
36fe780766
commit
b496f81b20
@ -24,6 +24,7 @@ import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Semaphore;
|
||||
|
||||
import static ch.dissem.bitmessage.utils.Bytes.inc;
|
||||
|
||||
@ -31,15 +32,28 @@ import static ch.dissem.bitmessage.utils.Bytes.inc;
|
||||
* A POW engine using all available CPU cores.
|
||||
*/
|
||||
public class MultiThreadedPOWEngine implements ProofOfWorkEngine {
|
||||
private static Logger LOG = LoggerFactory.getLogger(MultiThreadedPOWEngine.class);
|
||||
private static final Logger LOG = LoggerFactory.getLogger(MultiThreadedPOWEngine.class);
|
||||
private static final Semaphore semaphore = new Semaphore(1, true);
|
||||
|
||||
/**
|
||||
* Although it has a callback, this method will block until all pending nonce calculations are done. (It gets very
|
||||
* inefficient if multiple nonce are calculated at the same time.
|
||||
*
|
||||
* @param initialHash the SHA-512 hash of the object to send, sans nonce
|
||||
* @param target the target, representing an unsigned long
|
||||
* @param callback called with the calculated nonce as argument. The ProofOfWorkEngine implementation must make
|
||||
*/
|
||||
@Override
|
||||
public void calculateNonce(byte[] initialHash, byte[] target, Callback callback) {
|
||||
try {
|
||||
semaphore.acquire();
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
callback = new CallbackWrapper(callback);
|
||||
int cores = Runtime.getRuntime().availableProcessors();
|
||||
if (cores > 255) cores = 255;
|
||||
LOG.info("Doing POW using " + cores + " cores");
|
||||
long time = System.currentTimeMillis();
|
||||
List<Worker> workers = new ArrayList<>(cores);
|
||||
for (int i = 0; i < cores; i++) {
|
||||
Worker w = new Worker(workers, (byte) cores, i, initialHash, target, callback);
|
||||
@ -89,6 +103,7 @@ public class MultiThreadedPOWEngine implements ProofOfWorkEngine {
|
||||
try {
|
||||
callback.onNonceCalculated(nonce);
|
||||
} finally {
|
||||
semaphore.release();
|
||||
for (Worker w : workers) {
|
||||
w.interrupt();
|
||||
}
|
||||
|
@ -25,12 +25,12 @@ import static ch.dissem.bitmessage.utils.Singleton.security;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class ProofOfWorkEngineTest extends TestBase {
|
||||
@Test
|
||||
@Test(timeout = 90_000)
|
||||
public void testSimplePOWEngine() throws InterruptedException {
|
||||
testPOW(new SimplePOWEngine());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Test(timeout = 90_000)
|
||||
public void testThreadedPOWEngine() throws InterruptedException {
|
||||
testPOW(new MultiThreadedPOWEngine());
|
||||
}
|
||||
@ -49,8 +49,28 @@ public class ProofOfWorkEngineTest extends TestBase {
|
||||
}
|
||||
});
|
||||
byte[] nonce = waiter.waitForValue();
|
||||
System.out.println("Calculating nonce took " + (System.currentTimeMillis() - time) + "ms");
|
||||
time = System.currentTimeMillis() - time;
|
||||
System.out.println("Calculating nonce took " + time + "ms");
|
||||
assertTrue(Bytes.lt(security().doubleSha512(nonce, initialHash), target, 8));
|
||||
|
||||
// Let's add a second (shorter) run to find possible multi threading issues
|
||||
long time2 = System.currentTimeMillis();
|
||||
byte[] initialHash2 = security().sha512(new byte[]{1, 3, 6, 5});
|
||||
byte[] target2 = {0, -1, -1, -1, -1, -1, -1, -1};
|
||||
|
||||
final CallbackWaiter<byte[]> waiter2 = new CallbackWaiter<>();
|
||||
engine.calculateNonce(initialHash2, target2,
|
||||
new ProofOfWorkEngine.Callback() {
|
||||
@Override
|
||||
public void onNonceCalculated(byte[] nonce) {
|
||||
waiter2.setValue(nonce);
|
||||
}
|
||||
});
|
||||
byte[] nonce2 = waiter2.waitForValue();
|
||||
time2 = System.currentTimeMillis() - time2;
|
||||
System.out.println("Calculating nonce took " + time2 + "ms");
|
||||
assertTrue(Bytes.lt(security().doubleSha512(nonce2, initialHash2), target2, 8));
|
||||
assertTrue("Second nonce must be quicker to find", time > time2);
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user