Browse Source

Optimise day 2 some more.

Specify whether the VM uses IO or not, and if not don't create
channels. These are more expensive than I expected, and
pointlessly creating/destroying them thousands of times is
a significant CPU drain.
master
Chris Smith 4 years ago
parent
commit
62c511e66a
Signed by: Chris Smith <chris@chameth.com> GPG Key ID: 3A2D4BBDC4A3C9A9
4 changed files with 21 additions and 12 deletions
  1. 1
    1
      02/main.go
  2. 1
    1
      05/main.go
  3. 17
    8
      intcode/vm.go
  4. 2
    2
      intcode/vm_test.go

+ 1
- 1
02/main.go View File

@@ -39,7 +39,7 @@ func main() {
39 39
 
40 40
 	pool := &sync.Pool{
41 41
 		New: func() interface{} {
42
-			return intcode.NewVirtualMachine(make([]int, len(input)))
42
+			return intcode.NewVirtualMachine(make([]int, len(input)), false)
43 43
 		},
44 44
 	}
45 45
 

+ 1
- 1
05/main.go View File

@@ -22,7 +22,7 @@ func main() {
22 22
 	memory := make([]int, len(input))
23 23
 	copy(memory, input)
24 24
 
25
-	vm := intcode.NewVirtualMachine(memory)
25
+	vm := intcode.NewVirtualMachine(memory, true)
26 26
 	vm.Input <- 1
27 27
 	go vm.Run()
28 28
 	fmt.Println(last(vm.Output))

+ 17
- 8
intcode/vm.go View File

@@ -13,13 +13,11 @@ type VirtualMachine struct {
13 13
 
14 14
 // NewVirtualMachine creates a new IntCode virtual machine, initialised
15 15
 // to the given slice of memory.
16
-func NewVirtualMachine(memory []int) *VirtualMachine {
17
-	return &VirtualMachine{
16
+func NewVirtualMachine(memory []int, hasIO bool) *VirtualMachine {
17
+	vm := &VirtualMachine{
18 18
 		ip:     0,
19 19
 		Memory: memory,
20 20
 		Halted: false,
21
-		Input:  make(chan int, 1),
22
-		Output: make(chan int, 1),
23 21
 		opcodes: [100]interface{}{
24 22
 			1:  AddOpcode,
25 23
 			2:  MulOpcode,
@@ -32,6 +30,13 @@ func NewVirtualMachine(memory []int) *VirtualMachine {
32 30
 			99: HaltOpcode,
33 31
 		},
34 32
 	}
33
+
34
+	if hasIO {
35
+		vm.Input = make(chan int, 1)
36
+		vm.Output = make(chan int, 1)
37
+	}
38
+
39
+	return vm
35 40
 }
36 41
 
37 42
 func (vm *VirtualMachine) arg(pos int) int {
@@ -60,8 +65,10 @@ func (vm *VirtualMachine) Run() {
60 65
 
61 66
 		vm.opcodes[opcode].(OpcodeFunc)(vm)
62 67
 	}
63
-	close(vm.Input)
64
-	close(vm.Output)
68
+	if vm.Input != nil {
69
+		close(vm.Input)
70
+		close(vm.Output)
71
+	}
65 72
 }
66 73
 
67 74
 // Reset resets the memory to the given slice, and all other state back to its original value.
@@ -69,6 +76,8 @@ func (vm *VirtualMachine) Reset(memory []int) {
69 76
 	copy(vm.Memory, memory)
70 77
 	vm.ip = 0
71 78
 	vm.Halted = false
72
-	vm.Input = make(chan int, 1)
73
-	vm.Output = make(chan int, 1)
79
+	if vm.Input != nil {
80
+		vm.Input = make(chan int, 1)
81
+		vm.Output = make(chan int, 1)
82
+	}
74 83
 }

+ 2
- 2
intcode/vm_test.go View File

@@ -17,7 +17,7 @@ func TestDayTwoSamples(t *testing.T) {
17 17
 	}
18 18
 
19 19
 	for _, table := range tables {
20
-		vm := NewVirtualMachine(table.given)
20
+		vm := NewVirtualMachine(table.given, false)
21 21
 		vm.Run()
22 22
 		if !reflect.DeepEqual(table.expected, vm.Memory) {
23 23
 			t.Errorf("Evaluation of %v was incorrect, got: %v, want: %v.", table.given, vm.Memory, table.expected)
@@ -48,7 +48,7 @@ func TestDayFiveSamples(t *testing.T) {
48 48
 	}
49 49
 
50 50
 	for _, table := range tables {
51
-		vm := NewVirtualMachine(table.given)
51
+		vm := NewVirtualMachine(table.given, true)
52 52
 
53 53
 		for _, v := range table.input {
54 54
 			vm.Input <- v

Loading…
Cancel
Save