Pi4j的一个Performance的Bug

在玩树莓派的时候写了个程序,用来动态控制4位数码管。但是遇到了一个问题,就是数码管的刷新频率太慢,结果就是闪烁。

于是写了一篇测试程序,最后结果是,用Java + Pi4j,大概每秒钟可以把GPIO置高置低1400次左右。这也太慢了。

网上有一篇文章,http://codeandlife.com/2012/07/03/benchmarking-raspberry-pi-gpio-speed/ ,里面对比了各个开发库操作GPIO的效率。结果是Python Perl这样的都比我得到的结果快得多。(每秒40k)

也没别的办法,就下载了Pi4j的源代码,最后发现,原来Pi4j的实现有一点问题。

在每次调用high()或者low()的时候,都要调用一个com.pi4j.wiringpi.GpioUtil.isPinSupported函数。这个是个JNI函数,而且比较慢。调用层次为

    at com.pi4j.wiringpi.GpioUtil.isPinSupported(GpioUtil.java:291)
    at com.pi4j.io.gpio.RaspiGpioProvider.hasPin(RaspiGpioProvider.java:61)
    at com.pi4j.io.gpio.GpioProviderBase.setState(GpioProviderBase.java:172)
    at com.pi4j.io.gpio.RaspiGpioProvider.setState(RaspiGpioProvider.java:154)
    at com.pi4j.io.gpio.impl.GpioPinImpl.setState(GpioPinImpl.java:325)
    at com.pi4j.io.gpio.impl.GpioPinImpl.low(GpioPinImpl.java:209)
    at TestSpeed.test(TestSpeed.java:23)
    at TestSpeed.main(TestSpeed.java:14)
考虑到不需要每次都判断一个端口是否存在,就把这里加了一个Cache,改为
private static ConcurrentHashMap<Pin, Boolean> hasPinMap = new ConcurrentHashMap();

    @Override
    public boolean hasPin(Pin pin) {
        Boolean r = hasPinMap.get(pin);
        if (r != null) {
            return r.booleanValue();
        }
        boolean realValue = (com.pi4j.wiringpi.GpioUtil.isPinSupported(pin.getAddress()) > 0);
        hasPinMap.putIfAbsent(pin, realValue);
        return realValue;
    }

再次进行测试,结果从之前的1400次每秒上升为158000次每秒!!!重新进行数码管的测试,数码管的闪烁现象消失。
后来和Pi4j的开发者沟通了下,他们说这个bug已经在1.1 Snapshot下修正了,测试了下果然如此。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值