Skip to content

Commit 4dfe539

Browse files
Load sketch file contents only when needed
Previously, the full contents of *all* sketch files would be loaded into memory. This includes all source and header files inside the sketch directory, even when they will not even be compiled (e.g. subdirectories other than src). In practice, only the .ino file contents will actually be used, so these are now read on demand. Note that when copying the sketch into the build directory, the contents of all these sketch files *is* used, but that code (`writeIfDifferent()` in `arduino/builder/sketch.go`) already did not use the preloaded data but read the file contents when copying. For small sketches, this does not make much of a difference, but bigger sketches, especially when they include libraries, core definitions, tools, examples, documentation, etc. the memory usage can quite explode, for no good reason.
1 parent 4d48dc5 commit 4dfe539

File tree

4 files changed

+34
-38
lines changed

4 files changed

+34
-38
lines changed

Diff for: arduino/sketch/sketch.go

+14-11
Original file line numberDiff line numberDiff line change
@@ -27,25 +27,31 @@ import (
2727

2828
// Item holds the source and the path for a single sketch file
2929
type Item struct {
30-
Path string
31-
Source []byte
30+
Path string
3231
}
3332

3433
// NewItem reads the source code for a sketch item and returns an
3534
// Item instance
36-
func NewItem(itemPath string) (*Item, error) {
35+
func NewItem(itemPath string) *Item {
36+
return &Item{itemPath}
37+
}
38+
39+
func (i *Item) GetSourceBytes() ([]byte, error) {
3740
// read the file
38-
source, err := ioutil.ReadFile(itemPath)
41+
source, err := ioutil.ReadFile(i.Path)
3942
if err != nil {
4043
return nil, errors.Wrap(err, "error reading source file")
4144
}
42-
43-
return &Item{itemPath, source}, nil
45+
return source, nil
4446
}
4547

4648
// GetSourceStr returns the Source contents in string format
4749
func (i *Item) GetSourceStr() (string, error) {
48-
return string(i.Source), nil
50+
source, err := i.GetSourceBytes()
51+
if err != nil {
52+
return "", err
53+
}
54+
return string(source), nil
4955
}
5056

5157
// ItemByPath implements sort.Interface for []Item based on
@@ -73,10 +79,7 @@ func New(sketchFolderPath, mainFilePath, buildPath string, allFilesPaths []strin
7379
pathToItem := make(map[string]*Item)
7480
for _, p := range allFilesPaths {
7581
// create an Item
76-
item, err := NewItem(p)
77-
if err != nil {
78-
return nil, errors.Wrap(err, "error creating the sketch")
79-
}
82+
item := NewItem(p)
8083

8184
if p == mainFilePath {
8285
// store the main sketch file

Diff for: arduino/sketch/sketch_test.go

+13-9
Original file line numberDiff line numberDiff line change
@@ -26,22 +26,26 @@ import (
2626

2727
func TestNewItem(t *testing.T) {
2828
sketchItem := filepath.Join("testdata", t.Name()+".ino")
29-
item, err := sketch.NewItem(sketchItem)
30-
assert.Nil(t, err)
29+
item := sketch.NewItem(sketchItem)
3130
assert.Equal(t, sketchItem, item.Path)
32-
assert.Equal(t, []byte(`#include <testlib.h>`), item.Source)
33-
assert.Equal(t, "#include <testlib.h>", item.GetSourceStr())
31+
sourceBytes, err := item.GetSourceBytes()
32+
assert.Nil(t, err)
33+
assert.Equal(t, []byte(`#include <testlib.h>`), sourceBytes)
34+
sourceStr, err := item.GetSourceStr()
35+
assert.Nil(t, err)
36+
assert.Equal(t, "#include <testlib.h>", sourceStr)
3437

35-
item, err = sketch.NewItem("doesnt/exist")
36-
assert.Nil(t, item)
38+
item = sketch.NewItem("doesnt/exist")
39+
sourceBytes, err = item.GetSourceBytes()
40+
assert.Nil(t, sourceBytes)
3741
assert.NotNil(t, err)
3842
}
3943

4044
func TestSort(t *testing.T) {
4145
items := []*sketch.Item{
42-
&sketch.Item{"foo", nil},
43-
&sketch.Item{"baz", nil},
44-
&sketch.Item{"bar", nil},
46+
&sketch.Item{"foo"},
47+
&sketch.Item{"baz"},
48+
&sketch.Item{"bar"},
4549
}
4650

4751
sort.Sort(sketch.ItemByPath(items))

Diff for: legacy/builder/sketch_loader.go

+1-5
Original file line numberDiff line numberDiff line change
@@ -88,11 +88,7 @@ func collectAllSketchFiles(from *paths.Path) (paths.PathList, error) {
8888
func makeSketch(sketchLocation *paths.Path, allSketchFilePaths paths.PathList, buildLocation *paths.Path, logger i18n.Logger) (*types.Sketch, error) {
8989
sketchFilesMap := make(map[string]types.SketchFile)
9090
for _, sketchFilePath := range allSketchFilePaths {
91-
source, err := sketchFilePath.ReadFile()
92-
if err != nil {
93-
return nil, i18n.WrapError(err)
94-
}
95-
sketchFilesMap[sketchFilePath.String()] = types.SketchFile{Name: sketchFilePath, Source: string(source)}
91+
sketchFilesMap[sketchFilePath.String()] = types.SketchFile{Name: sketchFilePath}
9692
}
9793

9894
mainFile := sketchFilesMap[sketchLocation.String()]

Diff for: legacy/builder/types/types.go

+6-13
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,7 @@ func (f *SourceFile) DepfilePath(ctx *Context) *paths.Path {
8686
}
8787

8888
type SketchFile struct {
89-
Name *paths.Path
90-
Source string
89+
Name *paths.Path
9190
}
9291

9392
type SketchFileSortByName []SketchFile
@@ -114,20 +113,17 @@ func SketchToLegacy(sketch *sketch.Sketch) *Sketch {
114113
s := &Sketch{}
115114
s.MainFile = SketchFile{
116115
paths.New(sketch.MainFile.Path),
117-
string(sketch.MainFile.Source),
118116
}
119117

120118
for _, item := range sketch.OtherSketchFiles {
121119
s.OtherSketchFiles = append(s.OtherSketchFiles, SketchFile{
122120
paths.New(item.Path),
123-
string(item.Source),
124121
})
125122
}
126123

127124
for _, item := range sketch.AdditionalFiles {
128125
s.AdditionalFiles = append(s.AdditionalFiles, SketchFile{
129126
paths.New(item.Path),
130-
string(item.Source),
131127
})
132128
}
133129

@@ -137,22 +133,19 @@ func SketchToLegacy(sketch *sketch.Sketch) *Sketch {
137133
func SketchFromLegacy(s *Sketch) *sketch.Sketch {
138134
others := []*sketch.Item{}
139135
for _, f := range s.OtherSketchFiles {
140-
if i, err := sketch.NewItem(f.Name.String()); err == nil {
141-
others = append(others, i)
142-
}
136+
i := sketch.NewItem(f.Name.String())
137+
others = append(others, i)
143138
}
144139

145140
additional := []*sketch.Item{}
146141
for _, f := range s.AdditionalFiles {
147-
if i, err := sketch.NewItem(f.Name.String()); err == nil {
148-
additional = append(additional, i)
149-
}
142+
i := sketch.NewItem(f.Name.String())
143+
additional = append(additional, i)
150144
}
151145

152146
return &sketch.Sketch{
153147
MainFile: &sketch.Item{
154-
Path: s.MainFile.Name.String(),
155-
Source: []byte(s.MainFile.Source),
148+
Path: s.MainFile.Name.String(),
156149
},
157150
LocationPath: s.MainFile.Name.Parent().String(),
158151
OtherSketchFiles: others,

0 commit comments

Comments
 (0)