Skip to content

Commit de2c4ec

Browse files
committed
perf(gnolang): make print+println much more efficient
This change is the result of seeing print/println being reported in bugs as needing gas metering but on examination, noticed that the code causes a RAM and CPU bloat, so this makes an improvement in all dimensions ```shell $ benchstat before_println.txt after_println3.txt name old time/op new time/op delta GnoPrintln-8 1.94ms ± 2% 1.86ms ± 4% -4.02% (p=0.001 n=9+9) name old alloc/op new alloc/op delta GnoPrintln-8 1.92MB ± 0% 1.81MB ± 0% -5.92% (p=0.000 n=10+10) name old allocs/op new allocs/op delta GnoPrintln-8 19.0k ± 0% 16.0k ± 0% -15.76% (p=0.002 n=8+10) ``` Fixes #3951
1 parent 5e017a4 commit de2c4ec

File tree

1 file changed

+56
-17
lines changed

1 file changed

+56
-17
lines changed

gnovm/pkg/gnolang/uverse.go

+56-17
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package gnolang
22

33
import (
44
"fmt"
5+
"io"
56
"strings"
67

78
bm "github.com/gnolang/gno/gnovm/pkg/benchops"
@@ -718,16 +719,30 @@ func makeUverseNode() {
718719
arg0 := m.LastBlock().GetParams1()
719720
xv := arg0
720721
xvl := xv.TV.GetLength()
721-
ss := make([]string, xvl)
722-
for i := 0; i < xvl; i++ {
723-
ev := xv.TV.GetPointerAtIndexInt(m.Store, i).Deref()
724-
ss[i] = ev.Sprint(m)
725-
}
726-
rs := strings.Join(ss, " ")
727-
if debug {
728-
print(rs)
722+
723+
switch debug {
724+
case true:
725+
ss := make([]string, xvl)
726+
for i := 0; i < xvl; i++ {
727+
ev := xv.TV.GetPointerAtIndexInt(m.Store, i).Deref()
728+
ss[i] = ev.Sprint(m)
729+
}
730+
rs := strings.Join(ss, " ")
731+
if debug {
732+
print(rs)
733+
}
734+
io.WriteString(m.Output, rs)
735+
736+
default:
737+
max := xvl - 1
738+
for i := 0; i < xvl; i++ {
739+
ev := xv.TV.GetPointerAtIndexInt(m.Store, i).Deref()
740+
io.WriteString(m.Output, ev.Sprint(m))
741+
if i < max {
742+
io.WriteString(m.Output, " ")
743+
}
744+
}
729745
}
730-
m.Output.Write([]byte(rs))
731746
},
732747
)
733748
defNative("println",
@@ -739,16 +754,40 @@ func makeUverseNode() {
739754
arg0 := m.LastBlock().GetParams1()
740755
xv := arg0
741756
xvl := xv.TV.GetLength()
742-
ss := make([]string, xvl)
743-
for i := 0; i < xvl; i++ {
744-
ev := xv.TV.GetPointerAtIndexInt(m.Store, i).Deref()
745-
ss[i] = ev.Sprint(m)
757+
758+
if xvl == 0 {
759+
// Mimick Go in which invoking println() does nothing.
760+
return
746761
}
747-
rs := strings.Join(ss, " ") + "\n"
748-
if debug {
749-
println("DEBUG/stdout: " + rs)
762+
763+
max := xvl - 1
764+
765+
switch debug {
766+
case true:
767+
ss := make([]string, xvl)
768+
for i := 0; i < xvl; i++ {
769+
ev := xv.TV.GetPointerAtIndexInt(m.Store, i).Deref()
770+
ss[i] = ev.Sprint(m)
771+
}
772+
println("DEBUG/stdout: " + strings.Join(ss, " ") + "\n")
773+
for i, segment := range ss {
774+
io.WriteString(m.Output, segment)
775+
if i < max {
776+
io.WriteString(m.Output, " ")
777+
}
778+
}
779+
default:
780+
for i := 0; i < xvl; i++ {
781+
ev := xv.TV.GetPointerAtIndexInt(m.Store, i).Deref()
782+
io.WriteString(m.Output, ev.Sprint(m))
783+
if i < max {
784+
io.WriteString(m.Output, " ")
785+
}
786+
}
750787
}
751-
m.Output.Write([]byte(rs))
788+
789+
io.WriteString(m.Output, "\n")
790+
752791
},
753792
)
754793
defNative("recover",

0 commit comments

Comments
 (0)