[symbolize] Check modtime on ids.txt
This change checks the mod time on the ids.txt file
prior to reading the file and thus prior to performing
verificiation of the ids.txt. Coupled with caching this
reduces the primary cost of the symbolize to be parsing (30-40%, 30% regex alone),
lock contention (15%). This represents something like a 1000x
speed up. Further optimization seems much harder. Increasing
go channel buffer sizes should give a 25%-50% improvement.
Change-Id: I0da1a05c7e31afc68d8ddc2eecd0acf42ae59961
diff --git a/symbolize/mock_elf.go b/symbolize/mock_elf.go
index 1bc0b32..568a5da 100644
--- a/symbolize/mock_elf.go
+++ b/symbolize/mock_elf.go
@@ -5,6 +5,8 @@
package symbolize
import (
+ "time"
+
"fuchsia.googlesource.com/tools/elflib"
)
@@ -21,3 +23,8 @@
func (m mockSource) getBinaries() ([]elflib.BinaryFileRef, error) {
return []elflib.BinaryFileRef(m), nil
}
+
+func (m mockSource) getModTime() (*time.Time, error) {
+ out := time.Unix(1, 0)
+ return &out, nil
+}
diff --git a/symbolize/repo.go b/symbolize/repo.go
index ee0c92b..3a77028 100644
--- a/symbolize/repo.go
+++ b/symbolize/repo.go
@@ -8,6 +8,7 @@
"fmt"
"os"
"sync"
+ "time"
"fuchsia.googlesource.com/tools/elflib"
)
@@ -22,6 +23,7 @@
type BinaryFileSource interface {
// Extracts the set of binaries from this source.
getBinaries() ([]elflib.BinaryFileRef, error)
+ getModTime() (*time.Time, error)
}
// idsSource is a BinaryFileSource parsed from ids.txt
@@ -46,15 +48,29 @@
return elflib.ReadIDsFile(file)
}
+func (i *idsSource) getModTime() (*time.Time, error) {
+ info, err := os.Stat(i.pathToIDs)
+ if err != nil {
+ return nil, err
+ }
+ out := info.ModTime()
+ return &out, nil
+}
+
type buildInfo struct {
filepath string
buildID string
}
+type modTimeSource struct {
+ BinaryFileSource
+ modTime time.Time
+}
+
// SymbolizerRepo keeps track of build objects and source files used in those build objects.
type SymbolizerRepo struct {
lock sync.RWMutex
- sources []BinaryFileSource
+ sources []modTimeSource
// TODO (jakehehrlich): give 'builds' a more descriptive name
builds map[string]*buildInfo
}
@@ -74,7 +90,16 @@
}
}
-func (s *SymbolizerRepo) loadSource(source BinaryFileSource) error {
+func (s *SymbolizerRepo) loadSource(sourcePtr *modTimeSource) error {
+ source := *sourcePtr
+ time, err := source.getModTime()
+ if err != nil {
+ return err
+ }
+ if !time.After(source.modTime) {
+ return nil
+ }
+ sourcePtr.modTime = *time
bins, err := source.getBinaries()
if err != nil {
return err
@@ -94,13 +119,13 @@
// AddSource adds a source of binaries and all contained binaries.
func (s *SymbolizerRepo) AddSource(source BinaryFileSource) error {
- s.sources = append(s.sources, source)
- return s.loadSource(source)
+ s.sources = append(s.sources, modTimeSource{source, time.Unix(0, 0)})
+ return s.loadSource(&s.sources[len(s.sources)-1])
}
func (s *SymbolizerRepo) reloadSources() error {
for _, source := range s.sources {
- if err := s.loadSource(source); err != nil {
+ if err := s.loadSource(&source); err != nil {
return err
}
}