Writing document data by mmap to reduce disk write operations https://github.com/siyuan-note/siyuan/issues/16956

Signed-off-by: Daniel <845765@qq.com>
This commit is contained in:
Daniel 2026-02-06 22:17:53 +08:00
parent e0df2411c7
commit 9fd1bf7b96
No known key found for this signature in database
GPG key ID: 86211BA83DF03017
3 changed files with 52 additions and 6 deletions

View file

@ -32,6 +32,7 @@ import (
"github.com/88250/lute/html"
"github.com/88250/lute/parse"
"github.com/88250/lute/render"
mmap "github.com/edsrzf/mmap-go"
jsoniter "github.com/json-iterator/go"
"github.com/panjf2000/ants/v2"
"github.com/siyuan-note/dataparser"
@ -228,12 +229,10 @@ func WriteTree(tree *parse.Tree) (size uint64, err error) {
return
}
size = uint64(len(data))
if err = filelock.WriteFile(filePath, data); err != nil {
msg := fmt.Sprintf("write data [%s] failed: %s", filePath, err)
logging.LogErrorf(msg)
err = errors.New(msg)
return
if err = writeTreeByMmap(filePath, data); nil != err {
if err = writeTreeByWriteFile(filePath, data); nil != err {
return
}
}
if util.ExceedLargeFileWarningSize(len(data)) {
@ -243,6 +242,50 @@ func WriteTree(tree *parse.Tree) (size uint64, err error) {
cache.SetTreeData(tree.ID, data)
afterWriteTree(tree)
size = uint64(len(data))
return
}
func writeTreeByWriteFile(filePath string, data []byte) (err error) {
if err = filelock.WriteFile(filePath, data); err != nil {
msg := fmt.Sprintf("write data [%s] failed: %s", filePath, err)
logging.LogErrorf(msg)
err = errors.New(msg)
return
}
return
}
func writeTreeByMmap(filePath string, data []byte) (err error) {
f, err := filelock.OpenFile(filePath, os.O_RDWR|os.O_CREATE, 0644)
if err != nil {
return
}
defer filelock.CloseFile(f)
if err = f.Truncate(int64(len(data))); err != nil {
msg := fmt.Sprintf("truncate file [%s] failed: %s", filePath, err)
logging.LogErrorf(msg)
err = errors.New(msg)
return
}
m, err := mmap.Map(f, mmap.RDWR, 0)
if err != nil {
msg := fmt.Sprintf("map file [%s] failed: %s", filePath, err)
logging.LogErrorf(msg)
err = errors.New(msg)
return
}
defer m.Unmap()
copy(m, data)
if err = m.Flush(); err != nil {
msg := fmt.Sprintf("flush data [%s] failed: %s", filePath, err)
logging.LogErrorf(msg)
err = errors.New(msg)
return
}
return
}

View file

@ -127,6 +127,7 @@ require (
github.com/dsnet/compress v0.0.1 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/ebitengine/purego v0.9.1 // indirect
github.com/edsrzf/mmap-go v1.2.0 // indirect
github.com/fatih/set v0.2.1 // indirect
github.com/gammazero/toposort v0.1.1 // indirect
github.com/gigawattio/window v0.0.0-20180317192513-0f5467e35573 // indirect

View file

@ -133,6 +133,8 @@ github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkp
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
github.com/ebitengine/purego v0.9.1 h1:a/k2f2HQU3Pi399RPW1MOaZyhKJL9w/xFpKAg4q1s0A=
github.com/ebitengine/purego v0.9.1/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ=
github.com/edsrzf/mmap-go v1.2.0 h1:hXLYlkbaPzt1SaQk+anYwKSRNhufIDCchSPkUD6dD84=
github.com/edsrzf/mmap-go v1.2.0/go.mod h1:19H/e8pUPLicwkyNgOykDXkJ9F0MHE+Z52B8EIth78Q=
github.com/emersion/go-ical v0.0.0-20240127095438-fc1c9d8fb2b6/go.mod h1:BEksegNspIkjCQfmzWgsgbu6KdeJ/4LwUZs7DMBzjzw=
github.com/emersion/go-ical v0.0.0-20250609112844-439c63cef608 h1:5XWaET4YAcppq3l1/Yh2ay5VmQjUdq6qhJuucdGbmOY=
github.com/emersion/go-ical v0.0.0-20250609112844-439c63cef608/go.mod h1:BEksegNspIkjCQfmzWgsgbu6KdeJ/4LwUZs7DMBzjzw=