Skip to content
This repository was archived by the owner on Sep 11, 2020. It is now read-only.

Commit 962eeb3

Browse files
committed
Enforce the use of cache in packfile decoder
Decoder object can make use of an object cache to speed up processing. Previously the only way to specify it was changing manually the struct generated by NewDecodeForFile. This lead to some instances to be created without it and penalized performance. Now the cache should be explicitly passed to the constructor function. NewDecoder now creates objects with a cache using the default size. A new helper function was added to create cache objects with the default size as this becomes a common task now: cache.NewObjectLRUDefault() Signed-off-by: Javi Fontan <jfontan@gmail.com>
1 parent 55b5d73 commit 962eeb3

File tree

5 files changed

+36
-17
lines changed

5 files changed

+36
-17
lines changed

plumbing/cache/common.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ const (
1111

1212
type FileSize int64
1313

14+
const DefaultMaxSize FileSize = 96 * MiByte
15+
1416
// Object is an interface to a object cache.
1517
type Object interface {
1618
// Put puts the given object into the cache. Whether this object will

plumbing/cache/object_lru.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@ func NewObjectLRU(maxSize FileSize) *ObjectLRU {
2424
return &ObjectLRU{MaxSize: maxSize}
2525
}
2626

27+
// NewObjectLRUDefault creates a new ObjectLRU with the default cache size.
28+
func NewObjectLRUDefault() *ObjectLRU {
29+
return &ObjectLRU{MaxSize: DefaultMaxSize}
30+
}
31+
2732
// Put puts an object into the cache. If the object is already in the cache, it
2833
// will be marked as used. Otherwise, it will be inserted. A single object might
2934
// be evicted to make room for the new object.

plumbing/format/packfile/decoder.go

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -80,15 +80,20 @@ type Decoder struct {
8080
// If the ObjectStorer implements storer.Transactioner, a transaction is created
8181
// during the Decode execution. If anything fails, Rollback is called
8282
func NewDecoder(s *Scanner, o storer.EncodedObjectStorer) (*Decoder, error) {
83-
return NewDecoderForType(s, o, plumbing.AnyObject)
83+
return NewDecoderForType(s, o, plumbing.AnyObject,
84+
cache.NewObjectLRUDefault())
8485
}
8586

8687
// NewDecoderForType returns a new Decoder but in this case for a specific object type.
8788
// When an object is read using this Decoder instance and it is not of the same type of
8889
// the specified one, nil will be returned. This is intended to avoid the content
89-
// deserialization of all the objects
90+
// deserialization of all the objects.
91+
//
92+
// cacheObject is an ObjectLRU that is used to speed up the process. If cache
93+
// is not needed you can pass nil. To create a cache object with the default
94+
// size you an use the helper cache.ObjectLRUDefault().
9095
func NewDecoderForType(s *Scanner, o storer.EncodedObjectStorer,
91-
t plumbing.ObjectType) (*Decoder, error) {
96+
t plumbing.ObjectType, cacheObject cache.Object) (*Decoder, error) {
9297

9398
if t == plumbing.OFSDeltaObject ||
9499
t == plumbing.REFDeltaObject ||
@@ -101,8 +106,9 @@ func NewDecoderForType(s *Scanner, o storer.EncodedObjectStorer,
101106
}
102107

103108
return &Decoder{
104-
s: s,
105-
o: o,
109+
s: s,
110+
o: o,
111+
DeltaBaseCache: cacheObject,
106112

107113
idx: NewIndex(0),
108114
offsetToType: make(map[int64]plumbing.ObjectType),

plumbing/format/packfile/decoder_test.go

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"io"
55

66
"gopkg.in/src-d/go-git.v4/plumbing"
7+
"gopkg.in/src-d/go-git.v4/plumbing/cache"
78
"gopkg.in/src-d/go-git.v4/plumbing/format/idxfile"
89
"gopkg.in/src-d/go-git.v4/plumbing/format/packfile"
910
"gopkg.in/src-d/go-git.v4/plumbing/storer"
@@ -51,7 +52,8 @@ func (s *ReaderSuite) TestDecodeByTypeRefDelta(c *C) {
5152

5253
storage := memory.NewStorage()
5354
scanner := packfile.NewScanner(f.Packfile())
54-
d, err := packfile.NewDecoderForType(scanner, storage, plumbing.CommitObject)
55+
d, err := packfile.NewDecoderForType(scanner, storage, plumbing.CommitObject,
56+
cache.NewObjectLRUDefault())
5557
c.Assert(err, IsNil)
5658

5759
// Index required to decode by ref-delta.
@@ -77,7 +79,8 @@ func (s *ReaderSuite) TestDecodeByTypeRefDeltaError(c *C) {
7779
fixtures.Basic().ByTag("ref-delta").Test(c, func(f *fixtures.Fixture) {
7880
storage := memory.NewStorage()
7981
scanner := packfile.NewScanner(f.Packfile())
80-
d, err := packfile.NewDecoderForType(scanner, storage, plumbing.CommitObject)
82+
d, err := packfile.NewDecoderForType(scanner, storage,
83+
plumbing.CommitObject, cache.NewObjectLRUDefault())
8184
c.Assert(err, IsNil)
8285

8386
defer d.Close()
@@ -111,7 +114,8 @@ func (s *ReaderSuite) TestDecodeByType(c *C) {
111114
for _, t := range ts {
112115
storage := memory.NewStorage()
113116
scanner := packfile.NewScanner(f.Packfile())
114-
d, err := packfile.NewDecoderForType(scanner, storage, t)
117+
d, err := packfile.NewDecoderForType(scanner, storage, t,
118+
cache.NewObjectLRUDefault())
115119
c.Assert(err, IsNil)
116120

117121
// when the packfile is ref-delta based, the offsets are required
@@ -141,13 +145,17 @@ func (s *ReaderSuite) TestDecodeByTypeConstructor(c *C) {
141145
storage := memory.NewStorage()
142146
scanner := packfile.NewScanner(f.Packfile())
143147

144-
_, err := packfile.NewDecoderForType(scanner, storage, plumbing.OFSDeltaObject)
148+
_, err := packfile.NewDecoderForType(scanner, storage,
149+
plumbing.OFSDeltaObject, cache.NewObjectLRUDefault())
145150
c.Assert(err, Equals, plumbing.ErrInvalidType)
146151

147-
_, err = packfile.NewDecoderForType(scanner, storage, plumbing.REFDeltaObject)
152+
_, err = packfile.NewDecoderForType(scanner, storage,
153+
plumbing.REFDeltaObject, cache.NewObjectLRUDefault())
154+
148155
c.Assert(err, Equals, plumbing.ErrInvalidType)
149156

150-
_, err = packfile.NewDecoderForType(scanner, storage, plumbing.InvalidObject)
157+
_, err = packfile.NewDecoderForType(scanner, storage, plumbing.InvalidObject,
158+
cache.NewObjectLRUDefault())
151159
c.Assert(err, Equals, plumbing.ErrInvalidType)
152160
}
153161

@@ -313,7 +321,8 @@ func (s *ReaderSuite) TestDecodeObjectAt(c *C) {
313321
func (s *ReaderSuite) TestDecodeObjectAtForType(c *C) {
314322
f := fixtures.Basic().One()
315323
scanner := packfile.NewScanner(f.Packfile())
316-
d, err := packfile.NewDecoderForType(scanner, nil, plumbing.TreeObject)
324+
d, err := packfile.NewDecoderForType(scanner, nil, plumbing.TreeObject,
325+
cache.NewObjectLRUDefault())
317326
c.Assert(err, IsNil)
318327

319328
// when the packfile is ref-delta based, the offsets are required

storage/filesystem/object.go

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,6 @@ import (
1818
"gopkg.in/src-d/go-billy.v4"
1919
)
2020

21-
const DefaultMaxDeltaBaseCacheSize = 92 * cache.MiByte
22-
2321
type ObjectStorage struct {
2422
// DeltaBaseCache is an object cache uses to cache delta's bases when
2523
DeltaBaseCache cache.Object
@@ -30,7 +28,7 @@ type ObjectStorage struct {
3028

3129
func newObjectStorage(dir *dotgit.DotGit) (ObjectStorage, error) {
3230
s := ObjectStorage{
33-
DeltaBaseCache: cache.NewObjectLRU(DefaultMaxDeltaBaseCacheSize),
31+
DeltaBaseCache: cache.NewObjectLRUDefault(),
3432
dir: dir,
3533
}
3634

@@ -433,13 +431,12 @@ func newPackfileIter(f billy.File, t plumbing.ObjectType, seen map[plumbing.Hash
433431
return nil, err
434432
}
435433

436-
d, err := packfile.NewDecoderForType(s, memory.NewStorage(), t)
434+
d, err := packfile.NewDecoderForType(s, memory.NewStorage(), t, cache)
437435
if err != nil {
438436
return nil, err
439437
}
440438

441439
d.SetIndex(index)
442-
d.DeltaBaseCache = cache
443440

444441
return &packfileIter{
445442
f: f,

0 commit comments

Comments
 (0)