Skip to content

Commit 903247d

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 903247d

File tree

4 files changed

+36
-39
lines changed

4 files changed

+36
-39
lines changed

Diff for: arduino/sketch/sketch.go

+16-12
Original file line numberDiff line numberDiff line change
@@ -27,25 +27,32 @@ 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+
// GetSourceBytes reads the item file contents and returns it as bytes
40+
func (i *Item) GetSourceBytes() ([]byte, error) {
3741
// read the file
38-
source, err := ioutil.ReadFile(itemPath)
42+
source, err := ioutil.ReadFile(i.Path)
3943
if err != nil {
4044
return nil, errors.Wrap(err, "error reading source file")
4145
}
42-
43-
return &Item{itemPath, source}, nil
46+
return source, nil
4447
}
4548

46-
// GetSourceStr returns the Source contents in string format
49+
// GetSourceStr reads the item file contents and returns it as a string
4750
func (i *Item) GetSourceStr() (string, error) {
48-
return string(i.Source), nil
51+
source, err := i.GetSourceBytes()
52+
if err != nil {
53+
return "", err
54+
}
55+
return string(source), nil
4956
}
5057

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

8185
if p == mainFilePath {
8286
// 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)