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.security.NoSuchAlgorithmException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.concurrent.Semaphore;
|
||||||
|
|
||||||
import static ch.dissem.bitmessage.utils.Bytes.inc;
|
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.
|
* A POW engine using all available CPU cores.
|
||||||
*/
|
*/
|
||||||
public class MultiThreadedPOWEngine implements ProofOfWorkEngine {
|
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
|
@Override
|
||||||
public void calculateNonce(byte[] initialHash, byte[] target, Callback callback) {
|
public void calculateNonce(byte[] initialHash, byte[] target, Callback callback) {
|
||||||
|
try {
|
||||||
|
semaphore.acquire();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
callback = new CallbackWrapper(callback);
|
callback = new CallbackWrapper(callback);
|
||||||
int cores = Runtime.getRuntime().availableProcessors();
|
int cores = Runtime.getRuntime().availableProcessors();
|
||||||
if (cores > 255) cores = 255;
|
if (cores > 255) cores = 255;
|
||||||
LOG.info("Doing POW using " + cores + " cores");
|
LOG.info("Doing POW using " + cores + " cores");
|
||||||
long time = System.currentTimeMillis();
|
|
||||||
List<Worker> workers = new ArrayList<>(cores);
|
List<Worker> workers = new ArrayList<>(cores);
|
||||||
for (int i = 0; i < cores; i++) {
|
for (int i = 0; i < cores; i++) {
|
||||||
Worker w = new Worker(workers, (byte) cores, i, initialHash, target, callback);
|
Worker w = new Worker(workers, (byte) cores, i, initialHash, target, callback);
|
||||||
@ -89,6 +103,7 @@ public class MultiThreadedPOWEngine implements ProofOfWorkEngine {
|
|||||||
try {
|
try {
|
||||||
callback.onNonceCalculated(nonce);
|
callback.onNonceCalculated(nonce);
|
||||||
} finally {
|
} finally {
|
||||||
|
semaphore.release();
|
||||||
for (Worker w : workers) {
|
for (Worker w : workers) {
|
||||||
w.interrupt();
|
w.interrupt();
|
||||||
}
|
}
|
||||||
|
@ -25,12 +25,12 @@ import static ch.dissem.bitmessage.utils.Singleton.security;
|
|||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
public class ProofOfWorkEngineTest extends TestBase {
|
public class ProofOfWorkEngineTest extends TestBase {
|
||||||
@Test
|
@Test(timeout = 90_000)
|
||||||
public void testSimplePOWEngine() throws InterruptedException {
|
public void testSimplePOWEngine() throws InterruptedException {
|
||||||
testPOW(new SimplePOWEngine());
|
testPOW(new SimplePOWEngine());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test(timeout = 90_000)
|
||||||
public void testThreadedPOWEngine() throws InterruptedException {
|
public void testThreadedPOWEngine() throws InterruptedException {
|
||||||
testPOW(new MultiThreadedPOWEngine());
|
testPOW(new MultiThreadedPOWEngine());
|
||||||
}
|
}
|
||||||
@ -49,8 +49,28 @@ public class ProofOfWorkEngineTest extends TestBase {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
byte[] nonce = waiter.waitForValue();
|
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));
|
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