tip: 295
title: Optimize account assets
author: forfreeday@163.com
discussions to: https://github.com/tronprotocol/TIPs/issues/295
status: Final
type: Standards Track
category: Core
created: 2021-07-15
Separate storage of account and asset data to improve the speed of serialization deserialization of accounts and assets.
In the current account model data structure, account balance data and asset data are stored in AccountStore. When querying an account, asset-related data will also be queried and serialized, which will lead to slow serialization performance and affect query efficiency. In this regard, the account and asset data are stored separately to reduce the data volume and product and improve the speed of deserialization.
In the current project, there is very little coupling between the operations of different types of assets, and the account balance data and asset data are different types of data with little correlation. The number of assets data used is relatively small in the current business, but its data does affect the deserialization speed of the accounts. Therefore storing the asset data separately and populating it when it is needed can improve the deserialization speed of the account. Separate storage can also be logically decoupled. It can also improve the performance of TVM when using account related data.
- Create AccountAssetStore 2.Populate data when querying assets 3.Splitting when saving an account
1.Create AccountAssetStore Create a database to store split assets and save asset data.
Data structure of the AccountAsset
/* AccountAsset */
message AccountAsset {
/* frozen balance */
message Frozen {
int64 frozen_balance = 1; // the frozen trx balance
int64 expire_time = 2; // the expire time
}
// the create address
bytes address = 1;
// the other asset owned by this account
map<string, int64> asset = 2;
// the other asset owned by this account,key is assetId
map<string, int64> assetV2 = 3;
bytes asset_issued_name = 4;
bytes asset_issued_ID = 5;
map<string, int64> latest_asset_operation_time = 6;
map<string, int64> latest_asset_operation_timeV2 = 7;
map<string, int64> free_asset_net_usage = 8;
map<string, int64> free_asset_net_usageV2 = 9;
// frozen asset(for asset issuer)
repeated Frozen frozen_supply = 10;
}
2.Populate data when querying assets When the data is split, only the account data is returned when the account is queried to reduce the size. If the assets in the account are used, the asset data is populated by querying the assets, and this operation is done automatically.
3.When saving the account, splitting is performed. When saving an account, the AccountStore.put method is used as a proxy for the AccountAssetStore.put method to store the account separately.
When operating the account for the first time, the account is split and then stored. For operations that do not require asset data, the account only needs to deserialize the account data.
- Create AccountAssetStore to store asset data
- proxy the method of manipulating assets in AccountCapsule, and populate the asset data when manipulating assets
- Separate when storing AccountStore
1.Create AccountAssetStore to store asset data
2.Proxy methods for manipulating assets in AccountCapsule, and populate asset data when manipulating assets The methods that require asset manipulation are in AccountCapsule, including.
3.When saving the account, splitting is performed.
clearAssetV2()
clearLatestAssetOperationTimeV2()
clearFreeAssetNetUsageV2()
assetBalanceEnoughV2()
reduceAssetAmount()
reduceAssetAmountV2()
addAssetAmount()
addAssetAmountV2()
addAsset()
addAssetV2()
addAssetMapV2()
getAssetMap()
getAssetMapV2()
addAllLatestAssetOperationTimeV2()
getLatestAssetOperationTimeMap()
getLatestAssetOperationTimeMapV2()
getLatestAssetOperationTime()
getLatestAssetOperationTimeV2()
putLatestAssetOperationTimeMap()
putLatestAssetOperationTimeMapV2()
getFrozenSupplyCount()
getFrozenSupplyList()
getAssetIssuedName()
setAssetIssuedName()
getAssetIssuedID()
setAssetIssuedID()
addAllFreeAssetNetUsageV2()
getFreeAssetNetUsageV2()
getAllFreeAssetNetUsage()
getAllFreeAssetNetUsageV2()
putFreeAssetNetUsage()
putFreeAssetNetUsageV2()
All of these methods perform asset synchronization operations when used Examples
public Map<String, Long> getAssetMap() {
//fill data
importAsset();
Map<String, Long> assetMap = this.account.getAssetMap();
if (assetMap.isEmpty()) {
assetMap = Maps.newHashMap();
}
return assetMap;
}
3.Separation when storing AccountStore When the account is stored, the data is stored separately in the AccountStore and AccountAssetStore
public void put(byte[] key, AccountCapsule item) {
. ...
if (AssetUtil.isAllowAssetOptimization()) {
Account account = item.getInstance();
//separate asset data
AccountAsset accountAsset = AssetUtil.getAsset(account);
if (null != accountAsset) {
accountAssetStore.put(key, new AccountAssetCapsule(
accountAsset));
account = AssetUtil.clearAsset(account);
item.setIsAssetImport(false);
item.setInstance(account);
}
}
super.put(key, item);
accountStateCallBackUtils.accountCallBack(key, item);
}
TRC10 assets are a separate TOKEN type and are fully capable of being stored separately. In java-tron the balance TRC10 TRC20 is not affected in any way between separate storage