Skip to content

Commit b8646c9

Browse files
committed
Make GnoAttribute an int derived enum
This change reduces on the key comparison time (from hashing).
1 parent 9adc15d commit b8646c9

File tree

2 files changed

+58
-31
lines changed

2 files changed

+58
-31
lines changed

gnovm/pkg/gnolang/nodes.go

Lines changed: 44 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -145,26 +145,58 @@ func (loc Location) IsZero() bool {
145145
// even after preprocessing. Temporary attributes (e.g. those
146146
// for preprocessing) are stored in .data.
147147

148-
type GnoAttribute string
148+
type GnoAttribute int
149149

150150
const (
151-
ATTR_PREPROCESSED GnoAttribute = "ATTR_PREPROCESSED"
152-
ATTR_PREDEFINED GnoAttribute = "ATTR_PREDEFINED"
153-
ATTR_TYPE_VALUE GnoAttribute = "ATTR_TYPE_VALUE"
154-
ATTR_TYPEOF_VALUE GnoAttribute = "ATTR_TYPEOF_VALUE"
155-
ATTR_IOTA GnoAttribute = "ATTR_IOTA"
156-
ATTR_LOOP_DEFINES GnoAttribute = "ATTR_LOOP_DEFINES" // []Name defined within loops.
157-
ATTR_LOOP_USES GnoAttribute = "ATTR_LOOP_USES" // []Name loop defines actually used.
158-
ATTR_SHIFT_RHS GnoAttribute = "ATTR_SHIFT_RHS"
159-
ATTR_LAST_BLOCK_STMT GnoAttribute = "ATTR_LAST_BLOCK_STMT"
160-
ATTR_GLOBAL GnoAttribute = "ATTR_GLOBAL"
151+
ATTR_PREPROCESSED GnoAttribute = iota
152+
ATTR_PREDEFINED
153+
ATTR_TYPE_VALUE
154+
ATTR_TYPEOF_VALUE
155+
ATTR_IOTA
156+
ATTR_LOOP_DEFINES
157+
ATTR_LOOP_USES
158+
ATTR_SHIFT_RHS
159+
ATTR_LAST_BLOCK_STMT
160+
ATTR_GLOBAL
161161
)
162162

163+
func (ga GnoAttribute) String() string {
164+
switch ga {
165+
case ATTR_PREPROCESSED:
166+
return "ATTR_PREPROCESSED"
167+
case ATTR_PREDEFINED:
168+
return "ATTR_PREDEFINED"
169+
case ATTR_TYPE_VALUE:
170+
return "ATTR_TYPE_VALUE"
171+
case ATTR_TYPEOF_VALUE:
172+
return "ATTR_TYPEOF_VALUE"
173+
case ATTR_IOTA:
174+
return "ATTR_IOTA"
175+
case ATTR_LOOP_DEFINES:
176+
return "ATTR_LOOP_DEFINES" // []Name defined within loops.
177+
case ATTR_LOOP_USES:
178+
return "ATTR_LOOP_USES" // []Name loop defines actually used.
179+
case ATTR_SHIFT_RHS:
180+
return "ATTR_SHIFT_RHS"
181+
case ATTR_LAST_BLOCK_STMT:
182+
return "ATTR_LAST_BLOCK_STMT"
183+
case ATTR_GLOBAL:
184+
return "ATTR_GLOBAL"
185+
default:
186+
panic(fmt.Sprintf("Unknown attribute: %d", ga))
187+
}
188+
}
189+
163190
type Attributes struct {
164191
Line int
165192
Column int
166193
Label Name
167-
data []*attrKV // not persisted
194+
195+
// TODO: if ever the number of attributes ATTR_* grows
196+
// to say more than 100 (rough guess), you can then
197+
// consider using a map for it instead of a slice
198+
// Please see https://github.com/gnolang/gno/issues/3436
199+
data []*attrKV // not persisted
168200
}
169201

170202
func (attr *Attributes) GetLine() int {
@@ -218,10 +250,6 @@ type attrKV struct {
218250
}
219251

220252
func (attr *Attributes) SetAttribute(key GnoAttribute, value interface{}) {
221-
if attr.data == nil {
222-
attr.data = make([]*attrKV, 0, 4)
223-
}
224-
225253
for _, kv := range attr.data {
226254
if kv.key == key {
227255
kv.value = value
@@ -233,9 +261,6 @@ func (attr *Attributes) SetAttribute(key GnoAttribute, value interface{}) {
233261
}
234262

235263
func (attr *Attributes) DelAttribute(key GnoAttribute) {
236-
if debug && attr.data == nil {
237-
panic("should not happen, attribute is expected to be non-empty.")
238-
}
239264
_, index, _ := attr.getAttribute(key)
240265
if index < 0 {
241266
return

gnovm/pkg/gnolang/nodes_test.go

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package gnolang_test
22

33
import (
4-
"fmt"
54
"math"
65
"testing"
76

@@ -46,19 +45,20 @@ func TestStaticBlock_Define2_MaxNames(t *testing.T) {
4645

4746
func TestAttributesSetGetDel(t *testing.T) {
4847
attrs := new(gnolang.Attributes)
49-
if got, want := attrs.GetAttribute("a"), (any)(nil); got != want {
48+
key := gnolang.ATTR_IOTA
49+
if got, want := attrs.GetAttribute(key), (any)(nil); got != want {
5050
t.Errorf(".Get returned an unexpected value=%v, want=%v", got, want)
5151
}
52-
attrs.SetAttribute("a", 10)
53-
if got, want := attrs.GetAttribute("a"), 10; got != want {
52+
attrs.SetAttribute(key, 10)
53+
if got, want := attrs.GetAttribute(key), 10; got != want {
5454
t.Errorf(".Get returned an unexpected value=%v, want=%v", got, want)
5555
}
56-
attrs.SetAttribute("a", 20)
57-
if got, want := attrs.GetAttribute("a"), 20; got != want {
56+
attrs.SetAttribute(key, 20)
57+
if got, want := attrs.GetAttribute(key), 20; got != want {
5858
t.Errorf(".Get returned an unexpected value=%v, want=%v", got, want)
5959
}
60-
attrs.DelAttribute("a")
61-
if got, want := attrs.GetAttribute("a"), (any)(nil); got != want {
60+
attrs.DelAttribute(key)
61+
if got, want := attrs.GetAttribute(key), (any)(nil); got != want {
6262
t.Errorf(".Get returned an unexpected value=%v, want=%v", got, want)
6363
}
6464
}
@@ -69,20 +69,22 @@ func BenchmarkAttributesSetGetDel(b *testing.B) {
6969
n := 100
7070
keys := make([]gnolang.GnoAttribute, 0, n)
7171
for i := 0; i < n; i++ {
72-
keys = append(keys, gnolang.GnoAttribute(fmt.Sprintf("%d", i)))
72+
keys = append(keys, gnolang.GnoAttribute(i))
7373
}
7474

75+
attrCommon := gnolang.ATTR_TYPEOF_VALUE
76+
7577
b.ReportAllocs()
7678
b.ResetTimer()
7779

7880
for i := 0; i < b.N; i++ {
7981
attrs := new(gnolang.Attributes)
8082
for j := 0; j < 100; j++ {
81-
sink = attrs.GetAttribute("a")
83+
sink = attrs.GetAttribute(attrCommon)
8284
}
8385
for j := 0; j < 100; j++ {
84-
attrs.SetAttribute("a", j)
85-
sink = attrs.GetAttribute("a")
86+
attrs.SetAttribute(attrCommon, j)
87+
sink = attrs.GetAttribute(attrCommon)
8688
}
8789

8890
for j, key := range keys {

0 commit comments

Comments
 (0)