vmware-archive / go-pmem-transaction

Golang library for using persistent memory
Other
29 stars 5 forks source link

Redundant flushes when logging slice using undo log #24

Open jerrinsg opened 5 years ago

jerrinsg commented 5 years ago

It is seen that redundant flushes are issued when a pointer to a slice is passed to the undo Log() function.

When Log() is passed a pointer to a slice, it logs the slice header as well as the contents of the slice. When End() is called, the contents of the slice are flushed twice - first when the slice header data is flushed, End() also flushes the contents of the slice because t.log[i].sliceElemSize != 0. Second - the contents of the slice were logged separately as well by Log(). When End() processes that entry, a redundant flush is issued.

jerrinsg commented 5 years ago

Simple program to verify the issue -

package main

import (
    "github.com/vmware/go-pmem-transaction/pmem"
    "github.com/vmware/go-pmem-transaction/transaction"
)

type data struct {
    slc []int
}

var dptr *data

func main() {
    pmem.Init("/mnt/ext4-pmem0/database")
    tx := transaction.NewUndoTx()

    dptr = pnew(data)
    dptr.slc = pmake([]int, 10, 10)

    tx.Begin()
    tx.Log(&dptr.slc)
    tx.End()
}

By adding debug prints in Log() it is seen that the slice contents are getting flushed twice.

mohit10verma commented 5 years ago

Actually, this code will be of use if the sliceheader itself changes. For example, in the program above if dptr.slc changes, we get a new slice header we need to flush the new slice contents too!

tx.Begin()
tx.Log(&dptr.slc)
dptr.slc = pmake([]int, 100, 100) // <-- dptr.slc sliceheader stores pointer to backing data & that pointer can be updated here
tx.End()

But you are right, if the sliceheader doesn't change there are two flushes for the slice contents.