diff --git a/sysfs/sysfssmoketest/benchmark.go b/sysfs/sysfssmoketest/benchmark.go deleted file mode 100644 index 7dc08aa3..00000000 --- a/sysfs/sysfssmoketest/benchmark.go +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright 2017 The Periph Authors. All rights reserved. -// Use of this source code is governed under the Apache License, Version 2.0 -// that can be found in the LICENSE file. - -package sysfssmoketest - -import ( - "errors" - "flag" - "fmt" - "sort" - - "periph.io/x/conn/v3/gpio" - "periph.io/x/host/v3/sysfs" -) - -// Benchmark is imported by periph-smoketest. -type Benchmark struct { - short bool - p *sysfs.Pin - pull gpio.Pull -} - -// Name implements the SmokeTest interface. -func (s *Benchmark) Name() string { - return "sysfs-benchmark" -} - -// Description implements the SmokeTest interface. -func (s *Benchmark) Description() string { - return "Benchmarks sysfs gpio functionality" -} - -// Run implements the SmokeTest interface. -func (s *Benchmark) Run(f *flag.FlagSet, args []string) error { - num := f.Int("p", -1, "Pin number to use") - f.BoolVar(&s.short, "short", false, "Skip many partially redundant benchmarks") - if err := f.Parse(args); err != nil { - return err - } - - if f.NArg() != 0 { - f.Usage() - return errors.New("unsupported flags") - } - if *num == -1 { - f.Usage() - return errors.New("-p is required") - } - if s.p = sysfs.Pins[*num]; s.p == nil { - list := make([]int, 0, len(sysfs.Pins)) - for i := range sysfs.Pins { - list = append(list, i) - } - sort.Ints(list) - valid := "" - for i, v := range list { - if i == 0 { - valid += fmt.Sprintf("%d", v) - } else { - valid += fmt.Sprintf(", %d", v) - } - } - return fmt.Errorf("invalid pin %d; valid: %s", *num, valid) - } - s.pull = gpio.PullNoChange - s.runGPIOBenchmark() - return nil -} diff --git a/sysfs/sysfssmoketest/benchmark_gpio_support.go b/sysfs/sysfssmoketest/benchmark_gpio_support.go deleted file mode 100644 index 6dfce4c2..00000000 --- a/sysfs/sysfssmoketest/benchmark_gpio_support.go +++ /dev/null @@ -1,403 +0,0 @@ -// Copyright 2017 The Periph Authors. All rights reserved. -// Use of this source code is governed under the Apache License, Version 2.0 -// that can be found in the LICENSE file. - -// This file is expected to be copy-pasted in all benchmark smoke test. The -// only delta shall be the package name. - -package sysfssmoketest - -import ( - "fmt" - "os" - "testing" - "time" - - "periph.io/x/conn/v3/gpio" - "periph.io/x/conn/v3/physic" -) - -// runGPIOBenchmark runs the standardized GPIO benchmark for this specific -// implementation. -// -// Type Benchmark must have two members: -// - p: concrete type that implements gpio.PinIO. -// - pull: gpio.Pull value. -func (s *Benchmark) runGPIOBenchmark() { - if !s.short { - printBench("ReadNaive ", testing.Benchmark(s.benchmarkReadNaive)) - printBench("ReadDiscard ", testing.Benchmark(s.benchmarkReadDiscard)) - printBench("ReadSliceLevel ", testing.Benchmark(s.benchmarkReadSliceLevel)) - } - printBench("ReadBitsLSBLoop ", testing.Benchmark(s.benchmarkReadBitsLSBLoop)) - if !s.short { - printBench("ReadBitsMSBLoop ", testing.Benchmark(s.benchmarkReadBitsMSBLoop)) - } - printBench("ReadBitsLSBUnroll ", testing.Benchmark(s.benchmarkReadBitsLSBUnroll)) - if !s.short { - printBench("ReadBitsMSBUnroll ", testing.Benchmark(s.benchmarkReadBitsMSBUnroll)) - } - printBench("OutClock ", testing.Benchmark(s.benchmarkOutClock)) - if !s.short { - printBench("OutSliceLevel ", testing.Benchmark(s.benchmarkOutSliceLevel)) - } - printBench("OutBitsLSBLoop ", testing.Benchmark(s.benchmarkOutBitsLSBLoop)) - if !s.short { - printBench("OutBitsMSBLoop ", testing.Benchmark(s.benchmarkOutBitsMSBLoop)) - } - printBench("OutBitsLSBUnroll ", testing.Benchmark(s.benchmarkOutBitsLSBUnroll)) - if !s.short { - printBench("OutBitsMSBUnrool ", testing.Benchmark(s.benchmarkOutBitsMSBUnroll)) - } -} - -// Read - -// benchmarkReadNaive reads but ignores the data. -// -// This is an intentionally naive benchmark. -func (s *Benchmark) benchmarkReadNaive(b *testing.B) { - p := s.p - if err := p.In(s.pull, gpio.NoEdge); err != nil { - b.Fatal(err) - } - b.ResetTimer() - for i := 0; i < b.N; i++ { - p.Read() - } - b.StopTimer() -} - -// benchmarkReadDiscard reads but discards the data except for the last value. -// -// It measures the maximum raw read speed, at least in theory. -func (s *Benchmark) benchmarkReadDiscard(b *testing.B) { - p := s.p - if err := p.In(s.pull, gpio.NoEdge); err != nil { - b.Fatal(err) - } - l := gpio.Low - b.ResetTimer() - for i := 0; i < b.N; i++ { - l = p.Read() - } - b.StopTimer() - b.Log(l) -} - -// benchmarkReadSliceLevel reads into a []gpio.Level. -// -// This is 8x less space efficient that using bits packing, it measures if this -// has any performance impact versus bit packing. -func (s *Benchmark) benchmarkReadSliceLevel(b *testing.B) { - p := s.p - if err := p.In(s.pull, gpio.NoEdge); err != nil { - b.Fatal(err) - } - buf := make([]gpio.Level, b.N) - b.ResetTimer() - for i := range buf { - buf[i] = p.Read() - } - b.StopTimer() -} - -// benchmarkReadBitsLSBLoop reads into a []byte using LSBF using a loop to -// iterate over the bits. -func (s *Benchmark) benchmarkReadBitsLSBLoop(b *testing.B) { - p := s.p - if err := p.In(s.pull, gpio.NoEdge); err != nil { - b.Fatal(err) - } - buf := make([]byte, (b.N+7)/8) - b.ResetTimer() - for i := 0; i < b.N; i++ { - if p.Read() { - mask := byte(1) << uint(i&7) - buf[i/8] |= mask - } - } - b.StopTimer() -} - -// benchmarkReadBitsMSBLoop reads into a []byte using MSBF using a loop to -// iterate over the bits. -func (s *Benchmark) benchmarkReadBitsMSBLoop(b *testing.B) { - p := s.p - if err := p.In(s.pull, gpio.NoEdge); err != nil { - b.Fatal(err) - } - buf := make([]byte, (b.N+7)/8) - b.ResetTimer() - for i := 0; i < b.N; i++ { - if p.Read() { - mask := byte(1) << uint(7-(i&7)) - buf[i/8] |= mask - } - } - b.StopTimer() -} - -// benchmarkReadBitsLSBUnroll reads into a []byte using LSBF using an unrolled -// loop to iterate over the bits. -// -// It is expected to be slightly faster than benchmarkReadBitsLSBLoop. -func (s *Benchmark) benchmarkReadBitsLSBUnroll(b *testing.B) { - p := s.p - if err := p.In(s.pull, gpio.NoEdge); err != nil { - b.Fatal(err) - } - buf := make([]byte, (b.N+7)/8) - b.ResetTimer() - for i := range buf { - l := byte(0) - if p.Read() { - l |= 0x01 - } - if p.Read() { - l |= 0x02 - } - if p.Read() { - l |= 0x04 - } - if p.Read() { - l |= 0x08 - } - if p.Read() { - l |= 0x10 - } - if p.Read() { - l |= 0x20 - } - if p.Read() { - l |= 0x40 - } - if p.Read() { - l |= 0x80 - } - buf[i] = l - } - b.StopTimer() -} - -// benchmarkReadBitsMSBUnroll reads into a []byte using MSBF using an unrolled -// loop to iterate over the bits. -// -// It is expected to be slightly faster than benchmarkReadBitsMSBLoop. -func (s *Benchmark) benchmarkReadBitsMSBUnroll(b *testing.B) { - p := s.p - if err := p.In(s.pull, gpio.NoEdge); err != nil { - b.Fatal(err) - } - buf := make([]byte, (b.N+7)/8) - b.ResetTimer() - for i := range buf { - l := byte(0) - if p.Read() { - l |= 0x80 - } - if p.Read() { - l |= 0x40 - } - if p.Read() { - l |= 0x20 - } - if p.Read() { - l |= 0x10 - } - if p.Read() { - l |= 0x08 - } - if p.Read() { - l |= 0x04 - } - if p.Read() { - l |= 0x02 - } - if p.Read() { - l |= 0x01 - } - buf[i] = l - } - b.StopTimer() -} - -// Out - -// benchmarkOutClock outputs an hardcoded clock. -// -// It measures maximum raw output performance when the bitstream is hardcoded. -func (s *Benchmark) benchmarkOutClock(b *testing.B) { - p := s.p - if err := p.Out(gpio.Low); err != nil { - b.Fatal(err) - } - n := (b.N + 1) / 2 - b.ResetTimer() - for i := 0; i < n; i++ { - _ = p.Out(gpio.High) - _ = p.Out(gpio.Low) - } - b.StopTimer() -} - -// benchmarkOutSliceLevel writes into a []gpio.Level. -// -// This is 8x less space efficient that using bits packing, it measures if this -// has any performance impact versus bit packing. -func (s *Benchmark) benchmarkOutSliceLevel(b *testing.B) { - p := s.p - if err := p.Out(gpio.Low); err != nil { - b.Fatal(err) - } - buf := make([]gpio.Level, b.N) - for i := 0; i < len(buf); i += 2 { - buf[i] = gpio.High - } - b.ResetTimer() - for _, l := range buf { - _ = p.Out(l) - } - b.StopTimer() -} - -// benchmarkOutBitsLSBLoop writes into a []byte using LSBF using a loop to -// iterate over the bits. -func (s *Benchmark) benchmarkOutBitsLSBLoop(b *testing.B) { - p := s.p - if err := p.Out(gpio.Low); err != nil { - b.Fatal(err) - } - buf := make([]byte, (b.N+7)/8) - for i := 0; i < len(buf); i += 2 { - buf[i] = 0x55 - } - b.ResetTimer() - for _, l := range buf { - for i := 0; i < 8; i++ { - mask := byte(1) << uint(i) - _ = p.Out(gpio.Level(l&mask != 0)) - } - } - b.StopTimer() -} - -// benchmarkOutBitsMSBLoop writes into a []byte using MSBF using a loop to -// iterate over the bits. -func (s *Benchmark) benchmarkOutBitsMSBLoop(b *testing.B) { - p := s.p - if err := p.Out(gpio.Low); err != nil { - b.Fatal(err) - } - buf := make([]byte, (b.N+7)/8) - for i := 0; i < len(buf); i += 2 { - buf[i] = 0xAA - } - b.ResetTimer() - for _, l := range buf { - for i := 7; i >= 0; i-- { - mask := byte(1) << uint(i) - _ = p.Out(gpio.Level(l&mask != 0)) - } - } - b.StopTimer() -} - -// benchmarkOutBitsLSBUnroll writes into a []byte using LSBF using an unrolled -// loop to iterate over the bits. -// -// It is expected to be slightly faster than benchmarkOutBitsLSBLoop. -func (s *Benchmark) benchmarkOutBitsLSBUnroll(b *testing.B) { - p := s.p - if err := p.Out(gpio.Low); err != nil { - b.Fatal(err) - } - buf := make([]byte, (b.N+7)/8) - for i := 0; i < len(buf); i += 2 { - buf[i] = 0x55 - } - b.ResetTimer() - for _, l := range buf { - _ = p.Out(gpio.Level(l&0x01 != 0)) - _ = p.Out(gpio.Level(l&0x02 != 0)) - _ = p.Out(gpio.Level(l&0x04 != 0)) - _ = p.Out(gpio.Level(l&0x08 != 0)) - _ = p.Out(gpio.Level(l&0x10 != 0)) - _ = p.Out(gpio.Level(l&0x20 != 0)) - _ = p.Out(gpio.Level(l&0x40 != 0)) - _ = p.Out(gpio.Level(l&0x80 != 0)) - } - b.StopTimer() -} - -// benchmarkOutBitsMSBUnroll writes into a []byte using MSBF using an unrolled -// loop to iterate over the bits. -// -// It is expected to be slightly faster than benchmarkOutBitsMSBLoop. -func (s *Benchmark) benchmarkOutBitsMSBUnroll(b *testing.B) { - p := s.p - if err := p.Out(gpio.Low); err != nil { - b.Fatal(err) - } - buf := make([]byte, (b.N+7)/8) - for i := 0; i < len(buf); i += 2 { - buf[i] = 0xAA - } - b.ResetTimer() - for _, l := range buf { - _ = p.Out(gpio.Level(l&0x80 != 0)) - _ = p.Out(gpio.Level(l&0x40 != 0)) - _ = p.Out(gpio.Level(l&0x20 != 0)) - _ = p.Out(gpio.Level(l&0x10 != 0)) - _ = p.Out(gpio.Level(l&0x08 != 0)) - _ = p.Out(gpio.Level(l&0x04 != 0)) - _ = p.Out(gpio.Level(l&0x02 != 0)) - _ = p.Out(gpio.Level(l&0x01 != 0)) - } - b.StopTimer() -} - -// - -func printBench(name string, r testing.BenchmarkResult) { - if r.Bytes != 0 { - fmt.Fprintf(os.Stderr, "unexpected %d bytes written\n", r.Bytes) - return - } - if r.MemAllocs != 0 || r.MemBytes != 0 { - fmt.Fprintf(os.Stderr, "unexpected %d bytes allocated as %d calls\n", r.MemBytes, r.MemAllocs) - return - } - fmt.Printf("%s \t%s\t%s\n", name, r, toHz(&r)) -} - -// toHz converts a benchmark result to a frequency keeping the most precision -// as possible. -// -// Time is used at 1µs resolution, and lowered at 1ms resolution if the -// duration is over 10s. -func toHz(r *testing.BenchmarkResult) physic.Frequency { - if r.T <= 0 { - return 0 - } - n := int64(r.N) - t := r.T.Nanoseconds() - - timeRes := time.Microsecond - if r.T > 10*time.Second { - // Reduce the resolution to millisecond. This is needed to not overflow - // int64. - timeRes = time.Millisecond - } - - // Leverage the fact that the number of occurrences is generally a large - // base10. Still, make sure to keep at least 6 digits of resolution. - factor := int64(1) - for (n%10) == 0 && n > 1000000 { - n /= 10 - factor *= 10 - } - n *= int64(physic.Hertz) * int64(time.Second/timeRes) - t /= int64(timeRes) - return physic.Frequency(((n + (t / 2)) / t) * factor) -} diff --git a/sysfs/sysfssmoketest/benchmark_gpio_support_test.go b/sysfs/sysfssmoketest/benchmark_gpio_support_test.go deleted file mode 100644 index daddb80e..00000000 --- a/sysfs/sysfssmoketest/benchmark_gpio_support_test.go +++ /dev/null @@ -1,102 +0,0 @@ -// Copyright 2019 The Periph Authors. All rights reserved. -// Use of this source code is governed under the Apache License, Version 2.0 -// that can be found in the LICENSE file. - -package sysfssmoketest - -import ( - "testing" - "time" - - "periph.io/x/conn/v3/physic" -) - -func TestToHz(t *testing.T) { - data := []struct { - N int - T time.Duration - expected physic.Frequency - }{ - { - 0, - time.Second, - 0, - }, - { - 1, - 0, - 0, - }, - { - 1, - time.Millisecond, - physic.KiloHertz, - }, - { - 1, - time.Second, - physic.Hertz, - }, - { - 3, - 7 * time.Millisecond, - // 3/7 with perfect rounding. - 428571429 * physic.MicroHertz, - }, - { - 3000, - 7 * time.Microsecond, - // 3/7 with perfect rounding. - 428571428571429 * physic.MicroHertz, - }, - { - 1000000, - 1000 * time.Second, - physic.KiloHertz, - }, - { - 1000000, - time.Second, - physic.MegaHertz, - }, - { - 1000000, - time.Millisecond, - physic.GigaHertz, - }, - { - 1000000000, - 1000 * time.Second, - physic.MegaHertz, - }, - { - 1000000000, - time.Second, - physic.GigaHertz, - }, - { - 1234556000, - // 2.3s. - 2345567891 * time.Nanosecond, - // 10 digits of resolution for 526.336MHz. - 526335849711 * physic.MilliHertz, - }, - { - 1000000000, - time.Millisecond, - physic.TeraHertz, - }, - { - 300000000, - 7 * time.Millisecond, - // 3/7 with pretty good rounding, keeping in mind that's 42.857GHz. - 42857142857143 * physic.MilliHertz, - }, - } - for i, line := range data { - r := testing.BenchmarkResult{N: line.N, T: line.T} - if actual := toHz(&r); actual != line.expected { - t.Fatalf("#%d: toHz(%d, %s) = %s(%d); expected %s(%d)", i, line.N, line.T, actual, actual, line.expected, line.expected) - } - } -} diff --git a/sysfs/sysfssmoketest/sysfssmoketest.go b/sysfs/sysfssmoketest/sysfssmoketest.go deleted file mode 100644 index eac17749..00000000 --- a/sysfs/sysfssmoketest/sysfssmoketest.go +++ /dev/null @@ -1,6 +0,0 @@ -// Copyright 2017 The Periph Authors. All rights reserved. -// Use of this source code is governed under the Apache License, Version 2.0 -// that can be found in the LICENSE file. - -// Package sysfssmoketest verifies that sysfs specific functionality work. -package sysfssmoketest