Offload logbloom cache generation to computation executor, to avoid b… (#4530)

Signed-off-by: Fabio Di Fabio <fabio.difabio@consensys.net>
pull/5350/head
Fabio Di Fabio 2 years ago committed by GitHub
parent d9481c4de8
commit 78e566f2ef
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      CHANGELOG.md
  2. 12
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/query/cache/AutoTransactionLogBloomCachingService.java
  3. 42
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/query/cache/TransactionLogBloomCacher.java
  4. 13
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/query/cache/TransactionLogBloomCacherTest.java

@ -10,6 +10,7 @@
- Update most dependencies to latest version [#5269](https://github.com/hyperledger/besu/pull/5269)
- If jemalloc is used, print its version in the configuration overview [#4738](https://github.com/hyperledger/besu/pull/4738)
- Add metrics for accounts and storage reads (Flat database vs Merkle Patricia Trie) [#5315](https://github.com/hyperledger/besu/pull/5315)
- Offload LogBloom cache generation to computation executor, to avoid interfere with other scheduled tasks [#4530](https://github.com/hyperledger/besu/pull/4530)
### Bug Fixes

@ -77,7 +77,17 @@ public class AutoTransactionLogBloomCachingService {
transactionLogBloomCacher
.getScheduler()
.scheduleFutureTask(transactionLogBloomCacher::cacheAll, Duration.ofMinutes(1));
.scheduleFutureTask(
() ->
// run long tasks in the computation executor
transactionLogBloomCacher
.getScheduler()
.scheduleComputationTask(
() -> {
transactionLogBloomCacher.cacheAll();
return null;
}),
Duration.ofMinutes(1));
} catch (final IOException e) {
LOG.error("Unhandled caching exception.", e);
}

@ -284,25 +284,29 @@ public class TransactionLogBloomCacher {
final long blockNumber, final boolean overrideCacheCheck) {
if (!cachingStatus.isCaching()) {
scheduler.scheduleFutureTask(
() -> {
long currentSegment = (blockNumber / BLOCKS_PER_BLOOM_CACHE) - 1;
while (currentSegment >= 0) {
try {
if (overrideCacheCheck || !cachedSegments.getOrDefault(currentSegment, false)) {
final long startBlock = currentSegment * BLOCKS_PER_BLOOM_CACHE;
final File cacheFile = calculateCacheFileName(startBlock, cacheDir);
if (overrideCacheCheck
|| !cacheFile.isFile()
|| cacheFile.length() != EXPECTED_BLOOM_FILE_SIZE) {
generateLogBloomCache(startBlock, startBlock + BLOCKS_PER_BLOOM_CACHE);
}
cachedSegments.put(currentSegment, true);
}
} finally {
currentSegment--;
}
}
},
() ->
scheduler.scheduleComputationTask(
() -> {
long currentSegment = (blockNumber / BLOCKS_PER_BLOOM_CACHE) - 1;
while (currentSegment >= 0) {
try {
if (overrideCacheCheck
|| !cachedSegments.getOrDefault(currentSegment, false)) {
final long startBlock = currentSegment * BLOCKS_PER_BLOOM_CACHE;
final File cacheFile = calculateCacheFileName(startBlock, cacheDir);
if (overrideCacheCheck
|| !cacheFile.isFile()
|| cacheFile.length() != EXPECTED_BLOOM_FILE_SIZE) {
generateLogBloomCache(startBlock, startBlock + BLOCKS_PER_BLOOM_CACHE);
}
cachedSegments.put(currentSegment, true);
}
} finally {
currentSegment--;
}
}
return null;
}),
Duration.ofSeconds(1));
}
}

@ -40,6 +40,7 @@ import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.function.Supplier;
import org.apache.tuweni.bytes.Bytes;
import org.junit.Before;
@ -65,7 +66,7 @@ public class TransactionLogBloomCacherTest {
private TransactionLogBloomCacher transactionLogBloomCacher;
@BeforeClass
public static void setupClass() throws IOException {
public static void setupClass() {
final Address testAddress = Address.fromHexString("0x123456");
final Bytes testMessage = Bytes.fromHexString("0x9876");
final Log testLog = new Log(testAddress, testMessage, List.of());
@ -106,10 +107,16 @@ public class TransactionLogBloomCacherTest {
new MainnetBlockHeaderFunctions());
testHash = fakeHeader.getHash();
when(blockchain.getBlockHeader(anyLong())).thenReturn(Optional.of(fakeHeader));
when(scheduler.scheduleFutureTask(any(Runnable.class), any(Duration.class)))
when(scheduler.scheduleFutureTask(any(Supplier.class), any(Duration.class)))
.thenAnswer(
invocation -> {
invocation.getArgument(0, Runnable.class).run();
invocation.getArgument(0, Supplier.class).get();
return null;
});
when(scheduler.scheduleComputationTask(any(Supplier.class)))
.thenAnswer(
invocation -> {
invocation.getArgument(0, Supplier.class).get();
return null;
});
transactionLogBloomCacher =

Loading…
Cancel
Save