Skip to content

Commit 5a96e5d

Browse files
committed
feat(db): improve performance for db query
1. add cache for db
1 parent 2d88f6e commit 5a96e5d

File tree

17 files changed

+382
-74
lines changed

17 files changed

+382
-74
lines changed

chainbase/src/main/java/org/tron/core/db2/common/DB.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ public interface DB<K, V> extends Iterable<Map.Entry<K, V>>, Instance<DB<K, V>>
1515

1616
void remove(K k);
1717

18-
Iterator iterator();
18+
Iterator<Map.Entry<K, V>> iterator();
1919

2020
void close();
2121

chainbase/src/main/java/org/tron/core/db2/core/AbstractSnapshot.java

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@ public abstract class AbstractSnapshot<K, V> implements Snapshot {
1515

1616
protected WeakReference<Snapshot> next;
1717

18-
protected boolean isOptimized;
19-
2018
@Override
2119
public Snapshot advance() {
2220
return new SnapshotImpl(this);
@@ -36,9 +34,4 @@ public void setNext(Snapshot next) {
3634
public String getDbName() {
3735
return db.getDbName();
3836
}
39-
40-
@Override
41-
public boolean isOptimized(){
42-
return isOptimized;
43-
}
4437
}

chainbase/src/main/java/org/tron/core/db2/core/Snapshot.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,4 @@ static boolean isImpl(Snapshot snapshot) {
4646
void updateSolidity();
4747

4848
String getDbName();
49-
50-
boolean isOptimized();
5149
}

chainbase/src/main/java/org/tron/core/db2/core/SnapshotImpl.java

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -30,16 +30,6 @@ public class SnapshotImpl extends AbstractSnapshot<Key, Value> {
3030
}
3131
previous = snapshot;
3232
snapshot.setNext(this);
33-
// inherit
34-
isOptimized = snapshot.isOptimized();
35-
// merge for DynamicPropertiesStore,about 100 keys
36-
if (isOptimized) {
37-
if (root == previous ){
38-
Streams.stream(root.iterator()).forEach( e -> put(e.getKey(),e.getValue()));
39-
}else {
40-
merge(previous);
41-
}
42-
}
4333
}
4434

4535
@Override
@@ -50,10 +40,6 @@ public byte[] get(byte[] key) {
5040
private byte[] get(Snapshot head, byte[] key) {
5141
Snapshot snapshot = head;
5242
Value value;
53-
if (isOptimized) {
54-
value = db.get(Key.of(key));
55-
return value == null ? null: value.getBytes();
56-
}
5743
while (Snapshot.isImpl(snapshot)) {
5844
if ((value = ((SnapshotImpl) snapshot).db.get(Key.of(key))) != null) {
5945
return value.getBytes();

chainbase/src/main/java/org/tron/core/db2/core/SnapshotRoot.java

Lines changed: 53 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
11
package org.tron.core.db2.core;
22

3-
import ch.qos.logback.core.encoder.ByteArrayUtil;
43
import com.google.common.collect.Maps;
54
import com.google.common.collect.Streams;
65
import java.util.HashMap;
76
import java.util.Iterator;
87
import java.util.List;
98
import java.util.Map;
9+
import java.util.Objects;
1010
import java.util.stream.Collectors;
1111
import lombok.Getter;
12+
import org.tron.common.cache.CacheManager;
13+
import org.tron.common.cache.TronCache;
14+
import org.tron.common.parameter.CommonParameter;
1215
import org.tron.common.utils.ByteArray;
1316
import org.tron.core.ChainBaseManager;
1417
import org.tron.core.capsule.AccountCapsule;
@@ -23,11 +26,17 @@ public class SnapshotRoot extends AbstractSnapshot<byte[], byte[]> {
2326
private Snapshot solidity;
2427
private boolean isAccountDB;
2528

29+
private TronCache<WrappedByteArray, WrappedByteArray> cache;
30+
private static final List<String> CACHE_DBS = CommonParameter.getInstance()
31+
.getStorage().getCacheDbs();
32+
2633
public SnapshotRoot(DB<byte[], byte[]> db) {
2734
this.db = db;
2835
solidity = this;
29-
isOptimized = "properties".equalsIgnoreCase(db.getDbName());
3036
isAccountDB = "account".equalsIgnoreCase(db.getDbName());
37+
if (CACHE_DBS.contains(this.db.getDbName())) {
38+
this.cache = CacheManager.allocate(this.db.getDbName());
39+
}
3140
}
3241

3342
private boolean needOptAsset() {
@@ -37,11 +46,18 @@ private boolean needOptAsset() {
3746

3847
@Override
3948
public byte[] get(byte[] key) {
40-
return db.get(key);
49+
WrappedByteArray cache = getCache(key);
50+
if (cache != null) {
51+
return cache.getBytes();
52+
}
53+
byte[] value = db.get(key);
54+
putCache(key, value);
55+
return value;
4156
}
4257

4358
@Override
4459
public void put(byte[] key, byte[] value) {
60+
byte[] v = value;
4561
if (needOptAsset()) {
4662
if (ByteArray.isEmpty(value)) {
4763
remove(key);
@@ -56,10 +72,10 @@ public void put(byte[] key, byte[] value) {
5672
}
5773
assetStore.putAccount(item.getInstance());
5874
item.clearAsset();
59-
db.put(key, item.getData());
60-
} else {
61-
db.put(key, value);
75+
v = item.getData();
6276
}
77+
db.put(key, v);
78+
putCache(key, v);
6379
}
6480

6581
@Override
@@ -68,6 +84,7 @@ public void remove(byte[] key) {
6884
ChainBaseManager.getInstance().getAccountAssetStore().deleteAccount(key);
6985
}
7086
db.remove(key);
87+
putCache(key, null);
7188
}
7289

7390
@Override
@@ -81,6 +98,7 @@ public void merge(Snapshot from) {
8198
processAccount(batch);
8299
} else {
83100
((Flusher) db).flush(batch);
101+
putCache(batch);
84102
}
85103
}
86104

@@ -97,6 +115,7 @@ public void merge(List<Snapshot> snapshots) {
97115
processAccount(batch);
98116
} else {
99117
((Flusher) db).flush(batch);
118+
putCache(batch);
100119
}
101120
}
102121

@@ -120,11 +139,37 @@ private void processAccount(Map<WrappedByteArray, WrappedByteArray> batch) {
120139
}
121140
});
122141
((Flusher) db).flush(accounts);
142+
putCache(accounts);
123143
if (assets.size() > 0) {
124144
assetStore.updateByBatch(AccountAssetStore.convert(assets));
125145
}
126146
}
127147

148+
private boolean cached() {
149+
return Objects.nonNull(this.cache);
150+
}
151+
152+
private void putCache(byte[] key, byte[] value) {
153+
if (cached()) {
154+
cache.put(WrappedByteArray.of(key), WrappedByteArray.of(value));
155+
}
156+
}
157+
158+
private void putCache(Map<WrappedByteArray, WrappedByteArray> values) {
159+
if (cached()) {
160+
values.forEach(cache::put);
161+
}
162+
}
163+
164+
private WrappedByteArray getCache(byte[] key) {
165+
if (cached()) {
166+
return cache.getIfPresent(WrappedByteArray.of(key));
167+
}
168+
return null;
169+
}
170+
171+
// second cache
172+
128173
@Override
129174
public Snapshot retreat() {
130175
return this;
@@ -142,11 +187,13 @@ public Iterator<Map.Entry<byte[], byte[]>> iterator() {
142187

143188
@Override
144189
public void close() {
190+
CacheManager.release(this.getDbName());
145191
((Flusher) db).close();
146192
}
147193

148194
@Override
149195
public void reset() {
196+
CacheManager.release(this.getDbName());
150197
((Flusher) db).reset();
151198
}
152199

chainbase/src/main/java/org/tron/core/service/MortgageService.java

Lines changed: 9 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,9 @@
11
package org.tron.core.service;
22

33
import com.google.protobuf.ByteString;
4-
54
import java.math.BigInteger;
6-
import java.util.ArrayList;
75
import java.util.Comparator;
8-
import java.util.HashMap;
96
import java.util.List;
10-
import java.util.Map;
11-
127
import lombok.Getter;
138
import lombok.Setter;
149
import lombok.extern.slf4j.Slf4j;
@@ -18,7 +13,6 @@
1813
import org.tron.common.utils.StringUtil;
1914
import org.tron.core.capsule.AccountCapsule;
2015
import org.tron.core.capsule.WitnessCapsule;
21-
import org.tron.core.config.Parameter.ChainConstant;
2216
import org.tron.core.exception.BalanceInsufficientException;
2317
import org.tron.core.store.AccountStore;
2418
import org.tron.core.store.DelegationStore;
@@ -52,31 +46,17 @@ public void initStore(WitnessStore witnessStore, DelegationStore delegationStore
5246
}
5347

5448
public void payStandbyWitness() {
55-
List<WitnessCapsule> witnessCapsules = witnessStore.getAllWitnesses();
56-
Map<ByteString, WitnessCapsule> witnessCapsuleMap = new HashMap<>();
57-
List<ByteString> witnessAddressList = new ArrayList<>();
58-
for (WitnessCapsule witnessCapsule : witnessCapsules) {
59-
witnessAddressList.add(witnessCapsule.getAddress());
60-
witnessCapsuleMap.put(witnessCapsule.getAddress(), witnessCapsule);
61-
}
62-
witnessAddressList.sort(Comparator.comparingLong((ByteString b) -> witnessCapsuleMap.get(b).getVoteCount())
63-
.reversed().thenComparing(Comparator.comparingInt(ByteString::hashCode).reversed()));
64-
if (witnessAddressList.size() > ChainConstant.WITNESS_STANDBY_LENGTH) {
65-
witnessAddressList = witnessAddressList.subList(0, ChainConstant.WITNESS_STANDBY_LENGTH);
49+
List<WitnessCapsule> witnessStandbys = witnessStore.getWitnessStandby();
50+
long voteSum = witnessStandbys.stream().mapToLong(WitnessCapsule::getVoteCount).sum();
51+
if (voteSum < 1) {
52+
return;
6653
}
67-
long voteSum = 0;
6854
long totalPay = dynamicPropertiesStore.getWitness127PayPerBlock();
69-
for (ByteString b : witnessAddressList) {
70-
voteSum += witnessCapsuleMap.get(b).getVoteCount();
71-
}
72-
73-
if (voteSum > 0) {
74-
for (ByteString b : witnessAddressList) {
75-
double eachVotePay = (double) totalPay / voteSum;
76-
long pay = (long) (witnessCapsuleMap.get(b).getVoteCount() * eachVotePay);
77-
logger.debug("pay {} stand reward {}", Hex.toHexString(b.toByteArray()), pay);
78-
payReward(b.toByteArray(), pay);
79-
}
55+
double eachVotePay = (double) totalPay / voteSum;
56+
for (WitnessCapsule w : witnessStandbys) {
57+
long pay = (long) (w.getVoteCount() * eachVotePay);
58+
payReward(w.getAddress().toByteArray(), pay);
59+
logger.debug("pay {} stand reward {}", Hex.toHexString(w.getAddress().toByteArray()), pay);
8060
}
8161
}
8262

chainbase/src/main/java/org/tron/core/store/WitnessStore.java

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package org.tron.core.store;
22

33
import com.google.common.collect.Streams;
4+
import java.util.ArrayList;
5+
import java.util.Comparator;
46
import java.util.List;
57
import java.util.Map.Entry;
68
import java.util.stream.Collectors;
@@ -9,16 +11,23 @@
911
import org.springframework.beans.factory.annotation.Autowired;
1012
import org.springframework.beans.factory.annotation.Value;
1113
import org.springframework.stereotype.Component;
14+
import org.tron.common.cache.CacheManager;
15+
import org.tron.common.cache.TronCache;
1216
import org.tron.core.capsule.WitnessCapsule;
17+
import org.tron.core.config.Parameter;
1318
import org.tron.core.db.TronStoreWithRevoking;
1419

1520
@Slf4j(topic = "DB")
1621
@Component
1722
public class WitnessStore extends TronStoreWithRevoking<WitnessCapsule> {
1823

24+
private final TronCache<Integer, List<WitnessCapsule>> witnessStandby;
25+
1926
@Autowired
2027
protected WitnessStore(@Value("witness") String dbName) {
2128
super(dbName);
29+
String strategy = "initialCapacity=1,maximumSize=1,expireAfterAccess=6h";
30+
witnessStandby = CacheManager.allocate("witnessStandby", strategy);
2231
}
2332

2433
/**
@@ -35,4 +44,33 @@ public WitnessCapsule get(byte[] key) {
3544
byte[] value = revokingDB.getUnchecked(key);
3645
return ArrayUtils.isEmpty(value) ? null : new WitnessCapsule(value);
3746
}
47+
48+
public List<WitnessCapsule> getWitnessStandby() {
49+
List<WitnessCapsule> list =
50+
witnessStandby.getIfPresent(Parameter.ChainConstant.WITNESS_STANDBY_LENGTH);
51+
if (list != null) {
52+
return list;
53+
}
54+
return updateWitnessStandby(null);
55+
}
56+
57+
public List<WitnessCapsule> updateWitnessStandby(List<WitnessCapsule> all) {
58+
List<WitnessCapsule> ret;
59+
if (all == null) {
60+
all = getAllWitnesses();
61+
}
62+
all.sort(Comparator.comparingLong(WitnessCapsule::getVoteCount)
63+
.reversed().thenComparing(Comparator.comparingInt(
64+
(WitnessCapsule w) -> w.getAddress().hashCode()).reversed()));
65+
if (all.size() > Parameter.ChainConstant.WITNESS_STANDBY_LENGTH) {
66+
ret = new ArrayList<>(all.subList(0, Parameter.ChainConstant.WITNESS_STANDBY_LENGTH));
67+
} else {
68+
ret = new ArrayList<>(all);
69+
}
70+
// trim voteCount = 0
71+
ret.removeIf(w -> w.getVoteCount() < 1);
72+
witnessStandby.put(Parameter.ChainConstant.WITNESS_STANDBY_LENGTH, ret);
73+
return ret;
74+
}
75+
3876
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package org.tron.common.cache;
2+
3+
import com.google.common.cache.CacheLoader;
4+
import com.google.common.cache.CacheStats;
5+
import com.google.common.collect.Maps;
6+
import java.util.Map;
7+
import java.util.stream.Collectors;
8+
import org.tron.common.parameter.CommonParameter;
9+
10+
public class CacheManager {
11+
12+
private static final Map<String, TronCache<?, ?>> CACHES = Maps.newConcurrentMap();
13+
14+
public static <K, V> TronCache<K, V> allocate(String name) {
15+
TronCache<K, V> cache = new TronCache<>(name, CommonParameter.getInstance()
16+
.getStorage().getCacheStrategy(name));
17+
CACHES.put(name, cache);
18+
return cache;
19+
}
20+
21+
public static <K, V> TronCache<K, V> allocate(String name, String strategy) {
22+
TronCache<K, V> cache = new TronCache<>(name, strategy);
23+
CACHES.put(name, cache);
24+
return cache;
25+
}
26+
27+
public static <K, V> TronCache<K, V> allocate(String name, String strategy,
28+
CacheLoader<K, V> loader) {
29+
TronCache<K, V> cache = new TronCache<>(name, strategy, loader);
30+
CACHES.put(name, cache);
31+
return cache;
32+
}
33+
34+
public static void release(String name) {
35+
TronCache cache = CACHES.remove(name);
36+
if (cache != null) {
37+
cache.invalidateAll();
38+
}
39+
}
40+
41+
public static Map<String, CacheStats> stats() {
42+
return CACHES.values().stream().collect(Collectors.toMap(TronCache::getName, TronCache::stats));
43+
}
44+
45+
}

0 commit comments

Comments
 (0)