User avatar
savageautomate
Posts: 225
Joined: Thu Aug 16, 2012 3:20 pm
Location: USA
Contact: Website

Java GPIO Frequency Benchmarks

Wed Jan 09, 2013 3:15 pm

I posted an article on benchmarks of GPIO state change frequency running a java test program on different JVMs.
The Oracle JVM turned out to the be clear winner in this speed test.

See the full details here:
http://www.savagehomeautomation.com/pro ... marks.html

Image
Robert Savage | Follow me @savageautomate
http://www.pi4j.com | http://www.pislices.com
http://www.savagehomeautomation.com

trouch
Posts: 310
Joined: Fri Aug 03, 2012 7:24 pm
Location: France
Contact: Website

Re: Java GPIO Frequency Benchmarks

Wed Jan 09, 2013 7:26 pm

I see Pi4J relies on WiringPi for handling GPIO.
As WiringPi can use both SoC registers and GPIO driver, can you tell me which mode is used for your tests ?

WebIOPi - Raspberry Pi REST Framework to control your Pi from the web
http://store.raspberrypi.com/projects/webiopi
http://code.google.com/p/webiopi/
http://trouch.com

User avatar
savageautomate
Posts: 225
Joined: Thu Aug 16, 2012 3:20 pm
Location: USA
Contact: Website

Re: Java GPIO Frequency Benchmarks

Wed Jan 09, 2013 7:38 pm

Pi4J initializes wiringPi using this method:

Code: Select all

wiringPiSetup()
Thus is it not using the "/sys/class/gpio" interface but rather SoC registers directly.

We choose this method in Pi4J because the "wiringPiSetupSys()" initializer has some pin export limitations and we wanted to provide a single and consistent method for working with GPIO from Java.

More details on these initializer methods at:
https://projects.drogon.net/raspberry-p ... functions/

Note: the native C frequency test in the article also uses this same wiringPi initializer.

Thanks, Robert
Robert Savage | Follow me @savageautomate
http://www.pi4j.com | http://www.pislices.com
http://www.savagehomeautomation.com

hinkmond
Posts: 6
Joined: Wed Jan 09, 2013 7:49 pm

Re: Java GPIO Frequency Benchmarks

Wed Jan 09, 2013 8:17 pm

Hi Robert,

