github.com/nspcc-dev/neo-go@v0.105.2-0.20240517133400-6be757af3eba/pkg/vm/opcodebench_test.go (about) 1 package vm 2 3 import ( 4 "encoding/binary" 5 "strconv" 6 "testing" 7 8 "github.com/nspcc-dev/neo-go/pkg/vm/opcode" 9 "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" 10 "github.com/stretchr/testify/require" 11 ) 12 13 func benchOpcodeInt(t *testing.B, f func() *VM, fail bool) { 14 t.ResetTimer() 15 for n := 0; n < t.N; n++ { 16 t.StopTimer() 17 v := f() 18 t.StartTimer() 19 err := v.Step() 20 t.StopTimer() 21 if fail { 22 require.Error(t, err) 23 } else { 24 require.NoError(t, err) 25 } 26 t.StartTimer() 27 } 28 } 29 30 func benchOpcode(t *testing.B, f func() *VM) { 31 benchOpcodeInt(t, f, false) 32 } 33 34 func benchOpcodeFail(t *testing.B, f func() *VM) { 35 benchOpcodeInt(t, f, true) 36 } 37 38 func opVM(op opcode.Opcode) func() *VM { 39 return opParamVM(op, nil) 40 } 41 42 func opParamVM(op opcode.Opcode, param []byte) func() *VM { 43 return opParamPushVM(op, param) 44 } 45 46 func opParamPushVM(op opcode.Opcode, param []byte, items ...any) func() *VM { 47 return opParamSlotsPushVM(op, param, 0, 0, 0, items...) 48 } 49 50 func opParamSlotsPushVM(op opcode.Opcode, param []byte, sslot int, slotloc int, slotarg int, items ...any) func() *VM { 51 return func() *VM { 52 script := []byte{byte(op)} 53 script = append(script, param...) 54 v := load(script) 55 v.SyscallHandler = func(_ *VM, _ uint32) error { 56 return nil 57 } 58 if sslot != 0 { 59 v.Context().sc.static.init(sslot, &v.refs) 60 } 61 if slotloc != 0 && slotarg != 0 { 62 v.Context().local.init(slotloc, &v.refs) 63 v.Context().arguments.init(slotarg, &v.refs) 64 } 65 for i := range items { 66 item, ok := items[i].(stackitem.Item) 67 if ok { 68 item = stackitem.DeepCopy(item, true) 69 } else { 70 item = stackitem.Make(items[i]) 71 } 72 v.estack.PushVal(item) 73 } 74 return v 75 } 76 } 77 78 func exceptParamPushVM(op opcode.Opcode, param []byte, ilen int, elen int, exception bool, items ...any) func() *VM { 79 return func() *VM { 80 regVMF := opParamPushVM(op, param, items...) 81 v := regVMF() 82 if ilen != 0 { 83 eCtx := newExceptionHandlingContext(1, 2) 84 v.Context().tryStack.PushVal(eCtx) 85 for i := 0; i < ilen; i++ { 86 v.call(v.Context(), 0) 87 } 88 } else if elen != 0 { 89 for i := 0; i < elen; i++ { 90 eCtx := newExceptionHandlingContext(1, 2) 91 v.Context().tryStack.PushVal(eCtx) 92 } 93 } 94 if exception { 95 v.uncaughtException = &stackitem.Null{} 96 } 97 return v 98 } 99 } 100 101 func zeroSlice(l int) []byte { 102 return make([]byte, l) 103 } 104 105 func ffSlice(l int) []byte { 106 var s = make([]byte, l) 107 for i := range s { 108 s[i] = 0xff 109 } 110 return s 111 } 112 113 func maxNumber() []byte { 114 s := ffSlice(32) 115 s[0] = 0 116 return s 117 } 118 119 func bigNumber() []byte { 120 s := maxNumber() 121 s[31] = 0 122 return s 123 } 124 125 func bigNegNumber() []byte { 126 s := ffSlice(32) 127 s[0] = 80 128 return s 129 } 130 131 func arrayOfOnes(size int) []stackitem.Item { 132 var elems = make([]stackitem.Item, size) 133 for i := range elems { 134 elems[i] = stackitem.Make(1) 135 } 136 return elems 137 } 138 139 func arrayOfIfaces(size int) []any { 140 var elems = make([]any, size) 141 for i := range elems { 142 elems[i] = 1 143 } 144 return elems 145 } 146 147 func bigMap() *stackitem.Map { 148 var m = stackitem.NewMap() 149 for i := 0; i < 1024; i++ { 150 m.Add(stackitem.Make(i), stackitem.Make(i)) 151 } 152 return m 153 } 154 155 func maxBytes() []byte { 156 return zeroSlice(1024 * 1024) 157 } 158 159 func maxBuf() *stackitem.Buffer { 160 return stackitem.NewBuffer(maxBytes()) 161 } 162 163 func BenchmarkOpcodes(t *testing.B) { 164 t.Run("NOP", func(t *testing.B) { benchOpcode(t, opVM(opcode.NOP)) }) 165 t.Run("PUSHINT8", func(t *testing.B) { 166 t.Run("00", func(t *testing.B) { benchOpcode(t, opParamVM(opcode.PUSHINT8, []byte{0})) }) 167 t.Run("FF", func(t *testing.B) { benchOpcode(t, opParamVM(opcode.PUSHINT8, []byte{0xff})) }) 168 }) 169 t.Run("PUSHINT16", func(t *testing.B) { 170 t.Run("0000", func(t *testing.B) { benchOpcode(t, opParamVM(opcode.PUSHINT16, []byte{0, 0})) }) 171 t.Run("FFFF", func(t *testing.B) { benchOpcode(t, opParamVM(opcode.PUSHINT16, []byte{0xff, 0xff})) }) 172 }) 173 t.Run("PUSHINT32", func(t *testing.B) { 174 t.Run("0000...", func(t *testing.B) { benchOpcode(t, opParamVM(opcode.PUSHINT32, zeroSlice(4))) }) 175 t.Run("FFFF...", func(t *testing.B) { benchOpcode(t, opParamVM(opcode.PUSHINT32, ffSlice(4))) }) 176 }) 177 t.Run("PUSHINT64", func(t *testing.B) { 178 t.Run("0000...", func(t *testing.B) { benchOpcode(t, opParamVM(opcode.PUSHINT64, zeroSlice(8))) }) 179 t.Run("FFFF...", func(t *testing.B) { benchOpcode(t, opParamVM(opcode.PUSHINT64, ffSlice(8))) }) 180 }) 181 t.Run("PUSHINT128", func(t *testing.B) { 182 t.Run("0000...", func(t *testing.B) { benchOpcode(t, opParamVM(opcode.PUSHINT128, zeroSlice(16))) }) 183 t.Run("FFFF...", func(t *testing.B) { benchOpcode(t, opParamVM(opcode.PUSHINT128, ffSlice(16))) }) 184 }) 185 t.Run("PUSHINT256", func(t *testing.B) { 186 t.Run("0000...", func(t *testing.B) { benchOpcode(t, opParamVM(opcode.PUSHINT256, zeroSlice(32))) }) 187 t.Run("FFFF...", func(t *testing.B) { benchOpcode(t, opParamVM(opcode.PUSHINT256, ffSlice(32))) }) 188 }) 189 t.Run("PUSHA", func(t *testing.B) { 190 t.Run("small script", func(t *testing.B) { benchOpcode(t, opParamVM(opcode.PUSHA, zeroSlice(4))) }) 191 t.Run("big script", func(t *testing.B) { benchOpcode(t, opParamVM(opcode.PUSHA, zeroSlice(4+65536))) }) 192 }) 193 t.Run("PUSHNULL", func(t *testing.B) { benchOpcode(t, opVM(opcode.PUSHNULL)) }) 194 t.Run("PUSHDATA1", func(t *testing.B) { 195 var oneSlice = []byte{1, 0} 196 var maxSlice = zeroSlice(255) 197 maxSlice = append([]byte{255}, maxSlice...) 198 199 t.Run("1", func(t *testing.B) { benchOpcode(t, opParamVM(opcode.PUSHDATA1, oneSlice)) }) 200 t.Run("255", func(t *testing.B) { benchOpcode(t, opParamVM(opcode.PUSHDATA1, maxSlice)) }) 201 }) 202 t.Run("PUSHDATA2", func(t *testing.B) { 203 const minLen = 256 204 const maxLen = 65535 205 var minSlice = zeroSlice(minLen + 2) 206 var maxSlice = zeroSlice(maxLen + 2) 207 208 binary.LittleEndian.PutUint16(minSlice, minLen) 209 binary.LittleEndian.PutUint16(maxSlice, maxLen) 210 211 t.Run("256", func(t *testing.B) { benchOpcode(t, opParamVM(opcode.PUSHDATA2, minSlice)) }) 212 t.Run("65535", func(t *testing.B) { benchOpcode(t, opParamVM(opcode.PUSHDATA2, maxSlice)) }) 213 }) 214 t.Run("PUSHDATA4", func(t *testing.B) { 215 const minLen = 65536 216 const maxLen = 1024 * 1024 217 var minSlice = zeroSlice(minLen + 4) 218 var maxSlice = zeroSlice(maxLen + 4) 219 220 binary.LittleEndian.PutUint32(minSlice, minLen) 221 binary.LittleEndian.PutUint32(maxSlice, maxLen) 222 223 t.Run("64K", func(t *testing.B) { benchOpcode(t, opParamVM(opcode.PUSHDATA4, minSlice)) }) 224 t.Run("1M", func(t *testing.B) { benchOpcode(t, opParamVM(opcode.PUSHDATA4, maxSlice)) }) 225 }) 226 t.Run("PUSHM1", func(t *testing.B) { benchOpcode(t, opVM(opcode.PUSHM1)) }) 227 t.Run("PUSH0", func(t *testing.B) { benchOpcode(t, opVM(opcode.PUSH0)) }) 228 229 t.Run("JMP", func(t *testing.B) { benchOpcode(t, opParamVM(opcode.JMP, zeroSlice(1))) }) 230 t.Run("JMP_L", func(t *testing.B) { benchOpcode(t, opParamVM(opcode.JMPL, zeroSlice(4))) }) 231 232 var jmpifs = []struct { 233 op opcode.Opcode 234 size int 235 }{ 236 {opcode.JMPIF, 1}, 237 {opcode.JMPIFL, 4}, 238 {opcode.JMPIFNOT, 1}, 239 {opcode.JMPIFNOTL, 4}, 240 } 241 for _, jmpif := range jmpifs { 242 t.Run(jmpif.op.String(), func(t *testing.B) { 243 t.Run("false", func(t *testing.B) { benchOpcode(t, opParamPushVM(jmpif.op, zeroSlice(jmpif.size), false)) }) 244 t.Run("true", func(t *testing.B) { benchOpcode(t, opParamPushVM(jmpif.op, zeroSlice(jmpif.size), true)) }) 245 }) 246 } 247 248 var jmpcmps = []struct { 249 op opcode.Opcode 250 size int 251 }{ 252 {opcode.JMPEQ, 1}, 253 {opcode.JMPEQL, 4}, 254 {opcode.JMPNE, 1}, 255 {opcode.JMPNEL, 4}, 256 {opcode.JMPGT, 1}, 257 {opcode.JMPGTL, 4}, 258 {opcode.JMPGE, 1}, 259 {opcode.JMPGEL, 4}, 260 {opcode.JMPLT, 1}, 261 {opcode.JMPLTL, 4}, 262 {opcode.JMPLE, 1}, 263 {opcode.JMPLEL, 4}, 264 } 265 for _, jmpcmp := range jmpcmps { 266 t.Run(jmpcmp.op.String(), func(t *testing.B) { 267 t.Run("false", func(t *testing.B) { 268 t.Run("small", func(t *testing.B) { benchOpcode(t, opParamPushVM(jmpcmp.op, zeroSlice(jmpcmp.size), 1, 0)) }) 269 t.Run("big", func(t *testing.B) { 270 benchOpcode(t, opParamPushVM(jmpcmp.op, zeroSlice(jmpcmp.size), maxNumber(), bigNumber())) 271 }) 272 }) 273 t.Run("true", func(t *testing.B) { 274 t.Run("small", func(t *testing.B) { benchOpcode(t, opParamPushVM(jmpcmp.op, zeroSlice(jmpcmp.size), 1, 1)) }) 275 t.Run("big", func(t *testing.B) { 276 benchOpcode(t, opParamPushVM(jmpcmp.op, zeroSlice(jmpcmp.size), maxNumber(), maxNumber())) 277 }) 278 }) 279 }) 280 } 281 282 t.Run("CALL", func(t *testing.B) { benchOpcode(t, opParamVM(opcode.CALL, zeroSlice(1))) }) 283 t.Run("CALL_L", func(t *testing.B) { benchOpcode(t, opParamVM(opcode.CALLL, zeroSlice(4))) }) 284 t.Run("CALLA", func(t *testing.B) { 285 t.Run("small script", func(t *testing.B) { 286 p := stackitem.NewPointer(0, []byte{byte(opcode.CALLA)}) 287 benchOpcode(t, opParamPushVM(opcode.CALLA, nil, p)) 288 }) 289 t.Run("big script", func(t *testing.B) { 290 prog := zeroSlice(65536) 291 prog[0] = byte(opcode.CALLA) 292 p := stackitem.NewPointer(0, prog) 293 benchOpcode(t, opParamPushVM(opcode.CALLA, zeroSlice(65535), p)) 294 }) 295 }) 296 297 t.Run("ABORT", func(t *testing.B) { benchOpcodeFail(t, opVM(opcode.ABORT)) }) 298 t.Run("ASSERT", func(t *testing.B) { 299 t.Run("true", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.ASSERT, nil, true)) }) 300 t.Run("false", func(t *testing.B) { benchOpcodeFail(t, opParamPushVM(opcode.ASSERT, nil, false)) }) 301 }) 302 303 t.Run("THROW", func(t *testing.B) { 304 t.Run("0/1", func(t *testing.B) { 305 benchOpcode(t, exceptParamPushVM(opcode.THROW, []byte{0, 0, 0, 0}, 0, 1, false, 1)) 306 }) 307 t.Run("0/16", func(t *testing.B) { 308 benchOpcode(t, exceptParamPushVM(opcode.THROW, []byte{0, 0, 0, 0}, 0, 16, false, 1)) 309 }) 310 t.Run("255/0", func(t *testing.B) { 311 benchOpcode(t, exceptParamPushVM(opcode.THROW, []byte{0, 0, 0, 0}, 255, 0, false, 1)) 312 }) 313 t.Run("1023/0", func(t *testing.B) { 314 benchOpcode(t, exceptParamPushVM(opcode.THROW, []byte{0, 0, 0, 0}, 1023, 0, false, 1)) 315 }) 316 }) 317 t.Run("TRY", func(t *testing.B) { benchOpcode(t, opParamVM(opcode.TRY, []byte{1, 2, 0, 0})) }) 318 t.Run("TRY_L", func(t *testing.B) { benchOpcode(t, opParamVM(opcode.TRYL, []byte{1, 0, 0, 0, 2, 0, 0, 0})) }) 319 t.Run("ENDTRY", func(t *testing.B) { 320 t.Run("1", func(t *testing.B) { benchOpcode(t, exceptParamPushVM(opcode.ENDTRY, []byte{0, 0, 0, 0}, 0, 1, false)) }) 321 t.Run("16", func(t *testing.B) { benchOpcode(t, exceptParamPushVM(opcode.ENDTRY, []byte{0, 0, 0, 0}, 0, 16, false)) }) 322 }) 323 t.Run("ENDTRY_L", func(t *testing.B) { 324 t.Run("1", func(t *testing.B) { benchOpcode(t, exceptParamPushVM(opcode.ENDTRYL, []byte{0, 0, 0, 0}, 0, 1, false)) }) 325 t.Run("16", func(t *testing.B) { 326 benchOpcode(t, exceptParamPushVM(opcode.ENDTRYL, []byte{0, 0, 0, 0}, 0, 16, false)) 327 }) 328 }) 329 t.Run("ENDFINALLY", func(t *testing.B) { 330 t.Run("0/1", func(t *testing.B) { 331 benchOpcode(t, exceptParamPushVM(opcode.ENDFINALLY, []byte{0, 0, 0, 0}, 0, 1, true)) 332 }) 333 t.Run("0/16", func(t *testing.B) { 334 benchOpcode(t, exceptParamPushVM(opcode.ENDFINALLY, []byte{0, 0, 0, 0}, 0, 16, true)) 335 }) 336 t.Run("255/0", func(t *testing.B) { 337 benchOpcode(t, exceptParamPushVM(opcode.ENDFINALLY, []byte{0, 0, 0, 0}, 255, 0, true)) 338 }) 339 t.Run("1023/0", func(t *testing.B) { 340 benchOpcode(t, exceptParamPushVM(opcode.ENDFINALLY, []byte{0, 0, 0, 0}, 1023, 0, true)) 341 }) 342 }) 343 344 t.Run("RET", func(t *testing.B) { benchOpcode(t, opVM(opcode.RET)) }) 345 t.Run("SYSCALL", func(t *testing.B) { benchOpcode(t, opParamVM(opcode.SYSCALL, zeroSlice(4))) }) 346 347 t.Run("DEPTH", func(t *testing.B) { 348 t.Run("0", func(t *testing.B) { benchOpcode(t, opVM(opcode.DEPTH)) }) 349 t.Run("1024", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.DEPTH, nil, arrayOfIfaces(1024)...)) }) 350 }) 351 t.Run("DROP", func(t *testing.B) { 352 t.Run("1", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.DROP, nil, 1)) }) 353 t.Run("1024", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.DEPTH, nil, arrayOfIfaces(1024)...)) }) 354 }) 355 t.Run("NIP", func(t *testing.B) { 356 t.Run("2", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.NIP, nil, 1, 1)) }) 357 t.Run("1024", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.NIP, nil, arrayOfIfaces(1024)...)) }) 358 }) 359 t.Run("XDROP", func(t *testing.B) { 360 t.Run("0/1", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.XDROP, nil, 0, 0)) }) 361 var items = arrayOfIfaces(1025) 362 items[1024] = 0 363 t.Run("0/1024", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.XDROP, nil, items...)) }) 364 items[1024] = 1023 365 t.Run("1024/1024", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.XDROP, nil, items...)) }) 366 items = arrayOfIfaces(2048) 367 items[2047] = 2046 368 t.Run("2047/2048", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.XDROP, nil, items...)) }) 369 }) 370 t.Run("CLEAR", func(t *testing.B) { 371 t.Run("0", func(t *testing.B) { benchOpcode(t, opVM(opcode.CLEAR)) }) 372 t.Run("1024", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.CLEAR, nil, arrayOfIfaces(1024)...)) }) 373 t.Run("2048", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.CLEAR, nil, arrayOfIfaces(2048)...)) }) 374 }) 375 var copiers = []struct { 376 op opcode.Opcode 377 pos int 378 l int 379 }{ 380 {opcode.DUP, 0, 1}, 381 {opcode.OVER, 1, 2}, 382 {opcode.PICK, 2, 3}, 383 {opcode.PICK, 1024, 1025}, 384 {opcode.TUCK, 1, 2}, 385 } 386 for _, cp := range copiers { 387 var name = cp.op.String() 388 if cp.op == opcode.PICK { 389 name += "/" + strconv.Itoa(cp.pos) 390 } 391 var getitems = func(element any) []any { 392 l := cp.l 393 pos := cp.pos 394 if cp.op == opcode.PICK { 395 pos++ 396 l++ 397 } 398 var items = make([]any, l) 399 for i := range items { 400 items[i] = 0 401 } 402 items[pos] = element 403 if cp.op == opcode.PICK { 404 items[0] = cp.pos 405 } 406 return items 407 } 408 t.Run(name, func(t *testing.B) { 409 t.Run("null", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.DUP, nil, getitems(stackitem.Null{})...)) }) 410 t.Run("boolean", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.DUP, nil, getitems(true)...)) }) 411 t.Run("integer", func(t *testing.B) { 412 t.Run("small", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.DUP, nil, getitems(1)...)) }) 413 t.Run("big", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.DUP, nil, getitems(bigNumber())...)) }) 414 }) 415 t.Run("bytearray", func(t *testing.B) { 416 t.Run("small", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.DUP, nil, getitems("01234567")...)) }) 417 t.Run("big", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.DUP, nil, getitems(zeroSlice(65536))...)) }) 418 }) 419 t.Run("buffer", func(t *testing.B) { 420 t.Run("small", func(t *testing.B) { 421 benchOpcode(t, opParamPushVM(opcode.DUP, nil, getitems(stackitem.NewBuffer(zeroSlice(1)))...)) 422 }) 423 t.Run("big", func(t *testing.B) { 424 benchOpcode(t, opParamPushVM(opcode.DUP, nil, getitems(stackitem.NewBuffer(zeroSlice(65536)))...)) 425 }) 426 }) 427 t.Run("struct", func(t *testing.B) { 428 var items = make([]stackitem.Item, 1) 429 t.Run("small", func(t *testing.B) { 430 benchOpcode(t, opParamPushVM(opcode.DUP, nil, getitems(stackitem.NewStruct(items))...)) 431 }) 432 // Stack overflow. 433 if cp.op == opcode.PICK && cp.pos == 1024 { 434 return 435 } 436 items = make([]stackitem.Item, 1024) 437 t.Run("big", func(t *testing.B) { 438 benchOpcode(t, opParamPushVM(opcode.DUP, nil, getitems(stackitem.NewStruct(items))...)) 439 }) 440 }) 441 p := stackitem.NewPointer(0, zeroSlice(1024)) 442 t.Run("pointer", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.DUP, nil, getitems(p)...)) }) 443 }) 444 } 445 446 var swappers = []struct { 447 op opcode.Opcode 448 num int 449 }{ 450 {opcode.SWAP, 2}, 451 {opcode.ROT, 3}, 452 {opcode.ROLL, 4}, 453 {opcode.ROLL, 1024}, 454 {opcode.REVERSE3, 3}, 455 {opcode.REVERSE4, 4}, 456 {opcode.REVERSEN, 5}, 457 {opcode.REVERSEN, 1024}, 458 } 459 for _, sw := range swappers { 460 var name = sw.op.String() 461 if sw.op == opcode.ROLL || sw.op == opcode.REVERSEN { 462 name += "/" + strconv.Itoa(sw.num) 463 } 464 var getitems = func(element any) []any { 465 l := sw.num 466 if sw.op == opcode.ROLL || sw.op == opcode.REVERSEN { 467 l++ 468 } 469 var items = make([]any, l) 470 for i := range items { 471 items[i] = element 472 } 473 if sw.op == opcode.ROLL || sw.op == opcode.REVERSEN { 474 items[len(items)-1] = sw.num - 1 475 } 476 return items 477 } 478 t.Run(name, func(t *testing.B) { 479 t.Run("null", func(t *testing.B) { 480 benchOpcode(t, opParamPushVM(sw.op, nil, getitems(stackitem.Null{})...)) 481 }) 482 t.Run("integer", func(t *testing.B) { benchOpcode(t, opParamPushVM(sw.op, nil, getitems(0)...)) }) 483 t.Run("big bytes", func(t *testing.B) { 484 benchOpcode(t, opParamPushVM(sw.op, nil, getitems(zeroSlice(65536))...)) 485 }) 486 }) 487 } 488 489 t.Run("INITSSLOT", func(t *testing.B) { 490 t.Run("1", func(t *testing.B) { benchOpcode(t, opParamVM(opcode.INITSSLOT, []byte{1})) }) 491 t.Run("255", func(t *testing.B) { benchOpcode(t, opParamVM(opcode.INITSSLOT, []byte{255})) }) 492 }) 493 t.Run("INITSLOT", func(t *testing.B) { 494 t.Run("1/1", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.INITSLOT, []byte{1, 1}, 0)) }) 495 t.Run("1/255", func(t *testing.B) { 496 benchOpcode(t, opParamPushVM(opcode.INITSLOT, []byte{1, 255}, arrayOfIfaces(255)...)) 497 }) 498 t.Run("255/1", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.INITSLOT, []byte{255, 1}, 0)) }) 499 t.Run("255/255", func(t *testing.B) { 500 benchOpcode(t, opParamPushVM(opcode.INITSLOT, []byte{255, 255}, arrayOfIfaces(255)...)) 501 }) 502 }) 503 t.Run("LDSFLD0", func(t *testing.B) { benchOpcode(t, opParamSlotsPushVM(opcode.LDSFLD0, nil, 1, 0, 0)) }) 504 t.Run("LDSFLD254", func(t *testing.B) { benchOpcode(t, opParamSlotsPushVM(opcode.LDSFLD, []byte{254}, 255, 0, 0)) }) 505 t.Run("STSFLD0", func(t *testing.B) { benchOpcode(t, opParamSlotsPushVM(opcode.STSFLD0, nil, 1, 0, 0, 0)) }) 506 t.Run("STSFLD254", func(t *testing.B) { benchOpcode(t, opParamSlotsPushVM(opcode.STSFLD, []byte{254}, 255, 0, 0, 0)) }) 507 t.Run("LDLOC0", func(t *testing.B) { benchOpcode(t, opParamSlotsPushVM(opcode.LDLOC0, nil, 0, 1, 1)) }) 508 t.Run("LDLOC254", func(t *testing.B) { benchOpcode(t, opParamSlotsPushVM(opcode.LDLOC, []byte{254}, 0, 255, 255)) }) 509 t.Run("STLOC0", func(t *testing.B) { benchOpcode(t, opParamSlotsPushVM(opcode.STLOC0, nil, 0, 1, 1, 0)) }) 510 t.Run("STLOC254", func(t *testing.B) { benchOpcode(t, opParamSlotsPushVM(opcode.STLOC, []byte{254}, 0, 255, 255, 0)) }) 511 t.Run("LDARG0", func(t *testing.B) { benchOpcode(t, opParamSlotsPushVM(opcode.LDARG0, nil, 0, 1, 1)) }) 512 t.Run("LDARG254", func(t *testing.B) { benchOpcode(t, opParamSlotsPushVM(opcode.LDARG, []byte{254}, 0, 255, 255)) }) 513 t.Run("STARG0", func(t *testing.B) { benchOpcode(t, opParamSlotsPushVM(opcode.STARG0, nil, 0, 1, 1, 0)) }) 514 t.Run("STARG254", func(t *testing.B) { benchOpcode(t, opParamSlotsPushVM(opcode.STARG, []byte{254}, 0, 255, 255, 0)) }) 515 516 t.Run("NEWBUFFER", func(t *testing.B) { 517 t.Run("1", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.NEWBUFFER, nil, 1)) }) 518 t.Run("255", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.NEWBUFFER, nil, 255)) }) 519 t.Run("64K", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.NEWBUFFER, nil, 65536)) }) 520 t.Run("1M", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.NEWBUFFER, nil, 1024*1024)) }) 521 }) 522 t.Run("MEMCPY", func(t *testing.B) { 523 buf1 := maxBuf() 524 buf2 := maxBuf() 525 526 t.Run("1", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.MEMCPY, nil, buf1, 0, buf2, 0, 1)) }) 527 t.Run("255", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.MEMCPY, nil, buf1, 0, buf2, 0, 255)) }) 528 t.Run("64K", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.MEMCPY, nil, buf1, 0, buf2, 0, 65536)) }) 529 t.Run("1M", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.MEMCPY, nil, buf1, 0, buf2, 0, 1024*1024)) }) 530 }) 531 t.Run("CAT", func(t *testing.B) { 532 t.Run("1+1", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.CAT, nil, zeroSlice(1), zeroSlice(1))) }) 533 t.Run("256+256", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.CAT, nil, zeroSlice(255), zeroSlice(255))) }) 534 t.Run("64K+64K", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.CAT, nil, zeroSlice(65536), zeroSlice(65536))) }) 535 t.Run("512K+512K", func(t *testing.B) { 536 benchOpcode(t, opParamPushVM(opcode.CAT, nil, zeroSlice(512*1024), zeroSlice(512*1024))) 537 }) 538 }) 539 t.Run("SUBSTR", func(t *testing.B) { 540 buf := stackitem.NewBuffer(zeroSlice(1024 * 1024)) 541 542 t.Run("1", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.SUBSTR, nil, buf, 0, 1)) }) 543 t.Run("256", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.SUBSTR, nil, buf, 0, 256)) }) 544 t.Run("64K", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.SUBSTR, nil, buf, 0, 65536)) }) 545 t.Run("1M", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.SUBSTR, nil, buf, 0, 1024*1024)) }) 546 }) 547 t.Run("LEFT", func(t *testing.B) { 548 buf := stackitem.NewBuffer(zeroSlice(1024 * 1024)) 549 550 t.Run("1", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.LEFT, nil, buf, 1)) }) 551 t.Run("256", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.LEFT, nil, buf, 256)) }) 552 t.Run("64K", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.LEFT, nil, buf, 65536)) }) 553 t.Run("1M", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.LEFT, nil, buf, 1024*1024)) }) 554 }) 555 t.Run("RIGHT", func(t *testing.B) { 556 buf := stackitem.NewBuffer(zeroSlice(1024 * 1024)) 557 558 t.Run("1", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.RIGHT, nil, buf, 1)) }) 559 t.Run("256", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.RIGHT, nil, buf, 256)) }) 560 t.Run("64K", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.RIGHT, nil, buf, 65536)) }) 561 t.Run("1M", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.RIGHT, nil, buf, 1024*1024)) }) 562 }) 563 unaries := []opcode.Opcode{opcode.INVERT, opcode.SIGN, opcode.ABS, opcode.NEGATE, opcode.INC, opcode.DEC, opcode.NOT, opcode.NZ} 564 for _, op := range unaries { 565 t.Run(op.String(), func(t *testing.B) { 566 t.Run("1", func(t *testing.B) { benchOpcode(t, opParamPushVM(op, nil, 1)) }) 567 t.Run("0", func(t *testing.B) { benchOpcode(t, opParamPushVM(op, nil, 0)) }) 568 t.Run("big", func(t *testing.B) { benchOpcode(t, opParamPushVM(op, nil, bigNumber())) }) 569 t.Run("big negative", func(t *testing.B) { benchOpcode(t, opParamPushVM(op, nil, bigNegNumber())) }) 570 }) 571 } 572 binaries := []opcode.Opcode{opcode.AND, opcode.OR, opcode.XOR, opcode.ADD, opcode.SUB, 573 opcode.BOOLAND, opcode.BOOLOR, opcode.NUMEQUAL, opcode.NUMNOTEQUAL, 574 opcode.LT, opcode.LE, opcode.GT, opcode.GE, opcode.MIN, opcode.MAX} 575 for _, op := range binaries { 576 t.Run(op.String(), func(t *testing.B) { 577 t.Run("0+0", func(t *testing.B) { benchOpcode(t, opParamPushVM(op, nil, 0, 0)) }) 578 t.Run("1+1", func(t *testing.B) { benchOpcode(t, opParamPushVM(op, nil, 1, 1)) }) 579 t.Run("1/big", func(t *testing.B) { benchOpcode(t, opParamPushVM(op, nil, 1, bigNumber())) }) 580 t.Run("big/big", func(t *testing.B) { benchOpcode(t, opParamPushVM(op, nil, bigNumber(), bigNumber())) }) 581 t.Run("big/bigneg", func(t *testing.B) { benchOpcode(t, opParamPushVM(op, nil, bigNumber(), bigNegNumber())) }) 582 }) 583 } 584 equals := []opcode.Opcode{opcode.EQUAL, opcode.NOTEQUAL} 585 for _, op := range equals { 586 t.Run(op.String(), func(t *testing.B) { 587 t.Run("bools", func(t *testing.B) { benchOpcode(t, opParamPushVM(op, nil, true, false)) }) 588 t.Run("small integers", func(t *testing.B) { benchOpcode(t, opParamPushVM(op, nil, 1, 0)) }) 589 t.Run("big integers", func(t *testing.B) { benchOpcode(t, opParamPushVM(op, nil, bigNumber(), bigNegNumber())) }) 590 t.Run("255B", func(t *testing.B) { benchOpcode(t, opParamPushVM(op, nil, zeroSlice(255), zeroSlice(255))) }) 591 t.Run("64KEQ", func(t *testing.B) { benchOpcode(t, opParamPushVM(op, nil, zeroSlice(65535), zeroSlice(65535))) }) 592 t.Run("64KNEQ", func(t *testing.B) { benchOpcode(t, opParamPushVM(op, nil, zeroSlice(65535), ffSlice(65535))) }) 593 }) 594 } 595 t.Run(opcode.MUL.String(), func(t *testing.B) { 596 t.Run("1+0", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.MUL, nil, 1, 0)) }) 597 t.Run("100/big", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.MUL, nil, 100, bigNumber())) }) 598 t.Run("16ff*16ff", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.MUL, nil, ffSlice(16), ffSlice(16))) }) 599 }) 600 t.Run(opcode.DIV.String(), func(t *testing.B) { 601 t.Run("0/1", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.DIV, nil, 0, 1)) }) 602 t.Run("big/100", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.DIV, nil, bigNumber(), 100)) }) 603 t.Run("bigneg/big", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.DIV, nil, bigNumber(), bigNegNumber())) }) 604 }) 605 t.Run(opcode.MOD.String(), func(t *testing.B) { 606 t.Run("1+1", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.MOD, nil, 1, 1)) }) 607 t.Run("big/100", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.MOD, nil, bigNumber(), 100)) }) 608 t.Run("big/bigneg", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.MOD, nil, bigNumber(), bigNegNumber())) }) 609 }) 610 t.Run(opcode.SHL.String(), func(t *testing.B) { 611 t.Run("1/1", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.SHL, nil, 1, 1)) }) 612 t.Run("1/254", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.SHL, nil, 1, 254)) }) 613 t.Run("big/7", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.SHL, nil, bigNumber(), 7)) }) 614 t.Run("bigneg/7", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.SHL, nil, bigNegNumber(), 7)) }) 615 t.Run("16ff/15", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.SHL, nil, ffSlice(16), 15)) }) 616 }) 617 t.Run(opcode.SHR.String(), func(t *testing.B) { 618 t.Run("1/1", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.SHR, nil, 1, 1)) }) 619 t.Run("1/254", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.SHR, nil, 1, 254)) }) 620 t.Run("big/254", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.SHR, nil, bigNumber(), 254)) }) 621 t.Run("bigneg/7", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.SHR, nil, bigNegNumber(), 7)) }) 622 t.Run("16ff/15", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.SHR, nil, ffSlice(16), 15)) }) 623 }) 624 t.Run(opcode.WITHIN.String(), func(t *testing.B) { 625 t.Run("0/1/2", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.WITHIN, nil, 1, 0, 2)) }) 626 t.Run("bigNeg/1/big", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.WITHIN, nil, 1, bigNegNumber(), bigNumber())) }) 627 t.Run("bigNeg/big/max", func(t *testing.B) { 628 benchOpcode(t, opParamPushVM(opcode.WITHIN, nil, bigNumber(), bigNegNumber(), maxNumber())) 629 }) 630 }) 631 var newrefs = []opcode.Opcode{opcode.NEWARRAY0, opcode.NEWSTRUCT0, opcode.NEWMAP} 632 for _, op := range newrefs { 633 t.Run(op.String(), func(t *testing.B) { benchOpcode(t, opVM(op)) }) 634 } 635 var newcountedrefs = []opcode.Opcode{opcode.NEWARRAY, opcode.NEWSTRUCT} 636 for _, op := range newcountedrefs { 637 var nums = []int{1, 255, 1024} 638 t.Run(op.String(), func(t *testing.B) { 639 for _, n := range nums { 640 t.Run(strconv.Itoa(n), func(t *testing.B) { benchOpcode(t, opParamPushVM(op, nil, n)) }) 641 } 642 }) 643 } 644 t.Run("NEWARRAYT", func(t *testing.B) { 645 var nums = []int{1, 255, 1024} 646 var types = []stackitem.Type{stackitem.AnyT, stackitem.PointerT, stackitem.BooleanT, 647 stackitem.IntegerT, stackitem.ByteArrayT, stackitem.BufferT, stackitem.ArrayT, 648 stackitem.StructT, stackitem.MapT, stackitem.InteropT} 649 for _, n := range nums { 650 for _, typ := range types { 651 t.Run(typ.String()+"/"+strconv.Itoa(n), func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.NEWARRAYT, []byte{byte(typ)}, n)) }) 652 } 653 } 654 }) 655 t.Run("PACK", func(t *testing.B) { 656 var nums = []int{1, 255, 1024} 657 for _, n := range nums { 658 t.Run(strconv.Itoa(n), func(t *testing.B) { 659 var elems = make([]any, n+1) 660 for i := range elems { 661 elems[i] = 0 662 } 663 elems[n] = n 664 benchOpcode(t, opParamPushVM(opcode.PACK, nil, elems...)) 665 }) 666 } 667 }) 668 t.Run("UNPACK", func(t *testing.B) { 669 var nums = []int{1, 255, 1024} 670 for _, n := range nums { 671 t.Run(strconv.Itoa(n), func(t *testing.B) { 672 var elems = make([]stackitem.Item, n) 673 for i := range elems { 674 elems[i] = stackitem.Make(1) 675 } 676 benchOpcode(t, opParamPushVM(opcode.UNPACK, nil, elems)) 677 }) 678 } 679 }) 680 t.Run("SIZE", func(t *testing.B) { 681 var elems = arrayOfOnes(1024) 682 var buf = maxBytes() 683 t.Run("array/1", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.SIZE, nil, elems[:1])) }) 684 t.Run("array/1024", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.SIZE, nil, elems)) }) 685 t.Run("map/1024", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.SIZE, nil, bigMap())) }) 686 t.Run("bytes/255", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.SIZE, nil, buf[:255])) }) 687 t.Run("bytes/64K", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.SIZE, nil, buf[:65536])) }) 688 t.Run("bytes/1M", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.SIZE, nil, buf)) }) 689 }) 690 t.Run("HASKEY", func(t *testing.B) { 691 var elems = arrayOfOnes(1024) 692 var buf = maxBuf() 693 t.Run("array/1", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.HASKEY, nil, elems, 1)) }) 694 t.Run("array/1023", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.HASKEY, nil, elems, 1023)) }) 695 t.Run("array/1024", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.HASKEY, nil, elems, 1024)) }) 696 t.Run("map/1", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.HASKEY, nil, bigMap(), 1)) }) 697 t.Run("map/1023", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.HASKEY, nil, bigMap(), 1023)) }) 698 t.Run("map/1024", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.HASKEY, nil, bigMap(), 1024)) }) 699 t.Run("buffer/255", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.HASKEY, nil, buf, 255)) }) 700 t.Run("buffer/64K", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.HASKEY, nil, buf, 65536)) }) 701 t.Run("buffer/1M", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.HASKEY, nil, buf, 1024*1024)) }) 702 }) 703 t.Run("KEYS", func(t *testing.B) { 704 t.Run("map/1024", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.KEYS, nil, bigMap())) }) 705 }) 706 t.Run("VALUES", func(t *testing.B) { 707 var elems = arrayOfOnes(1024) 708 t.Run("array/1", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.VALUES, nil, elems[:1])) }) 709 t.Run("array/1024", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.VALUES, nil, elems)) }) 710 t.Run("map/1024", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.VALUES, nil, bigMap())) }) 711 }) 712 t.Run("PICKITEM", func(t *testing.B) { 713 var elems = arrayOfOnes(1024) 714 var buf = maxBytes() 715 t.Run("array/1", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.PICKITEM, nil, elems, 1)) }) 716 t.Run("array/1023", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.PICKITEM, nil, elems, 1023)) }) 717 t.Run("map/1", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.PICKITEM, nil, bigMap(), 1)) }) 718 t.Run("map/1023", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.PICKITEM, nil, bigMap(), 1023)) }) 719 t.Run("bytes/255", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.PICKITEM, nil, buf, 255)) }) 720 t.Run("bytes/64K", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.PICKITEM, nil, buf, 65536)) }) 721 t.Run("bytes/1M", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.PICKITEM, nil, buf, 1024*1024-1)) }) 722 }) 723 t.Run("APPEND", func(t *testing.B) { 724 var a0 = arrayOfOnes(0) 725 var a1023 = arrayOfOnes(1023) 726 t.Run("array/1", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.APPEND, nil, a0, 1)) }) 727 t.Run("array/1023", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.APPEND, nil, a1023, 1)) }) 728 t.Run("struct/1", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.APPEND, nil, stackitem.NewStruct(a0), 1)) }) 729 t.Run("struct/1023", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.APPEND, nil, stackitem.NewStruct(a1023), 1)) }) 730 t.Run("array/struct", func(t *testing.B) { 731 benchOpcode(t, opParamPushVM(opcode.APPEND, nil, a1023, stackitem.NewStruct(a1023))) 732 }) 733 }) 734 t.Run("SETITEM", func(t *testing.B) { 735 var elems = arrayOfOnes(1024) 736 var buf = maxBuf() 737 t.Run("array/1", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.SETITEM, nil, elems, 1, 1)) }) 738 t.Run("array/1023", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.SETITEM, nil, elems, 1023, 1)) }) 739 t.Run("map/1", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.SETITEM, nil, bigMap(), 1, 1)) }) 740 t.Run("map/1023", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.SETITEM, nil, bigMap(), 1023, 1)) }) 741 t.Run("buffer/255", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.SETITEM, nil, buf, 255, 1)) }) 742 t.Run("buffer/1M", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.SETITEM, nil, buf, 1024*1024-1, 1)) }) 743 }) 744 745 t.Run("REVERSEITEMS", func(t *testing.B) { 746 var elems = arrayOfOnes(1024) 747 var buf = maxBuf() 748 t.Run("array/1024", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.REVERSEITEMS, nil, elems)) }) 749 t.Run("buffer/1M", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.REVERSEITEMS, nil, buf)) }) 750 }) 751 752 t.Run("REMOVE", func(t *testing.B) { 753 var elems = arrayOfOnes(1024) 754 t.Run("array/1", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.REMOVE, nil, elems, 1)) }) 755 t.Run("array/255", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.REMOVE, nil, elems, 255)) }) 756 t.Run("array/1023", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.REMOVE, nil, elems, 1023)) }) 757 t.Run("map/1", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.REMOVE, nil, bigMap(), 1)) }) 758 t.Run("map/255", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.REMOVE, nil, bigMap(), 255)) }) 759 t.Run("map/1023", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.REMOVE, nil, bigMap(), 1023)) }) 760 }) 761 t.Run("CLEARITEMS", func(t *testing.B) { 762 t.Run("array/1024", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.CLEARITEMS, nil, arrayOfOnes(1024))) }) 763 t.Run("map/1024", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.CLEARITEMS, nil, bigMap())) }) 764 }) 765 766 t.Run("ISNULL", func(t *testing.B) { 767 t.Run("null", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.ISNULL, nil, stackitem.Null{})) }) 768 t.Run("integer", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.ISNULL, nil, 1)) }) 769 }) 770 t.Run("ISTYPE", func(t *testing.B) { 771 t.Run("null/null", func(t *testing.B) { 772 benchOpcode(t, opParamPushVM(opcode.ISTYPE, []byte{byte(stackitem.AnyT)}, stackitem.Null{})) 773 }) 774 t.Run("integer/integer", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.ISTYPE, []byte{byte(stackitem.IntegerT)}, 1)) }) 775 t.Run("null/integer", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.ISTYPE, []byte{byte(stackitem.AnyT)}, 1)) }) 776 }) 777 t.Run("CONVERT", func(t *testing.B) { 778 t.Run("bytes/integer", func(t *testing.B) { 779 benchOpcode(t, opParamPushVM(opcode.CONVERT, []byte{byte(stackitem.IntegerT)}, "1012345678901234567890123456789")) 780 }) 781 t.Run("integer/bytes", func(t *testing.B) { 782 benchOpcode(t, opParamPushVM(opcode.CONVERT, []byte{byte(stackitem.ByteArrayT)}, maxNumber())) 783 }) 784 t.Run("array/struct", func(t *testing.B) { 785 benchOpcode(t, opParamPushVM(opcode.CONVERT, []byte{byte(stackitem.StructT)}, arrayOfOnes(1024))) 786 }) 787 }) 788 }