Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
P
plugin
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
JIRA
JIRA
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
link33
plugin
Commits
cee0ed2c
Commit
cee0ed2c
authored
Nov 19, 2018
by
wjx@disanbo.com
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'master' into fix_lot_lint
parents
9ea7ec98
ebfb1739
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
64 additions
and
52 deletions
+64
-52
errors.go
plugin/store/kvmvcc/errors.go
+1
-0
kvmvccdb.go
plugin/store/kvmvcc/kvmvccdb.go
+13
-0
kvmvccdb_test.go
plugin/store/kvmvcc/kvmvccdb_test.go
+47
-49
mpt_test.go
plugin/store/mpt/mpt_test.go
+3
-3
No files found.
plugin/store/kvmvcc/errors.go
View file @
cee0ed2c
...
...
@@ -7,5 +7,6 @@ package kvmvccdb
import
"errors"
var
(
//ErrStateHashLost means err happened when query with StateHash
ErrStateHashLost
=
errors
.
New
(
"ErrStateHashLost"
)
)
plugin/store/kvmvcc/kvmvccdb.go
View file @
cee0ed2c
...
...
@@ -18,10 +18,12 @@ import (
var
klog
=
log
.
New
(
"module"
,
"kvmvccdb"
)
var
maxRollbackNum
=
200
// SetLogLevel set log level
func
SetLogLevel
(
level
string
)
{
clog
.
SetLogLevel
(
level
)
}
// DisableLog disable log output
func
DisableLog
()
{
klog
.
SetHandler
(
log
.
DiscardHandler
())
}
...
...
@@ -30,6 +32,7 @@ func init() {
drivers
.
Reg
(
"kvmvcc"
,
New
)
}
// KVMVCCStore provide kvmvcc store interface implementation
type
KVMVCCStore
struct
{
*
drivers
.
BaseStore
mvcc
dbm
.
MVCC
...
...
@@ -41,6 +44,7 @@ type subConfig struct {
EnableMVCCIter
bool
`json:"enableMVCCIter"`
}
// New construct KVMVCCStore module
func
New
(
cfg
*
types
.
Store
,
sub
[]
byte
)
queue
.
Module
{
bs
:=
drivers
.
NewBaseStore
(
cfg
)
var
kvs
*
KVMVCCStore
...
...
@@ -59,11 +63,13 @@ func New(cfg *types.Store, sub []byte) queue.Module {
return
kvs
}
// Close the KVMVCCStore module
func
(
mvccs
*
KVMVCCStore
)
Close
()
{
mvccs
.
BaseStore
.
Close
()
klog
.
Info
(
"store kvdb closed"
)
}
// Set kvs with statehash to KVMVCCStore
func
(
mvccs
*
KVMVCCStore
)
Set
(
datas
*
types
.
StoreSet
,
sync
bool
)
([]
byte
,
error
)
{
hash
:=
calcHash
(
datas
)
kvlist
,
err
:=
mvccs
.
mvcc
.
AddMVCC
(
datas
.
KV
,
hash
,
datas
.
StateHash
,
datas
.
Height
)
...
...
@@ -74,6 +80,7 @@ func (mvccs *KVMVCCStore) Set(datas *types.StoreSet, sync bool) ([]byte, error)
return
hash
,
nil
}
// Get kvs with statehash from KVMVCCStore
func
(
mvccs
*
KVMVCCStore
)
Get
(
datas
*
types
.
StoreGet
)
[][]
byte
{
values
:=
make
([][]
byte
,
len
(
datas
.
Keys
))
version
,
err
:=
mvccs
.
mvcc
.
GetVersion
(
datas
.
StateHash
)
...
...
@@ -92,6 +99,7 @@ func (mvccs *KVMVCCStore) Get(datas *types.StoreGet) [][]byte {
return
values
}
// MemSet set kvs to the mem of KVMVCCStore module and return the StateHash
func
(
mvccs
*
KVMVCCStore
)
MemSet
(
datas
*
types
.
StoreSet
,
sync
bool
)
([]
byte
,
error
)
{
kvset
,
err
:=
mvccs
.
checkVersion
(
datas
.
Height
)
if
err
!=
nil
{
...
...
@@ -110,6 +118,7 @@ func (mvccs *KVMVCCStore) MemSet(datas *types.StoreSet, sync bool) ([]byte, erro
return
hash
,
nil
}
// Commit kvs in the mem of KVMVCCStore module to state db and return the StateHash
func
(
mvccs
*
KVMVCCStore
)
Commit
(
req
*
types
.
ReqHash
)
([]
byte
,
error
)
{
_
,
ok
:=
mvccs
.
kvsetmap
[
string
(
req
.
Hash
)]
if
!
ok
{
...
...
@@ -122,6 +131,7 @@ func (mvccs *KVMVCCStore) Commit(req *types.ReqHash) ([]byte, error) {
return
req
.
Hash
,
nil
}
// Rollback kvs in the mem of KVMVCCStore module and return the StateHash
func
(
mvccs
*
KVMVCCStore
)
Rollback
(
req
*
types
.
ReqHash
)
([]
byte
,
error
)
{
_
,
ok
:=
mvccs
.
kvsetmap
[
string
(
req
.
Hash
)]
if
!
ok
{
...
...
@@ -135,6 +145,7 @@ func (mvccs *KVMVCCStore) Rollback(req *types.ReqHash) ([]byte, error) {
return
req
.
Hash
,
nil
}
// IterateRangeByStateHash travel with Prefix by StateHash to get the latest version kvs.
func
(
mvccs
*
KVMVCCStore
)
IterateRangeByStateHash
(
statehash
[]
byte
,
start
[]
byte
,
end
[]
byte
,
ascending
bool
,
fn
func
(
key
,
value
[]
byte
)
bool
)
{
if
!
mvccs
.
enableMVCCIter
{
panic
(
"call IterateRangeByStateHash when disable mvcc iter"
)
...
...
@@ -162,10 +173,12 @@ func (mvccs *KVMVCCStore) IterateRangeByStateHash(statehash []byte, start []byte
listhelper
.
IteratorCallback
(
start
,
end
,
0
,
1
,
fn
)
}
// ProcEvent handles supported events
func
(
mvccs
*
KVMVCCStore
)
ProcEvent
(
msg
queue
.
Message
)
{
msg
.
ReplyErr
(
"KVStore"
,
types
.
ErrActionNotSupport
)
}
// Del set kvs to nil with StateHash
func
(
mvccs
*
KVMVCCStore
)
Del
(
req
*
types
.
StoreDel
)
([]
byte
,
error
)
{
kvset
,
err
:=
mvccs
.
mvcc
.
DelMVCC
(
req
.
StateHash
,
req
.
Height
,
true
)
if
err
!=
nil
{
...
...
plugin/store/kvmvcc/kvmvccdb_test.go
View file @
cee0ed2c
...
...
@@ -35,8 +35,8 @@ func TestKvmvccdbNewClose(t *testing.T) {
assert
.
Nil
(
t
,
err
)
defer
os
.
RemoveAll
(
dir
)
// clean up
os
.
RemoveAll
(
dir
)
//删除已存在目录
var
store
_c
fg
=
newStoreCfg
(
dir
)
store
:=
New
(
store
_c
fg
,
nil
)
.
(
*
KVMVCCStore
)
var
store
C
fg
=
newStoreCfg
(
dir
)
store
:=
New
(
store
C
fg
,
nil
)
.
(
*
KVMVCCStore
)
assert
.
NotNil
(
t
,
store
)
store
.
Close
()
...
...
@@ -47,8 +47,8 @@ func TestKvmvccdbSetGet(t *testing.T) {
assert
.
Nil
(
t
,
err
)
defer
os
.
RemoveAll
(
dir
)
// clean up
os
.
RemoveAll
(
dir
)
//删除已存在目录
var
store
_c
fg
=
newStoreCfg
(
dir
)
store
:=
New
(
store
_c
fg
,
nil
)
.
(
*
KVMVCCStore
)
var
store
C
fg
=
newStoreCfg
(
dir
)
store
:=
New
(
store
C
fg
,
nil
)
.
(
*
KVMVCCStore
)
assert
.
NotNil
(
t
,
store
)
keys0
:=
[][]
byte
{[]
byte
(
"mk1"
),
[]
byte
(
"mk2"
)}
...
...
@@ -93,8 +93,8 @@ func TestKvmvccdbMemSet(t *testing.T) {
assert
.
Nil
(
t
,
err
)
defer
os
.
RemoveAll
(
dir
)
// clean up
os
.
RemoveAll
(
dir
)
//删除已存在目录
var
store
_c
fg
=
newStoreCfg
(
dir
)
store
:=
New
(
store
_c
fg
,
nil
)
.
(
*
KVMVCCStore
)
var
store
C
fg
=
newStoreCfg
(
dir
)
store
:=
New
(
store
C
fg
,
nil
)
.
(
*
KVMVCCStore
)
assert
.
NotNil
(
t
,
store
)
var
kv
[]
*
types
.
KeyValue
...
...
@@ -131,8 +131,8 @@ func TestKvmvccdbRollback(t *testing.T) {
assert
.
Nil
(
t
,
err
)
defer
os
.
RemoveAll
(
dir
)
// clean up
os
.
RemoveAll
(
dir
)
//删除已存在目录
var
store
_c
fg
=
newStoreCfg
(
dir
)
store
:=
New
(
store
_c
fg
,
nil
)
.
(
*
KVMVCCStore
)
var
store
C
fg
=
newStoreCfg
(
dir
)
store
:=
New
(
store
C
fg
,
nil
)
.
(
*
KVMVCCStore
)
assert
.
NotNil
(
t
,
store
)
var
kv
[]
*
types
.
KeyValue
...
...
@@ -164,8 +164,8 @@ func TestKvmvccdbRollbackBatch(t *testing.T) {
assert
.
Nil
(
t
,
err
)
defer
os
.
RemoveAll
(
dir
)
// clean up
os
.
RemoveAll
(
dir
)
//删除已存在目录
var
store
_c
fg
=
newStoreCfg
(
dir
)
store
:=
New
(
store
_c
fg
,
nil
)
.
(
*
KVMVCCStore
)
var
store
C
fg
=
newStoreCfg
(
dir
)
store
:=
New
(
store
C
fg
,
nil
)
.
(
*
KVMVCCStore
)
assert
.
NotNil
(
t
,
store
)
var
kv
[]
*
types
.
KeyValue
...
...
@@ -260,8 +260,8 @@ func TestIterateRangeByStateHash(t *testing.T) {
assert
.
Nil
(
t
,
err
)
defer
os
.
RemoveAll
(
dir
)
// clean up
os
.
RemoveAll
(
dir
)
//删除已存在目录
store
_c
fg
,
sub
:=
newStoreCfgIter
(
dir
)
store
:=
New
(
store
_c
fg
,
sub
)
.
(
*
KVMVCCStore
)
store
C
fg
,
sub
:=
newStoreCfgIter
(
dir
)
store
:=
New
(
store
C
fg
,
sub
)
.
(
*
KVMVCCStore
)
assert
.
NotNil
(
t
,
store
)
execaddr
:=
"0111vcBNSEA7fZhAdLJphDwQRQJa111"
...
...
@@ -406,8 +406,8 @@ func BenchmarkGet(b *testing.B) {
defer
os
.
RemoveAll
(
dir
)
// clean up
os
.
RemoveAll
(
dir
)
//删除已存在目录
var
store
_c
fg
=
newStoreCfg
(
dir
)
store
:=
New
(
store
_c
fg
,
nil
)
.
(
*
KVMVCCStore
)
var
store
C
fg
=
newStoreCfg
(
dir
)
store
:=
New
(
store
C
fg
,
nil
)
.
(
*
KVMVCCStore
)
assert
.
NotNil
(
b
,
store
)
var
kv
[]
*
types
.
KeyValue
...
...
@@ -429,7 +429,7 @@ func BenchmarkGet(b *testing.B) {
datas
:=
&
types
.
StoreSet
{
hash
,
kv
,
0
}
hash
,
err
=
store
.
Set
(
datas
,
true
)
assert
.
Nil
(
b
,
err
)
kv
=
nil
//
kv = nil
}
assert
.
Nil
(
b
,
err
)
start
:=
time
.
Now
()
...
...
@@ -450,8 +450,8 @@ func BenchmarkStoreGetKvs4N(b *testing.B) {
defer
os
.
RemoveAll
(
dir
)
// clean up
os
.
RemoveAll
(
dir
)
//删除已存在目录
var
store
_c
fg
=
newStoreCfg
(
dir
)
store
:=
New
(
store
_c
fg
,
nil
)
.
(
*
KVMVCCStore
)
var
store
C
fg
=
newStoreCfg
(
dir
)
store
:=
New
(
store
C
fg
,
nil
)
.
(
*
KVMVCCStore
)
assert
.
NotNil
(
b
,
store
)
var
kv
[]
*
types
.
KeyValue
...
...
@@ -495,8 +495,8 @@ func BenchmarkStoreGetKvsForNN(b *testing.B) {
defer
os
.
RemoveAll
(
dir
)
// clean up
os
.
RemoveAll
(
dir
)
//删除已存在目录
var
store
_c
fg
=
newStoreCfg
(
dir
)
store
:=
New
(
store
_c
fg
,
nil
)
.
(
*
KVMVCCStore
)
var
store
C
fg
=
newStoreCfg
(
dir
)
store
:=
New
(
store
C
fg
,
nil
)
.
(
*
KVMVCCStore
)
assert
.
NotNil
(
b
,
store
)
var
kv
[]
*
types
.
KeyValue
...
...
@@ -555,8 +555,8 @@ func BenchmarkStoreGetKvsFor10000(b *testing.B) {
defer
os
.
RemoveAll
(
dir
)
// clean up
os
.
RemoveAll
(
dir
)
//删除已存在目录
var
store
_c
fg
=
newStoreCfg
(
dir
)
store
:=
New
(
store
_c
fg
,
nil
)
.
(
*
KVMVCCStore
)
var
store
C
fg
=
newStoreCfg
(
dir
)
store
:=
New
(
store
C
fg
,
nil
)
.
(
*
KVMVCCStore
)
assert
.
NotNil
(
b
,
store
)
var
kv
[]
*
types
.
KeyValue
...
...
@@ -620,8 +620,8 @@ func BenchmarkGetIter(b *testing.B) {
defer
os
.
RemoveAll
(
dir
)
// clean up
os
.
RemoveAll
(
dir
)
//删除已存在目录
store
_c
fg
,
sub
:=
newStoreCfgIter
(
dir
)
store
:=
New
(
store
_c
fg
,
sub
)
.
(
*
KVMVCCStore
)
store
C
fg
,
sub
:=
newStoreCfgIter
(
dir
)
store
:=
New
(
store
C
fg
,
sub
)
.
(
*
KVMVCCStore
)
assert
.
NotNil
(
b
,
store
)
var
kv
[]
*
types
.
KeyValue
...
...
@@ -643,7 +643,7 @@ func BenchmarkGetIter(b *testing.B) {
datas
:=
&
types
.
StoreSet
{
hash
,
kv
,
0
}
hash
,
err
=
store
.
Set
(
datas
,
true
)
assert
.
Nil
(
b
,
err
)
kv
=
nil
//
kv = nil
}
assert
.
Nil
(
b
,
err
)
start
:=
time
.
Now
()
...
...
@@ -663,8 +663,8 @@ func BenchmarkSet(b *testing.B) {
assert
.
Nil
(
b
,
err
)
defer
os
.
RemoveAll
(
dir
)
// clean up
os
.
RemoveAll
(
dir
)
//删除已存在目录
var
store
_c
fg
=
newStoreCfg
(
dir
)
store
:=
New
(
store
_c
fg
,
nil
)
.
(
*
KVMVCCStore
)
var
store
C
fg
=
newStoreCfg
(
dir
)
store
:=
New
(
store
C
fg
,
nil
)
.
(
*
KVMVCCStore
)
assert
.
NotNil
(
b
,
store
)
b
.
Log
(
dir
)
...
...
@@ -686,9 +686,9 @@ func BenchmarkSet(b *testing.B) {
}
if
kv
!=
nil
{
datas
:=
&
types
.
StoreSet
{
hash
,
kv
,
0
}
hash
,
err
=
store
.
Set
(
datas
,
true
)
_
,
err
=
store
.
Set
(
datas
,
true
)
assert
.
Nil
(
b
,
err
)
kv
=
nil
//
kv = nil
}
end
:=
time
.
Now
()
fmt
.
Println
(
"mpt BenchmarkSet cost time is"
,
end
.
Sub
(
start
),
"num is"
,
b
.
N
)
...
...
@@ -700,8 +700,8 @@ func BenchmarkStoreSet(b *testing.B) {
assert
.
Nil
(
b
,
err
)
defer
os
.
RemoveAll
(
dir
)
// clean up
os
.
RemoveAll
(
dir
)
//删除已存在目录
var
store
_c
fg
=
newStoreCfg
(
dir
)
store
:=
New
(
store
_c
fg
,
nil
)
.
(
*
KVMVCCStore
)
var
store
C
fg
=
newStoreCfg
(
dir
)
store
:=
New
(
store
C
fg
,
nil
)
.
(
*
KVMVCCStore
)
assert
.
NotNil
(
b
,
store
)
var
kv
[]
*
types
.
KeyValue
...
...
@@ -735,8 +735,8 @@ func BenchmarkSetIter(b *testing.B) {
assert
.
Nil
(
b
,
err
)
defer
os
.
RemoveAll
(
dir
)
// clean up
os
.
RemoveAll
(
dir
)
//删除已存在目录
store
_c
fg
,
sub
:=
newStoreCfgIter
(
dir
)
store
:=
New
(
store
_c
fg
,
sub
)
.
(
*
KVMVCCStore
)
store
C
fg
,
sub
:=
newStoreCfgIter
(
dir
)
store
:=
New
(
store
C
fg
,
sub
)
.
(
*
KVMVCCStore
)
assert
.
NotNil
(
b
,
store
)
b
.
Log
(
dir
)
...
...
@@ -758,9 +758,9 @@ func BenchmarkSetIter(b *testing.B) {
}
if
kv
!=
nil
{
datas
:=
&
types
.
StoreSet
{
hash
,
kv
,
0
}
hash
,
err
=
store
.
Set
(
datas
,
true
)
_
,
err
=
store
.
Set
(
datas
,
true
)
assert
.
Nil
(
b
,
err
)
kv
=
nil
//
kv = nil
}
end
:=
time
.
Now
()
fmt
.
Println
(
"kvmvcc BenchmarkSet cost time is"
,
end
.
Sub
(
start
),
"num is"
,
b
.
N
)
...
...
@@ -771,11 +771,9 @@ func isDirExists(path string) bool {
if
err
!=
nil
{
return
os
.
IsExist
(
err
)
}
else
{
return
fi
.
IsDir
()
}
panic
(
"not reached"
)
return
fi
.
IsDir
(
)
}
//一次设定多对kv,测试一次的时间/多少对kv,来算平均一对kv的耗时。
...
...
@@ -784,8 +782,8 @@ func BenchmarkMemSet(b *testing.B) {
assert
.
Nil
(
b
,
err
)
defer
os
.
RemoveAll
(
dir
)
// clean up
os
.
RemoveAll
(
dir
)
//删除已存在目录
var
store
_c
fg
=
newStoreCfg
(
dir
)
store
:=
New
(
store
_c
fg
,
nil
)
.
(
*
KVMVCCStore
)
var
store
C
fg
=
newStoreCfg
(
dir
)
store
:=
New
(
store
C
fg
,
nil
)
.
(
*
KVMVCCStore
)
assert
.
NotNil
(
b
,
store
)
var
kv
[]
*
types
.
KeyValue
...
...
@@ -818,8 +816,8 @@ func BenchmarkStoreMemSet(b *testing.B) {
assert
.
Nil
(
b
,
err
)
defer
os
.
RemoveAll
(
dir
)
// clean up
os
.
RemoveAll
(
dir
)
//删除已存在目录
var
store
_c
fg
=
newStoreCfg
(
dir
)
store
:=
New
(
store
_c
fg
,
nil
)
.
(
*
KVMVCCStore
)
var
store
C
fg
=
newStoreCfg
(
dir
)
store
:=
New
(
store
C
fg
,
nil
)
.
(
*
KVMVCCStore
)
assert
.
NotNil
(
b
,
store
)
var
kv
[]
*
types
.
KeyValue
...
...
@@ -856,8 +854,8 @@ func BenchmarkCommit(b *testing.B) {
assert
.
Nil
(
b
,
err
)
defer
os
.
RemoveAll
(
dir
)
// clean up
os
.
RemoveAll
(
dir
)
//删除已存在目录
var
store
_c
fg
=
newStoreCfg
(
dir
)
store
:=
New
(
store
_c
fg
,
nil
)
.
(
*
KVMVCCStore
)
var
store
C
fg
=
newStoreCfg
(
dir
)
store
:=
New
(
store
C
fg
,
nil
)
.
(
*
KVMVCCStore
)
assert
.
NotNil
(
b
,
store
)
var
kv
[]
*
types
.
KeyValue
...
...
@@ -897,8 +895,8 @@ func BenchmarkStoreCommit(b *testing.B) {
assert
.
Nil
(
b
,
err
)
defer
os
.
RemoveAll
(
dir
)
// clean up
os
.
RemoveAll
(
dir
)
//删除已存在目录
var
store
_c
fg
=
newStoreCfg
(
dir
)
store
:=
New
(
store
_c
fg
,
nil
)
.
(
*
KVMVCCStore
)
var
store
C
fg
=
newStoreCfg
(
dir
)
store
:=
New
(
store
C
fg
,
nil
)
.
(
*
KVMVCCStore
)
assert
.
NotNil
(
b
,
store
)
var
kv
[]
*
types
.
KeyValue
...
...
@@ -941,8 +939,8 @@ func BenchmarkIterMemSet(b *testing.B) {
assert
.
Nil
(
b
,
err
)
defer
os
.
RemoveAll
(
dir
)
// clean up
os
.
RemoveAll
(
dir
)
//删除已存在目录
store
_c
fg
,
sub
:=
newStoreCfgIter
(
dir
)
store
:=
New
(
store
_c
fg
,
sub
)
.
(
*
KVMVCCStore
)
store
C
fg
,
sub
:=
newStoreCfgIter
(
dir
)
store
:=
New
(
store
C
fg
,
sub
)
.
(
*
KVMVCCStore
)
assert
.
NotNil
(
b
,
store
)
var
kv
[]
*
types
.
KeyValue
...
...
@@ -974,8 +972,8 @@ func BenchmarkIterCommit(b *testing.B) {
assert
.
Nil
(
b
,
err
)
defer
os
.
RemoveAll
(
dir
)
// clean up
os
.
RemoveAll
(
dir
)
//删除已存在目录
store
_c
fg
,
sub
:=
newStoreCfgIter
(
dir
)
store
:=
New
(
store
_c
fg
,
sub
)
.
(
*
KVMVCCStore
)
store
C
fg
,
sub
:=
newStoreCfgIter
(
dir
)
store
:=
New
(
store
C
fg
,
sub
)
.
(
*
KVMVCCStore
)
assert
.
NotNil
(
b
,
store
)
var
kv
[]
*
types
.
KeyValue
...
...
plugin/store/mpt/mpt_test.go
View file @
cee0ed2c
...
...
@@ -186,7 +186,7 @@ func BenchmarkGet(b *testing.B) {
datas
:=
&
types
.
StoreSet
{
hash
,
kv
,
0
}
hash
,
err
=
store
.
Set
(
datas
,
true
)
assert
.
Nil
(
b
,
err
)
kv
=
nil
//
kv = nil
}
start
:=
time
.
Now
()
b
.
ResetTimer
()
...
...
@@ -227,9 +227,9 @@ func BenchmarkSet(b *testing.B) {
}
if
kv
!=
nil
{
datas
:=
&
types
.
StoreSet
{
hash
,
kv
,
0
}
hash
,
err
=
store
.
Set
(
datas
,
true
)
_
,
err
=
store
.
Set
(
datas
,
true
)
assert
.
Nil
(
b
,
err
)
kv
=
nil
//
kv = nil
}
end
:=
time
.
Now
()
fmt
.
Println
(
"mpt BenchmarkSet cost time is"
,
end
.
Sub
(
start
),
"num is"
,
b
.
N
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment