BenchmarkMemory/open-8192x256 measures the live heap per cell of a sheet opened from a .012 file; BenchmarkRead the cost of reading one cell through Sheet.Value and as formulas read cells in recalculation.
- commit
- 21e41c5fb4a4bbd38c9be2ab5f69a9a45f0c8be2
- parent
- 24d313d458adc9a8a0311d3deba8fb68ea2318f3
- author
- Dami <dami.etoile@gmail.com>
| M | internal/ | 66 | ++++++++++++++++++++++++++++-- |
@@ -9,6 +9,7 @@ import (
99 "bytes"1010 "fmt"1111 "runtime"12+ "sync"1213 "testing"1314 1415 "github.com/FelineStateMachine/012/internal/sheet"@@ -246,14 +247,29 @@ func saveShapes() []namedBuild {
246247 }247248 }248249 249-// BenchmarkMemory reports the live heap per non-blank cell after a load.250+// BenchmarkMemory reports the live heap per non-blank cell after a load:251+// built through Load, or opened from a .012 file written beforehand.250252 func BenchmarkMemory(b *testing.B) {251- for _, sh := range []namedBuild{252- {"numbers", func() *sheet.Sheet { return stress.Dense(stress.Rows, 64) }},253- {"formulas", func() *sheet.Sheet { return stress.Chain(stress.Rows) }},254- {"text-200", func() *sheet.Sheet { return stress.LongText(stress.Rows, 200) }},253+ for _, sh := range []struct {254+ name string255+ prep func()256+ build func() *sheet.Sheet257+ }{258+ {"numbers", nil, func() *sheet.Sheet { return stress.Dense(stress.Rows, 64) }},259+ {"formulas", nil, func() *sheet.Sheet { return stress.Chain(stress.Rows) }},260+ {"text-200", nil, func() *sheet.Sheet { return stress.LongText(stress.Rows, 200) }},261+ {"open-8192x256", func() { denseFile() }, func() *sheet.Sheet {262+ s, err := sheet.Read(bytes.NewReader(denseFile()))263+ if err != nil {264+ b.Fatal(err)265+ }266+ return s267+ }},255268 } {256269 b.Run(sh.name, func(b *testing.B) {270+ if sh.prep != nil {271+ sh.prep()272+ }257273 for b.Loop() {258274 before := heap()259275 s := sh.build()@@ -265,6 +281,46 @@ func BenchmarkMemory(b *testing.B) {
265281 }266282 }267283 284+// denseFile is the .012 file of 8192x256 numbers.285+var denseFile = sync.OnceValue(func() []byte {286+ var buf bytes.Buffer287+ if err := stress.Dense(stress.Rows, stress.Cols).Write(&buf); err != nil {288+ panic(err)289+ }290+ return buf.Bytes()291+})292+293+// BenchmarkRead is the cost of reading a cell's value, per cell of 8192294+// x 26 numbers: through Sheet.Value, and as formulas read cells in a295+// recalculation (a SUM of each column, read directly).296+func BenchmarkRead(b *testing.B) {297+ s := stress.Dense(stress.Rows, 26)298+ cells := float64(stress.Rows * 26)299+ b.Run("value", func(b *testing.B) {300+ sum := 0.0301+ for b.Loop() {302+ for row := range stress.Rows {303+ for col := range 26 {304+ sum += s.Value(sheet.Addr{Col: col, Row: row}).Num305+ }306+ }307+ }308+ b.ReportMetric(float64(b.Elapsed().Nanoseconds())/float64(b.N)/cells, "ns/cell")309+ })310+ b.Run("recalc", func(b *testing.B) {311+ for col := range 26 {312+ name := sheet.ColName(col)313+ if err := s.Set(sheet.Addr{Col: col, Row: stress.Rows}, fmt.Sprintf("=SUM(%s1:%s%d)", name, name, stress.Rows)); err != nil {314+ b.Fatal(err)315+ }316+ }317+ for b.Loop() {318+ s.RecalcAll()319+ }320+ b.ReportMetric(float64(b.Elapsed().Nanoseconds())/float64(b.N)/cells, "ns/cell")321+ })322+}323+268324 // heap is the live heap after a full collection.269325 func heap() uint64 {270326 runtime.GC()