summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTed <37789839+Theodoree@users.noreply.github.com>2020-11-03 17:48:37 +0800
committerGitHub <noreply@github.com>2020-11-03 17:48:37 +0800
commitfcca8a38389c7a7f99639dc142b9b10c827ac7ce (patch)
treeaa0e2f264153a793f1157c23959a9c140fa1bf67
parent9d470bb38f992d9f0da2168b7a576f9e212b7a88 (diff)
optimize memory allocation (#722)
* optimize marshal * optimize mem alloc * add benchmark testing * add NewSheetWithRowNum testing * sync struct fields order * add BenchmarkNewSheetWithStreamWriter * delete NewSheetWithRowNum and benchmark test
-rw-r--r--lib.go3
-rw-r--r--sheet.go12
-rw-r--r--sheet_test.go34
-rw-r--r--xmlWorksheet.go21
4 files changed, 57 insertions, 13 deletions
diff --git a/lib.go b/lib.go
index 88aa3a1..7dcc09e 100644
--- a/lib.go
+++ b/lib.go
@@ -206,8 +206,9 @@ func CoordinatesToCellName(col, row int) (string, error) {
if col < 1 || row < 1 {
return "", fmt.Errorf("invalid cell coordinates [%d, %d]", col, row)
}
+ //Using itoa will save more memory
colname, err := ColumnNumberToName(col)
- return fmt.Sprintf("%s%d", colname, row), err
+ return colname + strconv.Itoa(row), err
}
// boolPtr returns a pointer to a bool with the given value.
diff --git a/sheet.go b/sheet.go
index 8da2e89..caf87d9 100644
--- a/sheet.go
+++ b/sheet.go
@@ -120,18 +120,26 @@ func (f *File) workBookWriter() {
// workSheetWriter provides a function to save xl/worksheets/sheet%d.xml after
// serialize structure.
func (f *File) workSheetWriter() {
+
+ // optimize memory alloc
+ var arr []byte
+ buffer := bytes.NewBuffer(arr)
+ encoder := xml.NewEncoder(buffer)
+
for p, sheet := range f.Sheet {
if sheet != nil {
for k, v := range sheet.SheetData.Row {
f.Sheet[p].SheetData.Row[k].C = trimCell(v.C)
}
- output, _ := xml.Marshal(sheet)
- f.saveFileList(p, replaceRelationshipsBytes(f.replaceNameSpaceBytes(p, output)))
+ // reusing buffer
+ encoder.Encode(sheet)
+ f.saveFileList(p, replaceRelationshipsBytes(f.replaceNameSpaceBytes(p, buffer.Bytes())))
ok := f.checked[p]
if ok {
delete(f.Sheet, p)
f.checked[p] = false
}
+ buffer.Reset()
}
}
}
diff --git a/sheet_test.go b/sheet_test.go
index 1a59b65..4626003 100644
--- a/sheet_test.go
+++ b/sheet_test.go
@@ -3,6 +3,7 @@ package excelize
import (
"fmt"
"path/filepath"
+ "strconv"
"strings"
"testing"
@@ -344,3 +345,36 @@ func TestSetSheetName(t *testing.T) {
f.SetSheetName("Sheet1", "Sheet1")
assert.Equal(t, "Sheet1", f.GetSheetName(0))
}
+
+func BenchmarkNewSheet(b *testing.B) {
+ b.RunParallel(func(pb *testing.PB) {
+ for pb.Next() {
+ newSheetWithSet()
+ }
+ })
+}
+func newSheetWithSet() {
+ file := NewFile()
+ file.NewSheet("sheet1")
+ for i := 0; i < 1000; i++ {
+ file.SetCellInt("sheet1", "A"+strconv.Itoa(i+1), i)
+ }
+ file = nil
+}
+
+func BenchmarkFile_SaveAs(b *testing.B) {
+ b.RunParallel(func(pb *testing.PB) {
+ for pb.Next() {
+ newSheetWithSave()
+ }
+
+ })
+}
+func newSheetWithSave() {
+ file := NewFile()
+ file.NewSheet("sheet1")
+ for i := 0; i < 1000; i++ {
+ file.SetCellInt("sheet1", "A"+strconv.Itoa(i+1), i)
+ }
+ file.Save()
+}
diff --git a/xmlWorksheet.go b/xmlWorksheet.go
index 0eaa8ee..8880909 100644
--- a/xmlWorksheet.go
+++ b/xmlWorksheet.go
@@ -313,20 +313,20 @@ type xlsxSheetData struct {
// xlsxRow directly maps the row element. The element expresses information
// about an entire row of a worksheet, and contains all cell definitions for a
// particular row in the worksheet.
-type xlsxRow struct {
- Collapsed bool `xml:"collapsed,attr,omitempty"`
+type xlsxRow struct { // alignment word
+ C []xlsxC `xml:"c"`
+ R int `xml:"r,attr,omitempty"`
+ Spans string `xml:"spans,attr,omitempty"`
+ S int `xml:"s,attr,omitempty"`
CustomFormat bool `xml:"customFormat,attr,omitempty"`
- CustomHeight bool `xml:"customHeight,attr,omitempty"`
- Hidden bool `xml:"hidden,attr,omitempty"`
Ht float64 `xml:"ht,attr,omitempty"`
+ Hidden bool `xml:"hidden,attr,omitempty"`
+ CustomHeight bool `xml:"customHeight,attr,omitempty"`
OutlineLevel uint8 `xml:"outlineLevel,attr,omitempty"`
- Ph bool `xml:"ph,attr,omitempty"`
- R int `xml:"r,attr,omitempty"`
- S int `xml:"s,attr,omitempty"`
- Spans string `xml:"spans,attr,omitempty"`
- ThickBot bool `xml:"thickBot,attr,omitempty"`
+ Collapsed bool `xml:"collapsed,attr,omitempty"`
ThickTop bool `xml:"thickTop,attr,omitempty"`
- C []xlsxC `xml:"c"`
+ ThickBot bool `xml:"thickBot,attr,omitempty"`
+ Ph bool `xml:"ph,attr,omitempty"`
}
// xlsxSortState directly maps the sortState element. This collection
@@ -456,6 +456,7 @@ type DataValidation struct {
// s (Shared String) | Cell containing a shared string.
// str (String) | Cell containing a formula string.
//
+// fixme: how to make this structure smaller; cur size is 152 bytes. it's be too bigger.
type xlsxC struct {
XMLName xml.Name `xml:"c"`
XMLSpace xml.Attr `xml:"space,attr,omitempty"`