From 47a3130f543703ffc100f0aeaf5e6e80ad776e13 Mon Sep 17 00:00:00 2001 From: Drahoslav Date: Tue, 5 Jun 2018 21:51:36 +0200 Subject: [PATCH 1/4] Minor change in edge event detection api Also other minor changes and gofmt --- rpio_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/rpio_test.go b/rpio_test.go index 23e40fa..c20001e 100644 --- a/rpio_test.go +++ b/rpio_test.go @@ -117,4 +117,5 @@ func TestEvent(t *testing.T) { } }) + } From a69ebca5eaebf84399703f8ceeb40e0b197bfade Mon Sep 17 00:00:00 2001 From: Drahoslav Date: Tue, 5 Jun 2018 23:18:07 +0200 Subject: [PATCH 2/4] Improve performance of pintoggle --- rpio.go | 25 +++++++++++++++++-------- rpio_test.go | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 8 deletions(-) diff --git a/rpio.go b/rpio.go index 155766c..e9abf79 100644 --- a/rpio.go +++ b/rpio.go @@ -284,10 +284,10 @@ func PinMode(pin Pin, mode Mode) { func WritePin(pin Pin, state State) { p := uint8(pin) - // Clear register, 10 / 11 depending on bank // Set register, 7 / 8 depending on bank - clearReg := p/32 + 10 + // Clear register, 10 / 11 depending on bank setReg := p/32 + 7 + clearReg := p/32 + 10 memlock.Lock() defer memlock.Unlock() @@ -312,14 +312,23 @@ func ReadPin(pin Pin) State { } // Toggle a pin state (high -> low -> high) -// TODO: probably possible to do this much faster without read func TogglePin(pin Pin) { - switch ReadPin(pin) { - case Low: - pin.High() - case High: - pin.Low() + p := uint8(pin) + + setReg := p/32 + 7 + clearReg := p/32 + 10 + levelReg := p/32 + 13 + + bit := uint32(1 << (p & 31)) + + memlock.Lock() + + if (gpioMem[levelReg] & bit) != 0 { + gpioMem[clearReg] = bit + } else { + gpioMem[setReg] = bit } + memlock.Unlock() } // Enable edge event detection on pin. diff --git a/rpio_test.go b/rpio_test.go index c20001e..5aef4c4 100644 --- a/rpio_test.go +++ b/rpio_test.go @@ -119,3 +119,35 @@ func TestEvent(t *testing.T) { }) } + +func BenchmarkToggle(b *testing.B) { + src := Pin(3) + src.Mode(Output) + src.Low() + + pin := Pin(2) + pin.Mode(Input) + pin.PullDown() + + oldToggle := func(pin Pin) { + switch ReadPin(pin) { + case Low: + pin.High() + case High: + pin.Low() + } + } + + b.Run("old toggle", func(b *testing.B) { + for i := 0; i < b.N; i++ { + oldToggle(src) + } + }) + + b.Run("current toggle", func(b *testing.B) { + for i := 0; i < b.N; i++ { + TogglePin(src) + } + }) + +} From b1b8e257128a8cb7539d80287bbf5f4d9cb9b1ac Mon Sep 17 00:00:00 2001 From: Drahoslav Date: Wed, 6 Jun 2018 00:28:17 +0200 Subject: [PATCH 3/4] Improve performance of WritePin --- rpio.go | 2 +- rpio_test.go | 69 +++++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 59 insertions(+), 12 deletions(-) diff --git a/rpio.go b/rpio.go index e9abf79..e453c80 100644 --- a/rpio.go +++ b/rpio.go @@ -290,13 +290,13 @@ func WritePin(pin Pin, state State) { clearReg := p/32 + 10 memlock.Lock() - defer memlock.Unlock() if state == Low { gpioMem[clearReg] = 1 << (p & 31) } else { gpioMem[setReg] = 1 << (p & 31) } + memlock.Unlock() // not deferring saves ~600ns } // Read the state of a pin diff --git a/rpio_test.go b/rpio_test.go index 5aef4c4..bd98eb2 100644 --- a/rpio_test.go +++ b/rpio_test.go @@ -129,25 +129,72 @@ func BenchmarkToggle(b *testing.B) { pin.Mode(Input) pin.PullDown() - oldToggle := func(pin Pin) { - switch ReadPin(pin) { - case Low: - pin.High() - case High: - pin.Low() - } - } - - b.Run("old toggle", func(b *testing.B) { + b.Run("old", func(b *testing.B) { for i := 0; i < b.N; i++ { oldToggle(src) } }) - b.Run("current toggle", func(b *testing.B) { + b.Run("current", func(b *testing.B) { for i := 0; i < b.N; i++ { TogglePin(src) } }) } + +func BenchmarkWrite(b *testing.B) { + src := Pin(3) + src.Mode(Output) + src.Low() + + pin := Pin(2) + pin.Mode(Input) + pin.PullDown() + + b.Run("old", func(b *testing.B) { + for i := 0; i < b.N; i++ { + if i%2 == 0 { + oldWrite(src, High) + } else { + oldWrite(src, Low) + } + } + }) + + b.Run("current", func(b *testing.B) { + for i := 0; i < b.N; i++ { + if i%2 == 0 { + WritePin(src, High) + } else { + WritePin(src, Low) + } + } + }) + +} + +func oldToggle(pin Pin) { + switch ReadPin(pin) { + case Low: + oldWrite(pin, High) + case High: + oldWrite(pin, Low) + } +} + +func oldWrite(pin Pin, state State) { + p := uint8(pin) + + setReg := p/32 + 7 + clearReg := p/32 + 10 + + memlock.Lock() + defer memlock.Unlock() + + if state == Low { + gpioMem[clearReg] = 1 << (p & 31) + } else { + gpioMem[setReg] = 1 << (p & 31) + } +} From 6c29b5003337ba98b076fe663185107cef65210b Mon Sep 17 00:00:00 2001 From: Drahoslav Date: Wed, 6 Jun 2018 00:41:50 +0200 Subject: [PATCH 4/4] Update benchmark --- rpio_test.go | 123 ++++++++++++++++++++++++--------------------------- 1 file changed, 58 insertions(+), 65 deletions(-) diff --git a/rpio_test.go b/rpio_test.go index bd98eb2..d534f5f 100644 --- a/rpio_test.go +++ b/rpio_test.go @@ -120,7 +120,7 @@ func TestEvent(t *testing.T) { } -func BenchmarkToggle(b *testing.B) { +func BenchmarkGpio(b *testing.B) { src := Pin(3) src.Mode(Output) src.Low() @@ -129,72 +129,65 @@ func BenchmarkToggle(b *testing.B) { pin.Mode(Input) pin.PullDown() - b.Run("old", func(b *testing.B) { - for i := 0; i < b.N; i++ { - oldToggle(src) + oldWrite := func(pin Pin, state State) { + p := uint8(pin) + + setReg := p/32 + 7 + clearReg := p/32 + 10 + + memlock.Lock() + defer memlock.Unlock() + + if state == Low { + gpioMem[clearReg] = 1 << (p & 31) + } else { + gpioMem[setReg] = 1 << (p & 31) } - }) - - b.Run("current", func(b *testing.B) { - for i := 0; i < b.N; i++ { - TogglePin(src) - } - }) - -} - -func BenchmarkWrite(b *testing.B) { - src := Pin(3) - src.Mode(Output) - src.Low() - - pin := Pin(2) - pin.Mode(Input) - pin.PullDown() - - b.Run("old", func(b *testing.B) { - for i := 0; i < b.N; i++ { - if i%2 == 0 { - oldWrite(src, High) - } else { - oldWrite(src, Low) - } - } - }) - - b.Run("current", func(b *testing.B) { - for i := 0; i < b.N; i++ { - if i%2 == 0 { - WritePin(src, High) - } else { - WritePin(src, Low) - } - } - }) - -} - -func oldToggle(pin Pin) { - switch ReadPin(pin) { - case Low: - oldWrite(pin, High) - case High: - oldWrite(pin, Low) } -} -func oldWrite(pin Pin, state State) { - p := uint8(pin) - - setReg := p/32 + 7 - clearReg := p/32 + 10 - - memlock.Lock() - defer memlock.Unlock() - - if state == Low { - gpioMem[clearReg] = 1 << (p & 31) - } else { - gpioMem[setReg] = 1 << (p & 31) + oldToggle := func(pin Pin) { + switch ReadPin(pin) { + case Low: + oldWrite(pin, High) + case High: + oldWrite(pin, Low) + } } + + b.Run("write", func(b *testing.B) { + b.Run("old", func(b *testing.B) { + for i := 0; i < b.N; i++ { + if i%2 == 0 { + oldWrite(src, High) + } else { + oldWrite(src, Low) + } + } + }) + + b.Run("new", func(b *testing.B) { + for i := 0; i < b.N; i++ { + if i%2 == 0 { + WritePin(src, High) + } else { + WritePin(src, Low) + } + } + }) + }) + + b.Run("toggle", func(b *testing.B) { + b.Run("old", func(b *testing.B) { + for i := 0; i < b.N; i++ { + oldToggle(src) + } + }) + + b.Run("new", func(b *testing.B) { + for i := 0; i < b.N; i++ { + TogglePin(src) + } + }) + }) + }