]> Cypherpunks.ru repositories - goredo.git/commitdiff
Another small performance optimisation
authorSergey Matveev <stargrave@stargrave.org>
Sun, 8 Oct 2023 13:56:10 +0000 (16:56 +0300)
committerSergey Matveev <stargrave@stargrave.org>
Sun, 8 Oct 2023 16:09:43 +0000 (19:09 +0300)
dep.go
depfix.go
inode.go
main.go
ood.go
run.go

diff --git a/dep.go b/dep.go
index 279e55dddbc1a736e950b8788394121651763307..b4dd7a1a54c22b718f1cc4a2105733feac91ba9a 100644 (file)
--- a/dep.go
+++ b/dep.go
@@ -67,11 +67,12 @@ func chunkWrite(in []byte) (out []byte) {
 
 type Ifchange struct {
        tgt  *Tgt
-       meta string
+       meta [InodeLen + HashLen]byte
 }
 
-func (ifchange *Ifchange) Inode() Inode {
-       return Inode(ifchange.meta[:InodeLen])
+func (ifchange *Ifchange) Inode() *Inode {
+       inode := Inode(ifchange.meta[:InodeLen])
+       return &inode
 }
 
 func (ifchange *Ifchange) Hash() Hash {
@@ -140,7 +141,7 @@ func depWrite(w io.Writer, fdDepName, cwd string, tgt *Tgt, hsh Hash) (err error
        }
        _, err = io.Copy(w, bytes.NewBuffer(chunkWrite(bytes.Join([][]byte{
                {DepTypeIfchange},
-               []byte(inode),
+               inode[:],
                []byte(hsh),
                []byte(tgt.RelTo(cwd)),
        }, nil))))
@@ -226,20 +227,19 @@ func depBinIfchangeParse(tgt *Tgt, chunk []byte) (*Ifchange, string, error) {
        if len(chunk) < InodeLen+HashLen+1 {
                return nil, "", errors.New("too short \"ifchange\" format")
        }
-       name := string(chunk[InodeLen+HashLen:])
-       meta := string(chunk[:InodeLen+HashLen])
 
        tgtH, _ := pathSplit(tgt.a)
-       ifchange := &Ifchange{tgt: NewTgt(path.Join(tgtH, name)), meta: meta}
-       cachedFound := false
+       name := string(chunk[InodeLen+HashLen:])
+       ifchange := &Ifchange{
+               tgt:  NewTgt(path.Join(tgtH, name)),
+               meta: ([InodeLen + HashLen]byte)(chunk),
+       }
        for _, cached := range IfchangeCache[ifchange.tgt.rel] {
                if ifchange.meta == cached.meta {
-                       ifchange = cached
-                       cachedFound = true
-                       break
+                       return cached, name, nil
                }
        }
-       if IfchangeCache != nil && !cachedFound {
+       if IfchangeCache != nil {
                IfchangeCache[ifchange.tgt.rel] = append(IfchangeCache[ifchange.tgt.rel], ifchange)
        }
        return ifchange, name, nil
index 72a40050c0c11588b900281bab1d782f9b30c1e0..cc073c2e69c436d6b0efd25fd098397d3570df52 100644 (file)
--- a/depfix.go
+++ b/depfix.go
@@ -156,7 +156,7 @@ func depFix(root string) error {
                                                if err != nil {
                                                        break
                                                }
-                                               var inode Inode
+                                               var inode *Inode
                                                inode, _, err = inodeFromFileByFd(fd)
                                                if err != nil {
                                                        fd.Close()
@@ -174,7 +174,7 @@ func depFix(root string) error {
                                                _, err = io.Copy(fdDepW, bytes.NewBuffer(
                                                        chunkWrite(bytes.Join([][]byte{
                                                                {DepTypeIfchange},
-                                                               []byte(inode),
+                                                               inode[:],
                                                                []byte(hsh),
                                                                []byte(name),
                                                        }, nil))))
@@ -244,7 +244,7 @@ func depFix(root string) error {
                                                if err != nil {
                                                        break
                                                }
-                                               var inode Inode
+                                               var inode *Inode
                                                inode, _, err = inodeFromFileByFd(fd)
                                                if err != nil {
                                                        fd.Close()
@@ -262,7 +262,7 @@ func depFix(root string) error {
                                                _, err = io.Copy(fdDepW, bytes.NewBuffer(
                                                        chunkWrite(bytes.Join([][]byte{
                                                                {DepTypeIfchange},
-                                                               []byte(inode),
+                                                               inode[:],
                                                                []byte(hsh),
                                                                []byte(name),
                                                        }, nil))))
index 84c1b029974d8d3ff5401df5dd173f3dc58d3542..ceaa4d30a07d5fa558dec921c6fc89cbdb881952 100644 (file)
--- a/inode.go
+++ b/inode.go
@@ -20,6 +20,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 package main
 
 import (
+       "bytes"
        "encoding/binary"
        "os"
        "strconv"
@@ -45,26 +46,26 @@ var InodeTrust InodeTrustType
 
 // It is big-endian 64-bit unsigned integers: size, inodeNum,
 // ctime sec, ctime nsec, mtime sec, mtime nsec.
-type Inode string
+type Inode [InodeLen]byte
 
-func (our Inode) Equals(their Inode) bool {
-       if our[:2*8] != their[:2*8] {
+func (our *Inode) Equals(their *Inode) bool {
+       if !bytes.Equal(our[:2*8], their[:2*8]) {
                return false
        }
        switch InodeTrust {
        case InodeTrustCtime:
-               if our[2*8:4*8] != their[2*8:4*8] {
+               if !bytes.Equal(our[2*8:4*8], their[2*8:4*8]) {
                        return false
                }
        case InodeTrustMtime:
-               if our[4*8:6*8] != their[4*8:6*8] {
+               if !bytes.Equal(our[4*8:6*8], their[4*8:6*8]) {
                        return false
                }
        }
        return true
 }
 
-func (inode Inode) RecfileFields() []recfile.Field {
+func (inode *Inode) RecfileFields() []recfile.Field {
        return []recfile.Field{
                {Name: "Size", Value: strconv.FormatUint(binary.BigEndian.Uint64(
                        []byte(inode[0*8:1*8])), 10)},
@@ -81,21 +82,21 @@ func (inode Inode) RecfileFields() []recfile.Field {
        }
 }
 
-func inodeFromFileStat(fi os.FileInfo, stat unix.Stat_t) Inode {
+func inodeFromFileStat(fi os.FileInfo, stat unix.Stat_t) *Inode {
        ctimeSec, ctimeNsec := stat.Ctim.Unix()
        mtimeSec := fi.ModTime().Unix()
        mtimeNsec := fi.ModTime().UnixNano()
-       buf := make([]byte, InodeLen)
-       binary.BigEndian.PutUint64(buf[0*8:1*8], uint64(fi.Size()))
-       binary.BigEndian.PutUint64(buf[1*8:2*8], uint64(stat.Ino))
-       binary.BigEndian.PutUint64(buf[2*8:3*8], uint64(ctimeSec))
-       binary.BigEndian.PutUint64(buf[3*8:4*8], uint64(ctimeNsec))
-       binary.BigEndian.PutUint64(buf[4*8:5*8], uint64(mtimeSec))
-       binary.BigEndian.PutUint64(buf[5*8:6*8], uint64(mtimeNsec))
-       return Inode(buf)
+       inode := new(Inode)
+       binary.BigEndian.PutUint64(inode[0*8:1*8], uint64(fi.Size()))
+       binary.BigEndian.PutUint64(inode[1*8:2*8], uint64(stat.Ino))
+       binary.BigEndian.PutUint64(inode[2*8:3*8], uint64(ctimeSec))
+       binary.BigEndian.PutUint64(inode[3*8:4*8], uint64(ctimeNsec))
+       binary.BigEndian.PutUint64(inode[4*8:5*8], uint64(mtimeSec))
+       binary.BigEndian.PutUint64(inode[5*8:6*8], uint64(mtimeNsec))
+       return inode
 }
 
-func inodeFromFileByFd(fd *os.File) (inode Inode, isDir bool, err error) {
+func inodeFromFileByFd(fd *os.File) (inode *Inode, isDir bool, err error) {
        fi, err := fd.Stat()
        if err != nil {
                return
@@ -113,15 +114,15 @@ func inodeFromFileByFd(fd *os.File) (inode Inode, isDir bool, err error) {
        return
 }
 
-func inodeFromFileByPath(p string) (Inode, error) {
+func inodeFromFileByPath(p string) (*Inode, error) {
        fi, err := os.Stat(p)
        if err != nil {
-               return "", err
+               return nil, err
        }
        var stat unix.Stat_t
        err = unix.Stat(p, &stat)
        if err != nil {
-               return "", err
+               return nil, err
        }
        return inodeFromFileStat(fi, stat), nil
 }
diff --git a/main.go b/main.go
index d795544fe64a9b0a793aa724770380cb9e5d6ef0..4439bcab13341686e05697502a6aefd42b3d41ce 100644 (file)
--- a/main.go
+++ b/main.go
@@ -507,7 +507,7 @@ func main() {
                DepFixHashCache = make(map[string]Hash)
                err = depFix(Cwd)
        case CmdNameRedoInode:
-               var inode Inode
+               var inode *Inode
                for _, tgt := range tgts {
                        inode, err = inodeFromFileByPath(tgt.a)
                        if err != nil {
@@ -542,6 +542,7 @@ func main() {
                }
                var typ byte
                var chunk []byte
+               var inode Inode
                for len(data) > 0 {
                        typ, chunk, data, _ = chunkRead(data)
                        switch typ {
@@ -561,7 +562,7 @@ func main() {
                                }...)
                        case DepTypeIfchange:
                                name := string(chunk[InodeLen+HashLen:])
-                               meta := string(chunk[:InodeLen+HashLen])
+                               meta := chunk[:InodeLen+HashLen]
                                fields := []recfile.Field{
                                        {Name: "Type", Value: "ifchange"},
                                        {Name: "Target", Value: name},
@@ -569,7 +570,8 @@ func main() {
                                fields = append(fields, recfile.Field{
                                        Name: "Hash", Value: Hash(meta[InodeLen:]).String(),
                                })
-                               fields = append(fields, Inode(meta[:InodeLen]).RecfileFields()...)
+                               inode = Inode(meta[:][:InodeLen])
+                               fields = append(fields, inode.RecfileFields()...)
                                err = recfileWrite(w, fields...)
                        case DepTypeIfchangeNonex:
                                err = recfileWrite(w, []recfile.Field{
diff --git a/ood.go b/ood.go
index ac5730cee6dbabf91b6d0b4c1325be70504bf456..7483ab3a0862971b2fd3b32f79019c9d4bf599c5 100644 (file)
--- a/ood.go
+++ b/ood.go
@@ -20,6 +20,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 package main
 
 import (
+       "bytes"
        "errors"
        "fmt"
        "io"
@@ -161,7 +162,7 @@ func isOOD(tgt *Tgt, level int, seen map[string]*Tgt) (bool, error) {
                        return ood, TgtError{tgt, ErrLine(err)}
                }
 
-               if inode[:8] != ifchange.Inode()[:8] {
+               if !bytes.Equal(inode[:8], ifchange.Inode()[:8]) {
                        tracef(CDebug, "ood: %s%s -> %s: size differs", indent, tgt, ifchange.tgt)
                        ood = true
                        OODCache[ifchange.tgt.rel] = ood
diff --git a/run.go b/run.go
index 971d8759f9e060afaba65431c7757e3f372e13cd..15628ddccfdf9d6ac9fc76d1f39618e977ac1750 100644 (file)
--- a/run.go
+++ b/run.go
@@ -133,7 +133,7 @@ func mkdirs(pth string) error {
 }
 
 func isModified(dep *Dep, tgt *Tgt) (
-       modified bool, ourInode Inode, hshPrev Hash, err error,
+       modified bool, ourInode *Inode, hshPrev Hash, err error,
 ) {
        if dep == nil {
                return
@@ -666,7 +666,7 @@ func runScript(tgt *Tgt, errs chan error, forced, traced bool) error {
 
                // Was $1 touched?
                if inode, err := inodeFromFileByPath(tgt.a); err == nil {
-                       if inodePrev == "" {
+                       if inodePrev == nil {
                                runErr.Err = Err1WasTouched
                                errs <- runErr
                                return