Skip to content

Commit 5bee4bc

Browse files
committed
⚡ Improve transaction performance #15306
1 parent 03d27d6 commit 5bee4bc

1 file changed

Lines changed: 48 additions & 27 deletions

File tree

kernel/model/transaction.go

Lines changed: 48 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -977,35 +977,37 @@ func syncDelete2AttributeView(node *ast.Node) (changedAvIDs []string) {
977977
}
978978

979979
func (tx *Transaction) doInsert(operation *Operation) (ret *TxErr) {
980-
var err error
981-
opParentID := operation.ParentID
982-
block := treenode.GetBlockTree(opParentID)
983-
if nil == block {
984-
block = treenode.GetBlockTree(operation.PreviousID)
985-
if nil == block {
986-
block = treenode.GetBlockTree(operation.NextID)
980+
var bt *treenode.BlockTree
981+
bts := treenode.GetBlockTrees([]string{operation.ParentID, operation.PreviousID, operation.NextID})
982+
for _, b := range bts {
983+
if "" != b.ID {
984+
bt = b
985+
break
987986
}
988987
}
989-
if nil == block {
990-
logging.LogWarnf("not found block [%s, %s, %s]", operation.ParentID, operation.PreviousID, operation.NextID)
988+
if nil == bt {
989+
logging.LogWarnf("not found block tree [%s, %s, %s]", operation.ParentID, operation.PreviousID, operation.NextID)
991990
util.ReloadUI() // 比如分屏后编辑器状态不一致,这里强制重新载入界面
992991
return
993992
}
994993

995-
tree, err := tx.loadTree(block.ID)
994+
var err error
995+
tree, err := tx.loadTreeByBlockTree(bt)
996996
if err != nil {
997-
msg := fmt.Sprintf("load tree [%s] failed: %s", block.ID, err)
997+
msg := fmt.Sprintf("load tree [%s] failed: %s", bt.ID, err)
998998
logging.LogErrorf(msg)
999-
return &TxErr{code: TxErrCodeBlockNotFound, id: block.ID}
999+
return &TxErr{code: TxErrCodeBlockNotFound, id: bt.ID}
10001000
}
10011001

10021002
data := strings.ReplaceAll(operation.Data.(string), editor.FrontEndCaret, "")
10031003
subTree := tx.luteEngine.BlockDOM2Tree(data)
10041004

1005-
p := block.Path
1006-
assets := getAssetsDir(filepath.Join(util.DataDir, block.BoxID), filepath.Dir(filepath.Join(util.DataDir, block.BoxID, p)))
1007-
isGlobalAssets := strings.HasPrefix(assets, filepath.Join(util.DataDir, "assets"))
1008-
if !isGlobalAssets {
1005+
if !tx.isGlobalAssetsInit {
1006+
tx.assetsDir = getAssetsDir(filepath.Join(util.DataDir, bt.BoxID), filepath.Dir(filepath.Join(util.DataDir, bt.BoxID, bt.Path)))
1007+
tx.isGlobalAssets = strings.HasPrefix(tx.assetsDir, filepath.Join(util.DataDir, "assets"))
1008+
tx.isGlobalAssetsInit = true
1009+
}
1010+
if !tx.isGlobalAssets {
10091011
// 本地资源文件需要移动到用户手动建立的 assets 下 https://github.com/siyuan-note/siyuan/issues/2410
10101012
ast.Walk(subTree.Root, func(n *ast.Node, entering bool) ast.WalkStatus {
10111013
if !entering {
@@ -1026,7 +1028,7 @@ func (tx *Transaction) doInsert(operation *Operation) (ret *TxErr) {
10261028
}
10271029

10281030
// 只有全局 assets 才移动到相对 assets
1029-
targetP := filepath.Join(assets, filepath.Base(assetPath))
1031+
targetP := filepath.Join(tx.assetsDir, filepath.Base(assetPath))
10301032
if e = filelock.Rename(assetPath, targetP); err != nil {
10311033
logging.LogErrorf("copy path of asset from [%s] to [%s] failed: %s", assetPath, targetP, err)
10321034
return ast.WalkContinue
@@ -1035,9 +1037,10 @@ func (tx *Transaction) doInsert(operation *Operation) (ret *TxErr) {
10351037
return ast.WalkContinue
10361038
})
10371039
}
1040+
10381041
insertedNode := subTree.Root.FirstChild
10391042
if nil == insertedNode {
1040-
return &TxErr{code: TxErrCodeBlockNotFound, msg: "invalid data tree", id: block.ID}
1043+
return &TxErr{code: TxErrCodeBlockNotFound, msg: "invalid data tree", id: bt.ID}
10411044
}
10421045
var remains []*ast.Node
10431046
for remain := insertedNode.Next; nil != remain; remain = remain.Next {
@@ -1123,7 +1126,7 @@ func (tx *Transaction) doInsert(operation *Operation) (ret *TxErr) {
11231126
createdUpdated(insertedNode)
11241127
tx.nodes[insertedNode.ID] = insertedNode
11251128
if err = tx.writeTree(tree); err != nil {
1126-
return &TxErr{code: TxErrCodeWriteTree, msg: err.Error(), id: block.ID}
1129+
return &TxErr{code: TxErrCodeWriteTree, msg: err.Error(), id: bt.ID}
11271130
}
11281131

11291132
// 收集引用的定义块 ID
@@ -1179,8 +1182,6 @@ func (tx *Transaction) doInsert(operation *Operation) (ret *TxErr) {
11791182

11801183
operation.ID = insertedNode.ID
11811184
operation.ParentID = insertedNode.Parent.ID
1182-
1183-
checkUpsertInUserGuide(tree)
11841185
return
11851186
}
11861187

@@ -1302,8 +1303,6 @@ func (tx *Transaction) doUpdate(operation *Operation) (ret *TxErr) {
13021303
}
13031304
}
13041305
}
1305-
1306-
checkUpsertInUserGuide(tree)
13071306
return
13081307
}
13091308

@@ -1408,8 +1407,6 @@ func (tx *Transaction) doUpdateUpdated(operation *Operation) (ret *TxErr) {
14081407
func (tx *Transaction) doCreate(operation *Operation) (ret *TxErr) {
14091408
tree := operation.Data.(*parse.Tree)
14101409
tx.writeTree(tree)
1411-
1412-
checkUpsertInUserGuide(tree)
14131410
return
14141411
}
14151412

@@ -1534,8 +1531,12 @@ type Transaction struct {
15341531
DoOperations []*Operation `json:"doOperations"`
15351532
UndoOperations []*Operation `json:"undoOperations"`
15361533

1537-
trees map[string]*parse.Tree
1538-
nodes map[string]*ast.Node
1534+
trees map[string]*parse.Tree // 事务中变更的树
1535+
nodes map[string]*ast.Node // 事务中变更的节点
1536+
1537+
isGlobalAssetsInit bool // 是否初始化过全局资源判断
1538+
isGlobalAssets bool // 是否属于全局资源
1539+
assetsDir string // 资源目录路径
15391540

15401541
luteEngine *lute.Lute
15411542
m *sync.Mutex
@@ -1570,6 +1571,8 @@ func (tx *Transaction) commit() (err error) {
15701571
var sources []interface{}
15711572
sources = append(sources, tx)
15721573
util.PushSaveDoc(tree.ID, "tx", sources)
1574+
1575+
checkUpsertInUserGuide(tree)
15731576
}
15741577
refreshDynamicRefTexts(tx.nodes, tx.trees)
15751578
IncSync()
@@ -1585,6 +1588,24 @@ func (tx *Transaction) rollback() {
15851588
return
15861589
}
15871590

1591+
func (tx *Transaction) loadTreeByBlockTree(bt *treenode.BlockTree) (ret *parse.Tree, err error) {
1592+
if nil == bt {
1593+
return nil, ErrBlockNotFound
1594+
}
1595+
1596+
ret = tx.trees[bt.RootID]
1597+
if nil != ret {
1598+
return
1599+
}
1600+
1601+
ret, err = filesys.LoadTree(bt.BoxID, bt.Path, tx.luteEngine)
1602+
if err != nil {
1603+
return
1604+
}
1605+
tx.trees[bt.RootID] = ret
1606+
return
1607+
}
1608+
15881609
func (tx *Transaction) loadTree(id string) (ret *parse.Tree, err error) {
15891610
var rootID, box, p string
15901611
bt := treenode.GetBlockTree(id)

0 commit comments

Comments
 (0)