Nice blog post! Especially how you point out that the Oracle JDK 8 for ARM Early Access Java VM (see: http://jdk8.java.net/fxarmpreview/ ) is so much faster for Java to RPi GPIO access than other OpenJDK-based Java VMs currently out there.

One issue to point out (as you noted) is that the Pi4J library uses JNI to access the WiringPi native C library which incurs intrinsic JNI overhead when converting from Java Strings to Native C function calls as is done in JNI, that in turn slows down the Java GPIO benchmark measurement.

Another approach that may avoid this JNI overhead, is by using Java to directly access the Raspian Linux file handle drivers to the GPIO interface using the RPi /sys/classes/gpio/* and Java File I/O. See my blog post: https://blogs.oracle.com/hinkmond/entry ... dded_gpio4

If you modify the above code in my blog post to not to sleep between flipping the GPIO output on/off and use NIO2 instead of java.io.*, then you could potentially see the Oracle JDK 8 for ARM Early Access approach and even possibly match the Native C benchmark numbers, since the JNI overhead of Pi4J would be avoided, and instead you would allow the Hotspot VM in Oracle JDK 8 for ARM to use the faster JVMI to Native C I/O access that the VM uses instead of JNI that Pi4J uses, along with NIO2 to avoid all that JNI overhead slowness.

Just one idea if anyone out there is ever interested in having Java run even faster accessing GPIO on a RPi with your benchmark.

Great blog, BTW! Keep up the good work!

Thanks,
Hinkmond

trouch
Posts: 310
Joined: Fri Aug 03, 2012 7:24 pm
Location: France
Contact: Website

Re: Java GPIO Frequency Benchmarks

Wed Jan 09, 2013 8:27 pm

thanks for precisions. I also choose to include native code in webiopi to get a full GPIO access through registers
I recently made some bench with java too, and I'm considering porting webiopi server to java.
But there is a big difference between 150KHz and 7Mhz !
How is compiled the native part ?
I'd like to see a native loop called from java to understand why.

WebIOPi - Raspberry Pi REST Framework to control your Pi from the web
http://store.raspberrypi.com/projects/webiopi
http://code.google.com/p/webiopi/
http://trouch.com

trouch
Posts: 310
Joined: Fri Aug 03, 2012 7:24 pm
Location: France
Contact: Website

Re: Java GPIO Frequency Benchmarks

Wed Jan 09, 2013 11:11 pm

hinkmond wrote:One issue to point out (as you noted) is that the Pi4J library uses JNI to access the WiringPi native C library which incurs intrinsic JNI overhead when converting from Java Strings to Native C function calls as is done in JNI, that in turn slows down the Java GPIO benchmark measurement.
thanks for this post I miss

WebIOPi - Raspberry Pi REST Framework to control your Pi from the web
http://store.raspberrypi.com/projects/webiopi
http://code.google.com/p/webiopi/
http://trouch.com

User avatar
savageautomate
Posts: 225
Joined: Thu Aug 16, 2012 3:20 pm
Location: USA
Contact: Website

Re: Java GPIO Frequency Benchmarks

Thu Jan 10, 2013 12:35 am

hinkmond wrote: ...
Another approach that may avoid this JNI overhead, is by using Java to directly access the Raspian Linux file handle drivers to the GPIO interface using the RPi /sys/classes/gpio/* and Java File I/O. ...
Hi Hinkmond,

Thank you for your post and suggestions. The overhead of JNI certainly makes sense to me so I went an re-tested using your suggested method of Java direct access to the "/sys/class/gpio/" interface. However, the results I am seeing seem to still favor the JNI approach ...

Using java.io with the Oracle JDK SE 8 (ARM preview) I am getting about 25kHz.
Image
(click here to see full size image)

Using java.nio with the Oracle JDK SE 8 (ARM preview) I am getting about 2.6kHz.
Image
(click here to see full size image)


So now I am left thinking ... what did I do wrong?

Here are the test programs I am using that are adapted from your code. Can you take a look and see if there is something wrong in my approach?

java.io test program @ http://pastebin.com/1upsTXev
java.nio test program @ http://pastebin.com/PWjx1PKD

Unless maybe accessing GPIO via the driver interface really slows it down more than the overhead of JNI?

Thanks, Robert
Robert Savage | Follow me @savageautomate
http://www.pi4j.com | http://www.pislices.com
http://www.savagehomeautomation.com

hinkmond
Posts: 6
Joined: Wed Jan 09, 2013 7:49 pm

Re: Java GPIO Frequency Benchmarks

Thu Jan 10, 2013 12:56 am

savageautomate wrote:
Using java.nio with the Oracle JDK SE 8 (ARM preview) I am getting about 2.6kHz.
Image
(click here to see full size image)


So now I am left thinking ... what did I do wrong?

Here are the test programs I am using that are adapted from your code. Can you take a look and see if there is something wrong in my approach?

java.io test program @ http://pastebin.com/1upsTXev
java.nio test program @ http://pastebin.com/PWjx1PKD

Unless maybe accessing GPIO via the driver interface really slows it down more than the overhead of JNI?

Thanks, Robert
Hi Robert,

Sorry, I wasn't quite clear what I meant by NIO2 when I replied. I meant to suggest NIO Memory Mapped File I/O as the possible faster way to access GPIO. So something like this (not tested yet):

Code: Select all

          String fn = "/sys/class/gpio/gpio" + GpioChannel + "/value";
          RandomAccessFile memoryMappedFile = new RandomAccessFile(fn, "rw");
         
          //Mapping a file into memory
          MappedByteBuffer out = memoryMappedFile.getChannel().map(FileChannel.MapMode.READ_WRITE, 0, 8);
        
          // Loop forever
          while (true) {
              //Writing into Memory Mapped File
              out.put((byte) '1');
              out.put((byte) '0');
          }
I'm not sure if you might need to flush it each time after the put, but in general the /sys/class/gpio/* file handle mapped directly to Java memory with NIO, should give you faster write access in Java than JNI to the WiringPi pin C library with Pi4J. This might need further investigation if it doesn't still show the correct results.

Unfortunately, I don't have a scope at Oracle. :( Go figure, but we are a software group. :D So, this theory might need some work to sort out.

Thanks for your interest in this! It's cool you are working with an oscilloscope, the RPi, and Java!
Hinkmond

User avatar
savageautomate
Posts: 225
Joined: Thu Aug 16, 2012 3:20 pm
Location: USA
Contact: Website

Re: Java GPIO Frequency Benchmarks

Thu Jan 10, 2013 1:04 am

trouch wrote:thanks for precisions. I also choose to include native code in webiopi to get a full GPIO access through registers
I recently made some bench with java too, and I'm considering porting webiopi server to java.
But there is a big difference between 150KHz and 7Mhz !
How is compiled the native part ?
I'd like to see a native loop called from java to understand why.
Trouch,

If you are porting your project to Java, then you may just want to consume the Pi4J library to handle your GPIO implementation. This way you don't have to worry about compiling the native code. Also, Pi4J provides interrupt driven events on GPIO state changes so you don't have to poll for this. This interrupt monitoring takes place in the native part of Pi4J. If you are interested, here is the native C project that Pi4J uses to provide the JNI wrappers to the wiringPi library. https://github.com/Pi4J/pi4j/tree/develop/pi4j-native. I am using Maven to SCP/SSH files to actual Pi hardware to perform the compile on both hard-float and soft-float ABIs.

I bet if you invoke a native loop from Java you will see the same frequency results as my pure native test while the loop is running. You just have the pay for the initial overhead of Java and JNI to invoke the loop. Probably negligible.

If there any real need in your project for super hi-speed frequency on GPIO pins?

Thanks, Robert
Robert Savage | Follow me @savageautomate
http://www.pi4j.com | http://www.pislices.com
http://www.savagehomeautomation.com

trouch
Posts: 310
Joined: Fri Aug 03, 2012 7:24 pm
Location: France
Contact: Website

Re: Java GPIO Frequency Benchmarks

Thu Jan 10, 2013 9:55 am

savageautomate wrote:I bet if you invoke a native loop from Java you will see the same frequency results as my pure native test while the loop is running. You just have the pay for the initial overhead of Java and JNI to invoke the loop. Probably negligible.

If there any real need in your project for super hi-speed frequency on GPIO pins?
I was just wondering where was the overhead to explain the difference between oracle jvm and native c code starting from the ground ;)
But Hinkmond added explaination about JNI I did not see.

Thanks for your post and blog article, it's a great complement to http://codeandlife.com/2012/07/03/bench ... pio-speed/
We can see Python is better than OpenJDK 7 but not Oracle JVM.
You will also see there is a difference between C/WiringPi and C/Direct register acces.
I think I will reuse my native code to wrap it with Java as I don't use wiringPi.

WebIOPi - Raspberry Pi REST Framework to control your Pi from the web
http://store.raspberrypi.com/projects/webiopi
http://code.google.com/p/webiopi/
http://trouch.com

User avatar
savageautomate
Posts: 225
Joined: Thu Aug 16, 2012 3:20 pm
Location: USA
Contact: Website

Re: Java GPIO Frequency Benchmarks

Thu Jan 10, 2013 10:38 am

trouch wrote:Thanks for your post and blog article, it's a great complement to http://codeandlife.com/2012/07/03/bench ... pio-speed/
Thanks for that link! I had not seen that article.

Regards, Robert
Robert Savage | Follow me @savageautomate
http://www.pi4j.com | http://www.pislices.com
http://www.savagehomeautomation.com

trouch
Posts: 310
Joined: Fri Aug 03, 2012 7:24 pm
Location: France
Contact: Website

Re: Java GPIO Frequency Benchmarks

Sat Jan 12, 2013 2:40 pm

I've also made my own bench using matrix computation to see float performance
You may take on look on http://www.raspberrypi.org/phpBB3/viewt ... 31&t=29421
All detail on http://trouch.com/2013/01/12/raspberry-pi-benchmark/

WebIOPi - Raspberry Pi REST Framework to control your Pi from the web
http://store.raspberrypi.com/projects/webiopi
http://code.google.com/p/webiopi/
http://trouch.com

neilf
Posts: 72
Joined: Sun Nov 11, 2012 8:14 am

Re: Java GPIO Frequency Benchmarks

Sat Jan 12, 2013 2:49 pm

I know it's not really relevant to a Java thread, but interpreted BBC Basic V, running under RISC OS, toggles an R-Pi GPIO line at >20MHz, so Java and C have a way to go yet.

Sebioff
Posts: 6
Joined: Mon Jan 14, 2013 9:43 pm

Re: Java GPIO Frequency Benchmarks

Fri Jan 25, 2013 11:47 am

Hi Hinkmond,
I'm interested in using the fastest GPIO speed possible, so I gave your NIO2 suggestion a try.
However, I'm getting an exception:
java.io.IOException: No matching device found
at sun.nio.ch.FileChannelImpl.map0(Native Method)
at sun.nio.ch.FileChannelImpl.map(FileChannelImpl.java:835)
at this line:

Code: Select all

memoryMappedFile.getChannel().map(FileChannel.MapMode.READ_WRITE, 0, 8);
Not quite sure what that's supposed to mean and what to do with this - any ideas?

Regards
Sebastian

hinkmond
Posts: 6
Joined: Wed Jan 09, 2013 7:49 pm

Re: Java GPIO Frequency Benchmarks

Fri Jan 25, 2013 10:52 pm

Hi Sebastian,

Let me take a look and figure out the right Java code to use with NIO. I recently obtained an oscilloscope for the RPi here! So, I can now reproduce the benchmark.

I'll post when I have more info...

Thanks,
Hinkmond

Sebioff
Posts: 6
Joined: Mon Jan 14, 2013 9:43 pm

Re: Java GPIO Frequency Benchmarks

Sun Feb 10, 2013 12:48 pm

That's awesome, thank you!

User avatar
aTao
Posts: 1087
Joined: Wed Dec 12, 2012 10:41 am
Location: Howlin Eigg

*Confused of SwineTown

Fri Feb 22, 2013 10:57 pm

I am working on my own JNI library for GPIO access and have some timings I dont trust.

I first raised the question here: http://www.raspberrypi.org/phpBB3/viewt ... 71#p294371

Here's the Java time measurement loops:

Code: Select all

			long now = 0;
			long then = 1;
			long onesies = 2;
			int loop = 1000000;
			setFuction( 16, PIN_OUTPUT);
			for(int rep = 0; rep <10; rep++){
			then = System.nanoTime();
			for(int i = 0; i<loop; i++){
				jpioOut(16, 1);
				jpioOut(16, 0);
			};
			now = System.nanoTime();
			onesies = now - then;
			then = System.nanoTime();
			for(int i = 0; i<loop; i++){
				jpioOut(16, 1);
				jpioOut(16, 0);
				jpioOut(16, 1);
				jpioOut(16, 0);
			};
			now = System.nanoTime();
			System.out.println("time:"+((now - then - onesies)/loop)+"ns / flash");
			};
and the native code just for good measure:

Code: Select all

JNIEXPORT void JNICALL Java_JPIO_jpioOut
  (JNIEnv *env, jobject mama, jint pin, jint data)
{
   if(data){
      *(jpio + 7) = 1 << pin;
   } else {
      *(jpio +10) = 1 << pin;
   };
} //jpioOutput
and here's some output:

Code: Select all

java.vm.vendor;Oracle Corporation
java.vm.version;1.8.0-ea
time:226ns / flash
time:349ns / flash
time:362ns / flash
time:365ns / flash
time:361ns / flash
time:384ns / flash
time:352ns / flash
time:364ns / flash
time:388ns / flash
time:348ns / flash

Now then, heres the bit thats bothering me a bit:, if the timings shown on Mr Savage's blog are all in the 5 to 160 kHz mark, how comes I seem to have ~3MHz ?
Did I miss something?
>)))'><'(((<

User avatar
savageautomate
Posts: 225
Joined: Thu Aug 16, 2012 3:20 pm
Location: USA
Contact: Website

Re: Java GPIO Frequency Benchmarks

Sat Feb 23, 2013 3:19 pm

This article (http://codeandlife.com/2012/07/03/bench ... pio-speed/) shows that ~14-22 MHz is attainable using Native C. All my Java tests were conducted using JNI wrappers around the WiringPi C library which topped out around 7 MHz. It may be possible that your implementation is using a more efficient/optimized path. If you want to package up the sample test program, I would be happy to run it on my system and scope it to provide independent verification of the speeds you are getting.

WiringPi and Pi4J were not explicitly written to perform highly optimized GPIO switching speeds, but rather written to provide easy to use abstracted interfaces and an easily consumable API.

Thanks, Robert
Robert Savage | Follow me @savageautomate
http://www.pi4j.com | http://www.pislices.com
http://www.savagehomeautomation.com

hinkmond
Posts: 6
Joined: Wed Jan 09, 2013 7:49 pm

Re: Java GPIO Frequency Benchmarks

Wed Feb 27, 2013 12:15 am

Hi Sebastian,

I'm still working on finding the right Java code to use NIO memory mapped file I/O to the GPIO file handle on the RPi. I'm seeing the same "No device found" bug you are seeing. It works fine on the RPi for any other regular text file on the device, such as /tmp/test.txt that I create with sample text in it and can run my same NIO code to map it into memory. But NIO memory mapping does not like the /sys/class/gpio/* Linux file handles for some reason...

It might have something to do with the Linux driver for turning GPIO pins into a Linux file handle. Will let you know when I find a workaround. If anyone has suggestions of getting MappedByteBuffer to work with an NIO FileChannel to a Linux virtual file handle (pointing to the RPi GPIO pins), please let me know. I'm looking into just using the FileChannel directly without memory mapping it...

Code: Select all

            String filename = "/sys/class/gpio/gpio24/value";
// NOTE: Changing to a test text file works fine
//            String filename = "/tmp/test.txt";

            System.out.println("DEBUG: filename = "+filename);
            RandomAccessFile memoryMappedFile = new 
                    RandomAccessFile(filename, "rw");
            memoryMappedFile.seek(0);
            // Map the GPIO file handle into memory
            FileChannel fileChannel = memoryMappedFile.getChannel();
            // ERROR occurs here: No device found
            MappedByteBuffer out = fileChannel.map(
                    FileChannel.MapMode.PRIVATE, 0, fileChannel.size());
hinkmond wrote:Hi Sebastian,

Let me take a look and figure out the right Java code to use with NIO. I recently obtained an oscilloscope for the RPi here! So, I can now reproduce the benchmark.

I'll post when I have more info...

Thanks,
Hinkmond

Williama1337
Posts: 1
Joined: Mon Aug 05, 2013 8:35 pm

Re: Java GPIO Frequency Benchmarks

Mon Aug 05, 2013 8:39 pm

hinkmond wrote:Hi Sebastian,

Let me take a look and figure out the right Java code to find a Malvern dentist to show your fillings. use with NIO. I recently obtained an oscilloscope for the RPi here! So, I can now reproduce the benchmark.

I'll post when I have more info...

Thanks,
Hinkmond
Just got a RPi oscilloscope as well, looking forward to posting my benchmarks!
Last edited by Williama1337 on Tue Aug 13, 2013 9:56 am, edited 1 time in total.

hinkmond
Posts: 6
Joined: Wed Jan 09, 2013 7:49 pm

Re: Java GPIO Frequency Benchmarks

Mon Aug 05, 2013 10:30 pm

I posted an update at: https://blogs.oracle.com/hinkmond/entry ... scope_and7 More updates to come...

mattlewis
Posts: 113
Joined: Sat Jan 12, 2013 3:05 pm
Location: UK
Contact: Website

Re: Java GPIO Frequency Benchmarks

Tue Mar 01, 2016 1:59 pm

Did anyone get to the bottom of this?
The JDK MappedByteBuffer fails as the underlying implementation thinks the file length is 0 bytes.
I started to have a quick look as to whether it was possible to provide access to /dev/gpiomem via a native DirectByteBuffer but simply cannot understand why it isn't working.
Basically I'm trying this in C using pigpio and wiringPi as examples (error handling code removed for readability):

Code: Select all

fdMem = open("/dev/gpiomem", O_RDWR | O_SYNC | O_CLOEXEC);
gpioAddr = (uint32_t *)mmap(NULL, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fdMem, 0);
return (*env)->NewDirectByteBuffer(env, gpioAddr, BLOCK_SIZE);
Then in Java:

Code: Select all

public static native ByteBuffer initialise();
public static void main(String[] args) {
  ByteBuffer gpioReg = initialise();
}
The thing that is frustrating me is that I am reading very different values in C as to those in Java, e.g. C:

Code: Select all

int i;
for (i=0; i<4; i++) {
  printf("gpioAddr[0]=0x%x\n", gpioAddr[0]);
}
Java:

Code: Select all

for (int i=0; i<4; i++) {
  System.out.format("gpioReg[%d]=0x%x%n", i, gpioReg.getInt(i*SIZE_OF_INT));
}
Any thoughts? Hope I'm not doing anything embarassingly stupid.

Matt
http://www.diozero.com/

JGPIO
Posts: 24
Joined: Sun Feb 28, 2016 6:29 pm

Re: Java GPIO Frequency Benchmarks

Sun May 29, 2016 9:00 pm

You might want to refer to your loop variable 'i' in your c code:

gpioAddr rather than gpioAddr[0]

then let us know what happens.

JGPIO
Posts: 24
Joined: Sun Feb 28, 2016 6:29 pm

Re: Java GPIO Frequency Benchmarks

Mon May 30, 2016 11:47 am

My own Java classes backed by my own JNI interface can manage 3MHz in a pin set/clr loop.

I'm trying to test memory mapped i/o in Java to determine if this is faster. The 100% Java /sys/class/gpio/gpioNN approach listed above works but is much slower (drops to KHz). The 100% Java NIO approach does not [yet] work, as we all know. The minimal JNI NewDirectByteBuffer approach seems promising, but I can't get it to work reliably at the moment.

mattlewis
Posts: 113
Joined: Sat Jan 12, 2013 3:05 pm
Location: UK
Contact: Website

Re: Java GPIO Frequency Benchmarks

Mon May 30, 2016 1:37 pm

I've created the Java diozero library as an object orientated interface to device programming (it was originally based on the excellent Python GPIO Zero API) - documentation. It works with different low-level device interface libraries including Pi4j, wiringPi as well as my own Java JNI wrapper around pigpio.
I was hoping that I would be able to create my own high-performance Java based library using just a thin JNI wrapper to provide memory mapped direct byte buffer access to /dev/gpiomem. I gave up after failing to get this working - I need to have another look to double check my mistake wasn't as stupid as you highlighted ([0]?!).
My performance results are here - wiringPi is the fastest, looking at the source code it has a number of optimisations not included in pigpio.

Sounds like you've had some success with this approach, is that correct? Are you able to share any code?

Regards,
Matt
http://www.diozero.com/

Return to “Java”