From 192d30c88d879d1f4a1b15b6753c342126f27fd3 Mon Sep 17 00:00:00 2001 From: Rodrigo Date: Mon, 23 Oct 2023 13:03:05 -0400 Subject: [PATCH 1/2] Minor optimization infer res --- pkg/vm/memory/memory.go | 17 ++++++++++++++++- pkg/vm/vm.go | 19 +++++++------------ 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/pkg/vm/memory/memory.go b/pkg/vm/memory/memory.go index f5d6c0629..e2faada04 100644 --- a/pkg/vm/memory/memory.go +++ b/pkg/vm/memory/memory.go @@ -115,7 +115,7 @@ func (segment *Segment) Read(offset uint64) (MemoryValue, error) { func (segment *Segment) Peek(offset uint64) MemoryValue { if offset >= segment.RealLen() { - segment.IncreaseSegmentSize(offset + 1) + return UnknownValue } return segment.Data[offset] } @@ -268,6 +268,21 @@ func (memory *Memory) PeekFromAddress(address *MemoryAddress) (MemoryValue, erro return memory.Peek(address.SegmentIndex, address.Offset) } +// Given a segment index and offset returns true if the value at that address +// is known +func (memory *Memory) KnownValue(segment uint64, offset uint64) bool { + if segment >= uint64(len(memory.Segments)) || + offset >= uint64(len(memory.Segments[segment].Data)) { + return false + } + return memory.Segments[segment].Data[offset].Known() +} + +// Given an address returns true if it contains a known value +func (memory *Memory) KnownValueAtAddress(address *MemoryAddress) bool { + return memory.KnownValue(address.SegmentIndex, address.Offset) +} + // It returns all segment offsets and max memory used func (memory *Memory) RelocationOffsets() ([]uint64, uint64) { // Prover expects maxMemoryUsed to start at one diff --git a/pkg/vm/vm.go b/pkg/vm/vm.go index b44c92bbf..a368c5cef 100644 --- a/pkg/vm/vm.go +++ b/pkg/vm/vm.go @@ -162,7 +162,7 @@ func (vm *VirtualMachine) RunInstruction(instruction *a.Instruction) error { res, err := vm.inferOperand(instruction, &dstAddr, &op0Addr, &op1Addr) if err != nil { - return fmt.Errorf("res infer: %w", err) + return fmt.Errorf("infer res: %w", err) } if !res.Known() { res, err = vm.computeRes(instruction, &op0Addr, &op1Addr) @@ -261,11 +261,11 @@ func (vm *VirtualMachine) getOp1Addr(instruction *a.Instruction, op0Addr *mem.Me op1Address = vm.Context.AddressAp() } - addr, isOverflow := safemath.SafeOffset(op1Address.Offset, instruction.OffOp1) + newOffset, isOverflow := safemath.SafeOffset(op1Address.Offset, instruction.OffOp1) if isOverflow { return mem.UnknownAddress, fmt.Errorf("offset overflow: %d + %d", op1Address.Offset, instruction.OffOp1) } - op1Address.Offset = addr + op1Address.Offset = newOffset return op1Address, nil } @@ -277,18 +277,13 @@ func (vm *VirtualMachine) inferOperand( instruction *a.Instruction, dstAddr *mem.MemoryAddress, op0Addr *mem.MemoryAddress, op1Addr *mem.MemoryAddress, ) (mem.MemoryValue, error) { if instruction.Opcode != a.OpCodeAssertEq || - (instruction.Res == a.Unconstrained) { + instruction.Res == a.Unconstrained || + !vm.Memory.KnownValueAtAddress(dstAddr) { return mem.MemoryValue{}, nil } - dstValue, err := vm.Memory.PeekFromAddress(dstAddr) - if err != nil { - return mem.MemoryValue{}, fmt.Errorf("cannot read dst: %w", err) - } - - if !dstValue.Known() { - return mem.MemoryValue{}, nil // let computeRes try to handle it - } + // we known dst value is known due to previous check + dstValue, _ := vm.Memory.PeekFromAddress(dstAddr) op0Value, err := vm.Memory.PeekFromAddress(op0Addr) if err != nil { From 3ad30fb1c031e5d738f5413556dcbd79bfe6f9c0 Mon Sep 17 00:00:00 2001 From: Rodrigo Date: Mon, 23 Oct 2023 17:12:39 -0400 Subject: [PATCH 2/2] Add assert equal benchmarks --- pkg/vm/vm_benchmark_test.go | 124 ++++++++++++++++++++++++++++++++++++ 1 file changed, 124 insertions(+) create mode 100644 pkg/vm/vm_benchmark_test.go diff --git a/pkg/vm/vm_benchmark_test.go b/pkg/vm/vm_benchmark_test.go new file mode 100644 index 000000000..93eecc525 --- /dev/null +++ b/pkg/vm/vm_benchmark_test.go @@ -0,0 +1,124 @@ +package vm + +import ( + "testing" +) + +func BenchmarkAssertEqual(b *testing.B) { + b.Run("assign left to rigth", func(b *testing.B) { + vm := defaultVirtualMachineWithCode(` + [ap] = [ap - 1], ap++; + `) + writeToDataSegment(vm, 1, 3) + vm.Context.Ap = 2 + vm.Context.Fp = 2 + + noHr := noHintRunner{} + b.ResetTimer() + for i := 0; i < b.N; i++ { + if err := vm.RunStep(&noHr); err != nil { + b.Error(err) + break + } + vm.Context.Pc.Offset-- + } + }) + b.Run("assign right to left", func(b *testing.B) { + vm := defaultVirtualMachineWithCode(` + [ap - 1] = [ap], ap++; + `) + writeToDataSegment(vm, 1, 3) + vm.Context.Ap = 2 + vm.Context.Fp = 2 + + noHr := noHintRunner{} + b.ResetTimer() + for i := 0; i < b.N; i++ { + if err := vm.RunStep(&noHr); err != nil { + b.Error(err) + break + } + vm.Context.Pc.Offset-- + } + }) + b.Run("addition", func(b *testing.B) { + vm := defaultVirtualMachineWithCode(` + [ap] = [ap - 1] + [ap - 2], ap++; + `) + writeToDataSegment(vm, 0, 1) + writeToDataSegment(vm, 1, 1) + vm.Context.Ap = 2 + vm.Context.Fp = 2 + + noHr := noHintRunner{} + b.ResetTimer() + for i := 0; i < b.N; i++ { + if err := vm.RunStep(&noHr); err != nil { + b.Error(err) + break + } + vm.Context.Pc.Offset-- + } + }) + b.Run("substraction", func(b *testing.B) { + vm := defaultVirtualMachineWithCode(` + [ap] = [ap - 1] + [ap - 2]; + [ap + 2] = [ap - 1]; + ap += 2; + `) + writeToDataSegment(vm, 0, 7) + writeToDataSegment(vm, 2, 10) + vm.Context.Ap = 2 + vm.Context.Fp = 2 + + noHr := noHintRunner{} + b.ResetTimer() + for i := 0; i < b.N; i++ { + if err := vm.RunStep(&noHr); err != nil { + b.Error(err) + break + } + vm.Context.Pc.Offset %= 4 + } + }) + b.Run("multiplication", func(b *testing.B) { + vm := defaultVirtualMachineWithCode(` + [ap] = [ap - 1] * [ap - 2] , ap++; + `) + writeToDataSegment(vm, 0, 2) + writeToDataSegment(vm, 1, 3) + vm.Context.Ap = 2 + vm.Context.Fp = 2 + + noHr := noHintRunner{} + b.ResetTimer() + for i := 0; i < b.N; i++ { + if err := vm.RunStep(&noHr); err != nil { + b.Error(err) + break + } + vm.Context.Pc.Offset-- + } + }) + b.Run("divition", func(b *testing.B) { + vm := defaultVirtualMachineWithCode(` + [ap] = [ap - 1] * [ap - 2]; + [ap + 2] = [ap - 1]; + ap += 2; + `) + writeToDataSegment(vm, 0, 4) + writeToDataSegment(vm, 2, 20) + vm.Context.Ap = 2 + vm.Context.Fp = 2 + + noHr := noHintRunner{} + b.ResetTimer() + for i := 0; i < b.N; i++ { + if err := vm.RunStep(&noHr); err != nil { + b.Error(err) + break + } + vm.Context.Pc.Offset %= 4 + } + }) +}