RocksDB Metrics (#531)

* Measure read/get, write/put, remove, and commit latencies
* Measure rollback count (latency seemed a bit much)
Danno Ferrin 6 years ago committed by GitHub
parent bd9ffac033
commit eab908441d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      ethereum/core/build.gradle
  2. 4
      ethereum/core/src/jmh/java/tech/pegasys/pantheon/ethereum/vm/operations/OperationBenchmarkHelper.java
  3. 7
      ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/storage/keyvalue/RocksDbStorageProvider.java
  4. 3
      metrics/src/main/java/tech/pegasys/pantheon/metrics/MetricCategory.java
  5. 2
      pantheon/src/main/java/tech/pegasys/pantheon/cli/PantheonControllerBuilder.java
  6. 2
      pantheon/src/test/java/tech/pegasys/pantheon/RunnerTest.java
  7. 1
      services/kvstore/build.gradle
  8. 52
      services/kvstore/src/main/java/tech/pegasys/pantheon/services/kvstore/RocksDbKeyValueStorage.java
  9. 4
      services/kvstore/src/test/java/tech/pegasys/pantheon/services/kvstore/RocksDbKeyValueStorageTest.java

@ -67,6 +67,7 @@ dependencies {
jmhImplementation project(path: ':ethereum:core', configuration: 'testSupportArtifacts') jmhImplementation project(path: ':ethereum:core', configuration: 'testSupportArtifacts')
jmhImplementation project(':ethereum:rlp') jmhImplementation project(':ethereum:rlp')
jmhImplementation project(':ethereum:trie') jmhImplementation project(':ethereum:trie')
jmhImplementation project(':metrics')
jmhImplementation project(':services:kvstore') jmhImplementation project(':services:kvstore')
jmhImplementation project(':util') jmhImplementation project(':util')

@ -21,6 +21,7 @@ import tech.pegasys.pantheon.ethereum.core.BlockHeaderTestFixture;
import tech.pegasys.pantheon.ethereum.core.ExecutionContextTestFixture; import tech.pegasys.pantheon.ethereum.core.ExecutionContextTestFixture;
import tech.pegasys.pantheon.ethereum.core.MessageFrameTestFixture; import tech.pegasys.pantheon.ethereum.core.MessageFrameTestFixture;
import tech.pegasys.pantheon.ethereum.vm.MessageFrame; import tech.pegasys.pantheon.ethereum.vm.MessageFrame;
import tech.pegasys.pantheon.metrics.noop.NoOpMetricsSystem;
import tech.pegasys.pantheon.services.kvstore.KeyValueStorage; import tech.pegasys.pantheon.services.kvstore.KeyValueStorage;
import tech.pegasys.pantheon.services.kvstore.RocksDbKeyValueStorage; import tech.pegasys.pantheon.services.kvstore.RocksDbKeyValueStorage;
import tech.pegasys.pantheon.util.uint.UInt256; import tech.pegasys.pantheon.util.uint.UInt256;
@ -49,7 +50,8 @@ public class OperationBenchmarkHelper {
public static OperationBenchmarkHelper create() throws IOException { public static OperationBenchmarkHelper create() throws IOException {
final Path storageDirectory = Files.createTempDirectory("benchmark"); final Path storageDirectory = Files.createTempDirectory("benchmark");
final KeyValueStorage keyValueStorage = RocksDbKeyValueStorage.create(storageDirectory); final KeyValueStorage keyValueStorage =
RocksDbKeyValueStorage.create(storageDirectory, new NoOpMetricsSystem());
final ExecutionContextTestFixture executionContext = final ExecutionContextTestFixture executionContext =
ExecutionContextTestFixture.builder().keyValueStorage(keyValueStorage).build(); ExecutionContextTestFixture.builder().keyValueStorage(keyValueStorage).build();

@ -13,6 +13,7 @@
package tech.pegasys.pantheon.ethereum.storage.keyvalue; package tech.pegasys.pantheon.ethereum.storage.keyvalue;
import tech.pegasys.pantheon.ethereum.storage.StorageProvider; import tech.pegasys.pantheon.ethereum.storage.StorageProvider;
import tech.pegasys.pantheon.metrics.MetricsSystem;
import tech.pegasys.pantheon.services.kvstore.KeyValueStorage; import tech.pegasys.pantheon.services.kvstore.KeyValueStorage;
import tech.pegasys.pantheon.services.kvstore.RocksDbKeyValueStorage; import tech.pegasys.pantheon.services.kvstore.RocksDbKeyValueStorage;
@ -22,8 +23,10 @@ import java.nio.file.Path;
public class RocksDbStorageProvider { public class RocksDbStorageProvider {
public static StorageProvider create(final Path databaseDir) throws IOException { public static StorageProvider create(final Path databaseDir, final MetricsSystem metricsSystem)
final KeyValueStorage kv = RocksDbKeyValueStorage.create(Files.createDirectories(databaseDir)); throws IOException {
final KeyValueStorage kv =
RocksDbKeyValueStorage.create(Files.createDirectories(databaseDir), metricsSystem);
return new KeyValueStorageProvider(kv); return new KeyValueStorageProvider(kv);
} }
} }

@ -19,7 +19,8 @@ public enum MetricCategory {
PROCESS("process", false), PROCESS("process", false),
BLOCKCHAIN("blockchain"), BLOCKCHAIN("blockchain"),
SYNCHRONIZER("synchronizer"), SYNCHRONIZER("synchronizer"),
NETWORK("network"); NETWORK("network"),
ROCKSDB("rocksdb");
private final String name; private final String name;
private final boolean pantheonSpecific; private final boolean pantheonSpecific;

@ -88,7 +88,7 @@ public class PantheonControllerBuilder {
final KeyPair nodeKeys = loadKeyPair(nodePrivateKeyFile); final KeyPair nodeKeys = loadKeyPair(nodePrivateKeyFile);
final StorageProvider storageProvider = final StorageProvider storageProvider =
RocksDbStorageProvider.create(homePath.resolve(DATABASE_PATH)); RocksDbStorageProvider.create(homePath.resolve(DATABASE_PATH), metricsSystem);
if (devMode) { if (devMode) {
final GenesisConfigFile genesisConfig = GenesisConfigFile.development(); final GenesisConfigFile genesisConfig = GenesisConfigFile.development();
return MainnetPantheonController.init( return MainnetPantheonController.init(

@ -250,7 +250,7 @@ public final class RunnerTest {
} }
private StorageProvider createKeyValueStorageProvider(final Path dbAhead) throws IOException { private StorageProvider createKeyValueStorageProvider(final Path dbAhead) throws IOException {
return RocksDbStorageProvider.create(dbAhead); return RocksDbStorageProvider.create(dbAhead, new NoOpMetricsSystem());
} }
private JsonRpcConfiguration jsonRpcConfiguration() { private JsonRpcConfiguration jsonRpcConfiguration() {

@ -27,6 +27,7 @@ jar {
dependencies { dependencies {
api project(':util') api project(':util')
implementation project(':metrics')
implementation 'org.apache.logging.log4j:log4j-api' implementation 'org.apache.logging.log4j:log4j-api'
implementation 'com.google.guava:guava' implementation 'com.google.guava:guava'

@ -12,6 +12,10 @@
*/ */
package tech.pegasys.pantheon.services.kvstore; package tech.pegasys.pantheon.services.kvstore;
import tech.pegasys.pantheon.metrics.Counter;
import tech.pegasys.pantheon.metrics.MetricCategory;
import tech.pegasys.pantheon.metrics.MetricsSystem;
import tech.pegasys.pantheon.metrics.OperationTimer;
import tech.pegasys.pantheon.util.bytes.BytesValue; import tech.pegasys.pantheon.util.bytes.BytesValue;
import java.io.Closeable; import java.io.Closeable;
@ -44,19 +48,47 @@ public class RocksDbKeyValueStorage implements KeyValueStorage, Closeable {
private final TransactionDB db; private final TransactionDB db;
private final AtomicBoolean closed = new AtomicBoolean(false); private final AtomicBoolean closed = new AtomicBoolean(false);
private final OperationTimer readLatency;
private final OperationTimer removeLatency;
private final OperationTimer writeLatency;
private final OperationTimer commitLatency;
private final Counter rollbackCount;
static { static {
RocksDB.loadLibrary(); RocksDB.loadLibrary();
} }
public static KeyValueStorage create(final Path storageDirectory) throws StorageException { public static KeyValueStorage create(
return new RocksDbKeyValueStorage(storageDirectory); final Path storageDirectory, final MetricsSystem metricsSystem) throws StorageException {
return new RocksDbKeyValueStorage(storageDirectory, metricsSystem);
} }
private RocksDbKeyValueStorage(final Path storageDirectory) { private RocksDbKeyValueStorage(final Path storageDirectory, final MetricsSystem metricsSystem) {
try { try {
options = new Options().setCreateIfMissing(true); options = new Options().setCreateIfMissing(true);
txOptions = new TransactionDBOptions(); txOptions = new TransactionDBOptions();
db = TransactionDB.open(options, txOptions, storageDirectory.toString()); db = TransactionDB.open(options, txOptions, storageDirectory.toString());
readLatency =
metricsSystem.createTimer(
MetricCategory.ROCKSDB, "read_latency_seconds", "Latency for read from RocksDB.");
removeLatency =
metricsSystem.createTimer(
MetricCategory.ROCKSDB,
"remove_latency_seconds",
"Latency of remove requests from RocksDB.");
writeLatency =
metricsSystem.createTimer(
MetricCategory.ROCKSDB, "write_latency_seconds", "Latency for write to RocksDB.");
commitLatency =
metricsSystem.createTimer(
MetricCategory.ROCKSDB, "commit_latency_seconds", "Latency for commits to RocksDB.");
rollbackCount =
metricsSystem.createCounter(
MetricCategory.ROCKSDB,
"rollback_count",
"Number of RocksDB transactions rolled back.");
} catch (final RocksDBException e) { } catch (final RocksDBException e) {
throw new StorageException(e); throw new StorageException(e);
} }
@ -65,7 +97,8 @@ public class RocksDbKeyValueStorage implements KeyValueStorage, Closeable {
@Override @Override
public Optional<BytesValue> get(final BytesValue key) throws StorageException { public Optional<BytesValue> get(final BytesValue key) throws StorageException {
throwIfClosed(); throwIfClosed();
try {
try (final OperationTimer.TimingContext ignored = readLatency.startTimer()) {
return Optional.ofNullable(db.get(key.extractArray())).map(BytesValue::wrap); return Optional.ofNullable(db.get(key.extractArray())).map(BytesValue::wrap);
} catch (final RocksDBException e) { } catch (final RocksDBException e) {
throw new StorageException(e); throw new StorageException(e);
@ -143,7 +176,7 @@ public class RocksDbKeyValueStorage implements KeyValueStorage, Closeable {
return entry; return entry;
} }
public Stream<Entry> toStream() { Stream<Entry> toStream() {
final Spliterator<Entry> split = final Spliterator<Entry> split =
Spliterators.spliteratorUnknownSize( Spliterators.spliteratorUnknownSize(
this, Spliterator.IMMUTABLE | Spliterator.DISTINCT | Spliterator.NONNULL); this, Spliterator.IMMUTABLE | Spliterator.DISTINCT | Spliterator.NONNULL);
@ -158,7 +191,7 @@ public class RocksDbKeyValueStorage implements KeyValueStorage, Closeable {
} }
} }
private static class RocksDbTransaction extends AbstractTransaction { private class RocksDbTransaction extends AbstractTransaction {
private final org.rocksdb.Transaction innerTx; private final org.rocksdb.Transaction innerTx;
private final WriteOptions options; private final WriteOptions options;
@ -169,7 +202,7 @@ public class RocksDbKeyValueStorage implements KeyValueStorage, Closeable {
@Override @Override
protected void doPut(final BytesValue key, final BytesValue value) { protected void doPut(final BytesValue key, final BytesValue value) {
try { try (final OperationTimer.TimingContext ignored = writeLatency.startTimer()) {
innerTx.put(key.extractArray(), value.extractArray()); innerTx.put(key.extractArray(), value.extractArray());
} catch (final RocksDBException e) { } catch (final RocksDBException e) {
throw new StorageException(e); throw new StorageException(e);
@ -178,7 +211,7 @@ public class RocksDbKeyValueStorage implements KeyValueStorage, Closeable {
@Override @Override
protected void doRemove(final BytesValue key) { protected void doRemove(final BytesValue key) {
try { try (final OperationTimer.TimingContext ignored = removeLatency.startTimer()) {
innerTx.delete(key.extractArray()); innerTx.delete(key.extractArray());
} catch (final RocksDBException e) { } catch (final RocksDBException e) {
throw new StorageException(e); throw new StorageException(e);
@ -187,7 +220,7 @@ public class RocksDbKeyValueStorage implements KeyValueStorage, Closeable {
@Override @Override
protected void doCommit() throws StorageException { protected void doCommit() throws StorageException {
try { try (final OperationTimer.TimingContext ignored = commitLatency.startTimer()) {
innerTx.commit(); innerTx.commit();
} catch (final RocksDBException e) { } catch (final RocksDBException e) {
throw new StorageException(e); throw new StorageException(e);
@ -200,6 +233,7 @@ public class RocksDbKeyValueStorage implements KeyValueStorage, Closeable {
protected void doRollback() { protected void doRollback() {
try { try {
innerTx.rollback(); innerTx.rollback();
rollbackCount.inc();
} catch (final RocksDBException e) { } catch (final RocksDBException e) {
throw new StorageException(e); throw new StorageException(e);
} finally { } finally {

@ -12,6 +12,8 @@
*/ */
package tech.pegasys.pantheon.services.kvstore; package tech.pegasys.pantheon.services.kvstore;
import tech.pegasys.pantheon.metrics.noop.NoOpMetricsSystem;
import org.junit.Rule; import org.junit.Rule;
import org.junit.rules.TemporaryFolder; import org.junit.rules.TemporaryFolder;
@ -21,6 +23,6 @@ public class RocksDbKeyValueStorageTest extends AbstractKeyValueStorageTest {
@Override @Override
protected KeyValueStorage createStore() throws Exception { protected KeyValueStorage createStore() throws Exception {
return RocksDbKeyValueStorage.create(folder.newFolder().toPath()); return RocksDbKeyValueStorage.create(folder.newFolder().toPath(), new NoOpMetricsSystem());
} }
} }

Loading…
Cancel
Save