raspberry-sharp/raspberry-sharp-io

Benchmark

saltzman007 opened this issue · 5 comments

Hi there,
I'm just making my first steps with Raspberry and the Raspberry Sharp IO project, and it feels straightforward and good to use.
I'm wondering, if it is the Raspberry, the Mono-FW or the IO Library or my Setup, which makes some things a little bit slow: In my benchmark I write blind to a pin < 1ms, read < 1 ms, but if I connect the write-pin to the read-pin, I have to wait 0,1 sec before I can be shure to read the value written.
This is not a complaint, just wondering if you have similar timing values!
thx
Harry

    static void Benchmark ()
    {
        DateTime start = DateTime.Now;

        OutputPinConfiguration output = ConnectorPin.P1Pin11.Output ();
        InputPinConfiguration input = ConnectorPin.P1Pin12.Input ();

        using (GpioConnection connection = new GpioConnection (new PinConfiguration[]{ output, input })) {

            Console.WriteLine ("ConnectTime = " + new TimeSpan (DateTime.Now.Ticks - start.Ticks)); //3sec, long time

            const int testCount = 100;

            start = DateTime.Now;
            for (int i = 0; i < testCount; i++) {
                bool buttonPressed = connection [input];
            }

            Console.WriteLine ("ReadTime = " + new TimeSpan ((DateTime.Now.Ticks - start.Ticks) / testCount));  // < 1ms, quick

            start = DateTime.Now;
            for (int i = 0; i < testCount; i++) {
                connection [output] = (i & 1) > 0;
            }

            Console.WriteLine ("WriteTime = " + new TimeSpan ((DateTime.Now.Ticks - start.Ticks) / testCount)); // < 1ms, quick

            //ReadWrite: Connect output to input on breadboard
            bool status;
            start = DateTime.Now;
            for (int i = 0; i < testCount; i++) 
            {
                status = (i & 1) > 0;
                connection [output] = status;
                Thread.Sleep (100); //Write seems to be async, Errors if < 100ms! slow
                if (connection [input] != status)
                    Console.WriteLine ("Bullshit");
            }

            Console.WriteLine ("WriteReadTime = " + new TimeSpan ((DateTime.Now.Ticks - start.Ticks) / testCount));

            connection.Close ();
        }
        Console.ReadKey ();

    }

Hello,

most of the GPIO pins on the RPi don't have real interrupts, instead they are polled at a certain interval, this applies to the GpioConnection that you're using in your example. The default poll interval is 50 ms (it can be configured to less, but at some point you'll incur a lot of CPU constantly polling the pins). So the reason you have to wait (about) 100 ms is so the timer (check the GpioConnection source code) can refresh the internal pinValues array (which is what happens when you access input[pin], it doesn't actually read the Gpio, it just returns the latest values in the internal array, updated by the polling timer).
Same thing applies to your test of reading the pins 100 times, you're actually just reading the array, it doesn't do anything on the Gpio port.

Hello,

Sorry for the late reply, but @HakanL provides a good answer when using GpioConnection.
You may expect better performances by using the underlying GpioConnectionDriver, which allow direct read/write to the pins.

You may load the driver by invoking GpioConnectionSettings.DefaultDriver

Am 29.09.2015 um 06:12 schrieb Hakan
  Lindestaf:


  Hello,
  most of the GPIO pins on the RPi don't have real interrupts,
    instead they are polled at a certain interval, this applies to
    the GpioConnection that you're using in your example. The
    default poll interval is 50 ms (it can be configured to less,
    but at some point you'll incur a lot of CPU constantly polling
    the pins). So the reason you have to wait (about) 100 ms is so
    the timer (check the GpioConnection source code) can refresh the
    internal pinValues array (which is what happens when you access
    input[pin], it doesn't actually read the Gpio, it just returns
    the latest values in the internal array, updated by the polling
    timer).
    Same thing applies to your test of reading the pins 100 times,
    you're actually just reading the array, it doesn't do anything
    on the Gpio port.
  —
    Reply to this email directly or view
      it on GitHub.








Hello Hakan, 

thanks for your reply. I saw the code: Maybe a high price for the
interrupts, because every normal read without interrupt is slowed
down by the polling and the middle layer of this array.

I like your library and will use it for SPI and I2C.

If your interested in bringing the lib to the maximum speed under
.net/mono, we could discuss a few points:

- We could speed up reading / writing by directly rw (without the
array) and have the polling in a different thread that doesn't
affect the normal read/writes
- I made some experiments and tried your memory pin writer and it
became faster
- with https://github.com/danriches/WiringPi.Net it was again ten
times faster
- when i optimized this wrapper, so it has delegates to the
functions and therefor reads the functionadresses just once and not
on every call, it was again 10 times faster making 1MHz read/writes.

We this frequency I want to try to connects an SPI AD Converter and
record a .wav:-)

Are you interested in putting these things together?

Cheers

Harry

I'm not the developer of this project, but if you have any suggestions on improvements then I'm sure Eric will consider a pull request. In general .NET/Mono on RPi is probably not your best option for rapid sampling, you have to deal with drop-outs when the GC freezes all threads, etc.

Hello Eric, 

  thanks for your reply. I saw the code: Maybe a high price for the
  interrupts, because every normal read without interrupt is slowed
  down by the polling and the middle layer of this array.

  I like your library and will use it for SPI and I2C.

  If your interested in bringing the lib to the maximum speed under
  .net/mono, we could discuss a few points:

  - We could speed up reading / writing by directly rw (without the
  array) and have the polling in a different thread that doesn't
  affect the normal read/writes
  - I made some experiments and tried your memory pin writer and it
  became faster
  - with https://github.com/danriches/WiringPi.Net
  it was again ten times faster
  - when i optimized this wrapper, so it has delegates to the
  functions and therefor reads the functionadresses just once and
  not on every call, it was again 10 times faster making 1MHz
  read/writes.

  We this frequency I want to try to connects an SPI AD Converter
  and record a .wav:-)

  Are you interested in putting these things together?

  Cheers

  Harry



  Am 29.09.2015 um 20:12 schrieb Eric Bézine:


  Hello,
  Sorry for the late reply, but @HakanL
    provides a good answer when using GpioConnection.
    You may expect better performances by using the underlying
    GpioConnectionDriver, which allow direct read/write to the pins.
  You may load the driver by invoking
    GpioConnectionSettings.DefaultDriver
  —
    Reply to this email directly or view
      it on GitHub.