Closed EmmanuelP closed 4 years ago
I am happy to test this when someone has time to work on it. My aravis installation is already a git clone, so I can easily pull new changes to test the performance.
I am curious why a problem with register caching causes some enum features to take a very long time to read, while others are very fast? For example on the FLIR Oryx 51S5M it takes about 700 ms and 3500 GcRegisterNode::_get_integer_value
messages when reading the 15 enum values and strings for TriggerSource. However, it takes less than 1 ms and no GcRegisterNode::_get_integer_value
messages when reading the 10 enum values and strings for ChunkPixelFormat.
There is also a very large difference between USB and 10 GigE cameras. On the USB camera is takes less than 100 ms to read all of the features, compared to 1 to 12 seconds on GigE and 10 GigE. Is the USB bus read time that much faster when reading registers?
TriggerSource and ChunkPixelFormat declarations in the genicam are not the same:
<Enumeration Name="ChunkPixelFormat" NameSpace="Standard">
<ToolTip>Format of the pixel provided by the camera</ToolTip>
<Description>Format of the pixel provided by the camera</Description>
<DisplayName>Chunk Pixel Format</DisplayName>
<Visibility>Expert</Visibility>
<pIsLocked>ChunkSelector_PixelFormat_Imp</pIsLocked>
<EnumEntry Name="Mono8" NameSpace="Standard">
<DisplayName>Mono8</DisplayName>
<Value>0x01080001</Value>
</EnumEntry>
<EnumEntry Name="Mono12Packed" NameSpace="Standard">
<DisplayName>Mono12Packed</DisplayName>
<Value>0x010C0006</Value>
</EnumEntry>
<EnumEntry Name="Mono16" NameSpace="Standard">
<DisplayName>Mono16</DisplayName>
<Value>0x01100007</Value>
</EnumEntry>
<EnumEntry Name="RGB8Packed" NameSpace="Standard">
<DisplayName>RGB8Packed</DisplayName>
<Value>0x02180014</Value>
</EnumEntry>
<EnumEntry Name="YUV422Packed" NameSpace="Standard">
<DisplayName>YUV422Packed</DisplayName>
<Value>0x0210001F</Value>
</EnumEntry>
<EnumEntry Name="BayerGR8" NameSpace="Standard">
<DisplayName>BayerGR8</DisplayName>
<Value>0x01080008</Value>
</EnumEntry>
<EnumEntry Name="BayerRG8" NameSpace="Standard">
<DisplayName>BayerRG8</DisplayName>
<Value>0x01080009</Value>
</EnumEntry>
<EnumEntry Name="BayerGB8" NameSpace="Standard">
<DisplayName>BayerGB8</DisplayName>
<Value>0x0108000A</Value>
</EnumEntry>
<EnumEntry Name="BayerBG8" NameSpace="Standard">
<DisplayName>BayerBG8</DisplayName>
<Value>0x0108000B</Value>
</EnumEntry>
<EnumEntry Name="YCbCr601_422_8_CbYCrY" NameSpace="Standard">
<DisplayName>YCbCr601_422_8_CbYCrY</DisplayName>
<Value>0x02100044</Value>
</EnumEntry>
<pValue>ChunkPixelFormat_Val</pValue>
</Enumeration>
<Enumeration Name="TriggerSource" NameSpace="Standard">
<ToolTip>Specifies the internal signal or physical input line to use as the trigger source.</ToolTip>
<Description>Specifies the internal signal or physical input line to use as the trigger source.</Description>
<DisplayName>Trigger Source</DisplayName>
<Visibility>Beginner</Visibility>
<pIsImplemented>TriggerSource_Imp</pIsImplemented>
<pIsAvailable>TriggerSource_Avl</pIsAvailable>
<pIsLocked>TriggerSource_Lck</pIsLocked>
<ImposedAccessMode>RW</ImposedAccessMode>
<EnumEntry Name="Software" NameSpace="Standard">
<DisplayName>Software</DisplayName>
<pIsImplemented>TriggerSource_Software_Imp</pIsImplemented>
<pIsAvailable>TriggerSource_Software_Avl</pIsAvailable>
<Value>31</Value>
</EnumEntry>
<EnumEntry Name="Line0" NameSpace="Standard">
<DisplayName>Line 0</DisplayName>
<pIsImplemented>TriggerSource_Line0_Imp</pIsImplemented>
<pIsAvailable>TriggerSource_Line0_Avl</pIsAvailable>
<Value>0</Value>
</EnumEntry>
<EnumEntry Name="Line1" NameSpace="Standard">
<DisplayName>Line 1</DisplayName>
<pIsImplemented>TriggerSource_Line1_Imp</pIsImplemented>
<pIsAvailable>TriggerSource_Line1_Avl</pIsAvailable>
<Value>1</Value>
</EnumEntry>
<EnumEntry Name="Line2" NameSpace="Standard">
<DisplayName>Line 2</DisplayName>
<pIsImplemented>TriggerSource_Line2_Imp</pIsImplemented>
<pIsAvailable>TriggerSource_Line2_Avl</pIsAvailable>
<Value>2</Value>
</EnumEntry>
<EnumEntry Name="Line3" NameSpace="Standard">
<DisplayName>Line 3</DisplayName>
<pIsImplemented>TriggerSource_Line3_Imp</pIsImplemented>
<pIsAvailable>TriggerSource_Line3_Avl</pIsAvailable>
<Value>3</Value>
</EnumEntry>
<EnumEntry Name="Line4" NameSpace="Standard">
<DisplayName>Line 4</DisplayName>
<pIsImplemented>TriggerSource_Line4_Imp</pIsImplemented>
<pIsAvailable>TriggerSource_Line4_Avl</pIsAvailable>
<Value>8</Value>
</EnumEntry>
<EnumEntry Name="Line5" NameSpace="Standard">
<DisplayName>Line 5</DisplayName>
<pIsImplemented>TriggerSource_Line5_Imp</pIsImplemented>
<pIsAvailable>TriggerSource_Line5_Avl</pIsAvailable>
<Value>9</Value>
</EnumEntry>
<EnumEntry Name="Line6" NameSpace="Standard">
<DisplayName>Line 6</DisplayName>
<pIsImplemented>TriggerSource_Line6_Imp</pIsImplemented>
<pIsAvailable>TriggerSource_Line6_Avl</pIsAvailable>
<Value>10</Value>
</EnumEntry>
The Locked, Available and Implemented values are read from registers like this one:
<MaskedIntReg Name="TriggerSource_Avl">
<pAddress>TriggerSourceAddr</pAddress>
<Length>4</Length>
<AccessMode>RO</AccessMode>
<pPort>Device</pPort>
<pInvalidator>ExposureMode_Val</pInvalidator>
<Bit>1</Bit>
<Sign>Unsigned</Sign>
<Endianess>BigEndian</Endianess>
</MaskedIntReg>
TriggerSourceAddr is defined by:
<IntSwissKnife Name="TriggerSourceAddr">
<pVariable Name="SELECTOR_INDEX_0">TriggerSelectorValueToIndex</pVariable>
<Formula>0x000C8C00 + 0x20 * ( ( SELECTOR_INDEX_0 * 1 ) )</Formula>
</IntSwissKnife>
<IntSwissKnife Name="TriggerSelectorValueToIndex">
<Visibility>Invisible</Visibility>
<pVariable Name="SWITCH_TARGET">TriggerSelector</pVariable>
<Formula>( SWITCH_TARGET = 2 ) ? 0 : ( ( SWITCH_TARGET = 3 ) ? 1 : ( ( SWITCH_TARGET = 4 ) ? 2 : 0 ) )</Formula>
</IntSwissKnife>
And Trigger selector is itself an enum:
<Enumeration Name="TriggerSelector" NameSpace="Standard">
<ToolTip>Selects the type of trigger to configure.</ToolTip>
<Description>Selects the type of trigger to configure.</Description>
<DisplayName>Trigger Selector</DisplayName>
<Visibility>Beginner</Visibility>
<ImposedAccessMode>RW</ImposedAccessMode>
<EnumEntry Name="AcquisitionStart" NameSpace="Standard">
<DisplayName>Acquisition Start</DisplayName>
<pIsImplemented>TriggerSourceAcquisitionStart_Imp</pIsImplemented>
<pIsAvailable>TriggerSourceAcquisitionStart_Avl</pIsAvailable>
<Value>2</Value>
</EnumEntry>
<EnumEntry Name="FrameStart" NameSpace="Standard">
<DisplayName>Frame Start</DisplayName>
<pIsImplemented>TriggerSourceFrameStart_Imp</pIsImplemented>
<pIsAvailable>TriggerSourceFrameStart_Avl</pIsAvailable>
<Value>3</Value>
</EnumEntry>
<EnumEntry Name="FrameBurstStart" NameSpace="Standard">
<DisplayName>Frame Burst Start</DisplayName>
<pIsImplemented>TriggerSourceFrameBurstStart_Imp</pIsImplemented>
<pIsAvailable>TriggerSourceFrameBurstStart_Avl</pIsAvailable>
<Value>4</Value>
</EnumEntry>
<Value>3</Value>
<pSelected>TriggerMode</pSelected>
<pSelected>TriggerSoftware</pSelected>
<pSelected>TriggerSource</pSelected>
<pSelected>TriggerActivation</pSelected>
<pSelected>TriggerOverlap</pSelected>
<pSelected>TriggerDelay</pSelected>
</Enumeration>
I have to check, but it is possible the read of the TriggerSelector value may cause a read if its enum entry Implemented and Available properties, which would lead to more register reads. That part could be also improved.
So, in the end, registers are read numerous times, which probably explains the huge numbers you are seeing. Proper caching would help a lot.
Regarding the difference between GigEVision and USB, may be the genicam definition of TriggerSource is simpler.
Thanks for the explanation, that makes sense.
@MarkRivers I've tried to fix register caching, but I'm not sure I will be able to enable it by default, it looks like most of the devices don't declare correctly the cachable and pInvalidators properties.
The resulting work is in this branch: https://github.com/AravisProject/aravis/tree/wip/cache
There is 3 cache modes: disable, enable and debug, that can be selected using arv_device_set_register_cache_policy.
The viewer takes a -c option for the policy selection.
In the debug mode, the register is always read, whatever the cache validity is, and the resulting read and the cache content is compared. Is they don't match, an error is displayed on the console. When the device is released, a statistic of cache hits and misses is also displayed.
Could you test it please ?
@EmmanuelP thanks for working on this.
I have checked out the wip/cache branch. I am not sure how to build it, with ./configure or meson?
When I use ./configure I get this error:
config.status: creating docs/Makefile
config.status: creating docs/reference/Makefile
config.status: creating docs/reference/aravis/Makefile
config.status: error: cannot find input file: `aravis.pc.in'
When I use meson I get this error:
corvette:/usr/local/aravis>meson build
The Meson build system
Version: 0.47.2
Source dir: /usr/local/aravis
Build dir: /usr/local/aravis/build
Build type: native build
Project name: aravis
Project version: 0.7.0
Native C compiler: cc (gcc 4.8.5 "cc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-28)")
Native C++ compiler: c++ (gcc 4.8.5 "c++ (GCC) 4.8.5 20150623 (Red Hat 4.8.5-28)")
Build machine cpu family: x86_64
Build machine cpu: x86_64
Found pkg-config: /bin/pkg-config (0.27.1)
Native dependency glib-2.0 found: YES 2.54.2
Native dependency gobject-2.0 found: YES 2.54.2
Native dependency gio-2.0 found: YES 2.54.2
Native dependency libxml-2.0 found: YES 2.9.1
Native dependency zlib found: YES 1.2.7
Library m found: YES
meson.build:36:1: ERROR: Native dependency 'audit' not found
A full log can be found at /usr/local/aravis/build/meson-logs/meson-log.txt
I have never used meson before, so this could be something simple. The OS is Centos 7.
I realized that the problem might be that it needed a package called "audit", so I installed that with yum install.
...
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
Updating : audit-libs-2.8.4-4.el7.x86_64 1/6
Updating : audit-2.8.4-4.el7.x86_64 2/6
Updating : audit-libs-2.8.4-4.el7.i686 3/6
Cleanup : audit-2.8.1-3.el7_5.1.x86_64 4/6
Cleanup : audit-libs-2.8.1-3.el7_5.1 5/6
Cleanup : audit-libs-2.8.1-3.el7_5.1 6/6
Verifying : audit-libs-2.8.4-4.el7.x86_64 1/6
Verifying : audit-2.8.4-4.el7.x86_64 2/6
Verifying : audit-libs-2.8.4-4.el7.i686 3/6
Verifying : audit-libs-2.8.1-3.el7_5.1.x86_64 4/6
Verifying : audit-2.8.1-3.el7_5.1.x86_64 5/6
Verifying : audit-libs-2.8.1-3.el7_5.1.i686 6/6
Updated:
audit.x86_64 0:2.8.4-4.el7
Dependency Updated:
audit-libs.i686 0:2.8.4-4.el7 audit-libs.x86_64 0:2.8.4-4.el7
It seems to have installed OK. However, meson still fails:
corvette:/usr/local/aravis>meson build
The Meson build system
Version: 0.47.2
Source dir: /usr/local/aravis
Build dir: /usr/local/aravis/build
Build type: native build
Project name: aravis
Project version: 0.7.0
Native C compiler: cc (gcc 4.8.5 "cc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-28)")
Native C++ compiler: c++ (gcc 4.8.5 "c++ (GCC) 4.8.5 20150623 (Red Hat 4.8.5-28)")
Build machine cpu family: x86_64
Build machine cpu: x86_64
Found pkg-config: /bin/pkg-config (0.27.1)
Native dependency glib-2.0 found: YES 2.54.2
Native dependency gobject-2.0 found: YES 2.54.2
Native dependency gio-2.0 found: YES 2.54.2
Native dependency libxml-2.0 found: YES 2.9.1
Native dependency zlib found: YES 1.2.7
Library m found: YES
meson.build:36:1: ERROR: Native dependency 'audit' not found
A full log can be found at /usr/local/aravis/build/meson-logs/meson-log.txt
I cannot find a file called audit.pc anywhere in /usr.
Meson is the one and only build system now. Your configure file is a leftover of the time autotools was still used.
You need the development package of audit: audit-libs-devel
After installing a number of other packages I got "meson build" to work.
I then cd to the build directory. The README.md says to type "ninja" but on Centos7 the command seems to be "ninja-build" not "ninja"?
I then get an error:
corvette:/usr/local/aravis>rm -rf build
corvette:/usr/local/aravis>meson build
The Meson build system
Version: 0.47.2
Source dir: /usr/local/aravis
Build dir: /usr/local/aravis/build
Build type: native build
Project name: aravis
Project version: 0.7.0
Native C compiler: cc (gcc 4.8.5 "cc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-28)")
Native C++ compiler: c++ (gcc 4.8.5 "c++ (GCC) 4.8.5 20150623 (Red Hat 4.8.5-28)")
Build machine cpu family: x86_64
Build machine cpu: x86_64
Found pkg-config: /bin/pkg-config (0.27.1)
Native dependency glib-2.0 found: YES 2.54.2
Native dependency gobject-2.0 found: YES 2.54.2
Native dependency gio-2.0 found: YES 2.54.2
Native dependency libxml-2.0 found: YES 2.9.1
Native dependency zlib found: YES 1.2.7
Library m found: YES
Native dependency audit found: YES 2.8.4
Native dependency libusb-1.0 found: YES 1.0.21
Configuring arvfeatures.h using configuration
Configuring arvversion.h using configuration
Native dependency gobject-introspection-1.0 found: YES 1.50.0
Native dependency gtk+-3.0 found: YES 3.22.30
Native dependency gstreamer-base-1.0 found: YES 1.10.4
Native dependency gstreamer-app-1.0 found: YES 1.10.4
Native dependency gstreamer-video-1.0 found: YES 1.10.4
Native dependency libnotify found: YES 0.7.7
Native dependency glib-2.0 found: YES 2.54.2
Configuring arv-viewer-0.8.appdata.xml using configuration
Dependency gstreamer-base-1.0 found: YES (cached)
Dependency gstreamer-app-1.0 found: YES (cached)
Build targets in project: 38
Found ninja-1.7.2 at /bin/ninja-build
corvette:/usr/local/aravis>cd build
/usr/local/aravis/build
corvette:local/aravis/build>ninja-build
[128/130] Linking target viewer/arv-viewer-0.8.
FAILED: viewer/arv-viewer-0.8
cc -o viewer/arv-viewer-0.8 'viewer/viewer@@arv-viewer-0.8@exe/meson-generated_.._arvviewerresources.c.o' 'viewer/viewer@@arv-viewer-0.8@exe/main.c.o' 'viewer/viewer@@arv-viewer-0.8@exe/arvviewer.c.o' -Wl,--no-undefined -Wl,--as-needed -Wl,--start-group src/libaravis-0.8.so.0.7.0 /usr/lib64/libglib-2.0.so /usr/lib64/libgobject-2.0.so /usr/lib64/libgio-2.0.so /usr/lib64/libxml2.so /usr/lib64/libz.so -lm /lib64/libaudit.so /usr/lib64/libusb-1.0.so /usr/lib64/libgtk-3.so /usr/lib64/libgdk-3.so /usr/lib64/libatk-1.0.so /usr/lib64/libpangocairo-1.0.so /usr/lib64/libgdk_pixbuf-2.0.so /usr/lib64/libcairo-gobject.so /usr/lib64/libpango-1.0.so /usr/lib64/libcairo.so /usr/lib64/libgstbase-1.0.so /usr/lib64/libgstreamer-1.0.so /usr/lib64/libgstapp-1.0.so /usr/lib64/libgstvideo-1.0.so /usr/lib64/libnotify.so -Wl,--end-group '-Wl,-rpath,$ORIGIN/../src:$ORIGIN/../../../../../lib64' -Wl,-rpath-link,/usr/local/aravis/build/src:/lib64
/usr/lib64/libcairo.so: undefined reference to `FT_Get_Var_Design_Coordinates'
/usr/lib64/libcairo.so: undefined reference to `FT_Get_Var_Blend_Coordinates'
collect2: error: ld returned 1 exit status
[129/130] Generating Aravis-0.8.gir with a custom command.
ninja: build stopped: subcommand failed.
corvette:local/aravis/build>ls
Any idea how to fix this? I think it has successfully built the aravis library and arvtool at this point, but it won't install them because of the above error.
I would also be happy to just disable building the arv-viewer for now, but I am not sure which file to edit to do that.
meson configure -Dviewer=false
Which distribution are you using ? The undefined reference errors are weird...
/usr/lib64/libcairo.so: undefined reference to 'FT_Get_Var_Design_Coordinates'
/usr/lib64/libcairo.so: undefined reference to 'FT_Get_Var_Blend_Coordinates'
Do you have a custom libfreetype installed somewhere ?
Centos7 is the distribution I am using.
Do you have a custom libfreetype installed somewhere ?
I don't have any in /usr, /lib, or /lib64
1073743164 0 lrwxrwxrwx 1 root root 21 Oct 23 2017 /usr/lib64/libfreetype.so.6 -> libfreetype.so.6.10.0
1073743165 676 -rwxr-xr-x 1 root root 691736 Aug 2 2017 /usr/lib64/libfreetype.so.6.10.0
1104140251 0 lrwxrwxrwx 1 root root 21 Oct 23 2017 /usr/lib64/libfreetype.so -> libfreetype.so.6.10.0
corvette:aravisIOC/aravisApp/src>sudo find /lib -name 'libfreetype*' -ls
corvette:aravisIOC/aravisApp/src>sudo find /lib64 -name 'libfreetype*' -ls
I do have a newer version in the anaconda3 directory in my home directory, but those directories are not in my LD_LIBRARY_PATH or PATH.
2158261691 4 -rwxrwxr-x 1 epics domain users 1065 Aug 24 2018 /home/epics/anaconda3/pkgs/freetype-2.9.1-h8a8886c_1/lib/libfreetype.la
2158261958 0 lrwxrwxrwx 1 epics domain users 21 Aug 28 2018 /home/epics/anaconda3/pkgs/freetype-2.9.1-h8a8886c_1/lib/libfreetype.so -> libfreetype.so.6.16.1
2158261959 0 lrwxrwxrwx 1 epics domain users 21 Aug 28 2018 /home/epics/anaconda3/pkgs/freetype-2.9.1-h8a8886c_1/lib/libfreetype.so.6 -> libfreetype.so.6.16.1
2158261961 760 -rwxrwxr-x 2 epics domain users 778224 Aug 24 2018 /home/epics/anaconda3/pkgs/freetype-2.9.1-h8a8886c_1/lib/libfreetype.so.6.16.1
2158261962 948 -rw-rw-r-- 2 epics domain users 968668 Aug 24 2018 /home/epics/anaconda3/pkgs/freetype-2.9.1-h8a8886c_1/lib/libfreetype.a
2158261962 948 -rw-rw-r-- 2 epics domain users 968668 Aug 24 2018 /home/epics/anaconda3/lib/libfreetype.a
1078561232 0 lrwxrwxrwx 1 epics domain users 21 Feb 5 2019 /home/epics/anaconda3/lib/libfreetype.so -> libfreetype.so.6.16.1
1078561233 0 lrwxrwxrwx 1 epics domain users 21 Feb 5 2019 /home/epics/anaconda3/lib/libfreetype.so.6 -> libfreetype.so.6.16.1
2158261961 760 -rwxrwxr-x 2 epics domain users 778224 Aug 24 2018 /home/epics/anaconda3/lib/libfreetype.so.6.16.1
1078561231 4 -rwxrwxr-x 1 epics domain users 1032 Feb 5 2019 /home/epics/anaconda3/lib/libfreetype.la
I tried removing the anaconda3/bin directory from my PATH but that did not fix the error building arv-viewer.
Building with -Dviewer=false allowed the build and install to complete. I can now begin to test my application.
I was hoping that this would finally solve the slowness of QArv's feature browser, but it has no discernible effect. In particular, color transformation features of Basler-acA1300-30gc are especially problematic (the grayscale version of the same Basler camera responds much more quickly).
Looking at XML dumped from Basler-acA1300-30gc, it only specifies WriteAround and NoCache for a few registers and nothing for most of them, so it seems to me that it assumes WriteThrough as default.
Skimming through arvgcregisternode.c
, it seems that arv_gc_register_node_new_*
functions set the defaults mostly to WriteThrough (BTW, there's a typo: TRHOUGH), except for floats (WriteAround) and structs (NoCache). But then arv_gc_register_node_init()
, which is the function that allocates the cache hash table, sets
gc_register_node->default_cachable = ARV_GC_CACHABLE_NO_CACHE;
Does this mean that the default cacheability is actually NoCache?
Hi Jure,
Did you enable caching with arv_device_set_register_cache_policy()
?
Does this mean that the default cacheability is actually NoCache?
arv_gc_register_node_init()
is executed during object initialization in g_object_new()
. default_cachable
is overriden in the different arv_gc_register_node_new_*()
constructors.
If you set ARV_DEBUG=genicam
, a cache hit/miss statistic will be displayed when the device object is finalized. Something like that:
Cache hits = 1 / 1 for DeviceModelName
Cache hits = 1 / 2 for SensorHeightRegister
Cache hits = 1 / 2 for SensorWidthRegister
Cache hits = 1 / 2 for OffsetXRegister
Cache hits = 1 / 2 for OffsetYRegister
Cache hits = 3 / 4 for WidthRegister
Cache hits = 3 / 4 for HeightRegister
Cache hits = 0 / 1 for BinningHorizontalRegister
Cache hits = 0 / 1 for BinningVerticalRegister
Cache hits = 3 / 4 for PixelFormatRegister
Cache hits = 0 / 1 for AcquisitionFramePeriodRegister
Cache hits = 0 / 1 for ExposureTimeAbsRegister
Cache hits = 0 / 1 for GainRawRegister
Cache hits = 2 / 3 for GainAutoRegister
arv_gc_register_node_init() is executed during object initialization in g_object_new(). default_cachable is overriden in the different arv_gc_register_nodenew*() constructors.
I see. Shows how little I work with gobject :)
I did set the cache policy, of course, and I also noticed that cache hit stats were printed; they looked good, but the performance was not, which is why I'm looking into it. Sadly, I don't have much time to play with an actual camera.
So in the meantime, I'm trying to understand the code. And AFAICT, arv_gc_port_read
is called regardless of whether the value is cached or not. Shouldn't the read only happen under the debug policy?
BTW, cache hit stats are printed on finalization regardless of any debug settings, but they are meaningless without the debug cache policy.
So in the meantime, I'm trying to understand the code. And AFAICT, arv_gc_port_read is called regardless of whether the value is cached or not. Shouldn't the read only happen under the debug policy?
You are right. I'm going to fix that.
I apologize for not being able to test this sooner.
I have now tested using the FLIR Spinnaker SDK, aravis 0.6.3 and the aravis wip/cache as of October 7, 2019. I test the time to write the ExposureTime feature and then read back the values of all other features. So far I have tested on a GigE BlackkFlyS camera. These are the results:
BlackFlyS 13Y3M | ||
---|---|---|
SDK | Caching | Time (s) |
Spinnaker | N.A. | 0.036 |
aravis 0.6.3 | N.A. | 1.569 |
aravis wip/cache | ARV_REGISTER_CACHE_POLICY_DISABLE | 6.634 |
aravis wip/cache | ARV_REGISTER_CACHE_POLICY_ENABLE | 6.658 |
aravis wip/cache | ARV_REGISTER_CACHE_POLICY_DEBUG | 6.610 |
So Spinnaker takes on 36 ms. With the stable aravis 0.6.3is takes 1.57 seconds. However, with the wip/cache branch it takes 6.6 seconds no matter what value I use for arv_gc_set_register_cache_policy(). I read back and print the actual cache policy to verify that it is being set correctly.
Perhaps I am doing something wrong? Is wip/cache still the branch I should be testing?
I apologize for not being able to test this sooner.
No need to apologize, I'm happy you are testing aravis.
Is wip/cache still the branch I should be testing?
No, sorry, I should have deleted it. The branch was merged into master a while ago.
Could you re-run your tests using aravis master ?
I have switched to the master branch. I changed the feature set/get calls to add the new GError** argument which I set to NULL.
BlackFlyS 13Y3M | ||
---|---|---|
SDK | Caching | Time (s) |
ADSpinnaker | N.A. | 0.036 |
aravis 0.6.3 | N.A. | 1.569 |
aravis wip/cache | ARV_REGISTER_CACHE_POLICY_DISABLE | 6.634 |
aravis wip/cache | ARV_REGISTER_CACHE_POLICY_ENABLE | 6.658 |
aravis wip/cache | ARV_REGISTER_CACHE_POLICY_DEBUG | 6.610 |
aravis/master | ARV_REGISTER_CACHE_POLICY_DISABLE | 6.612 |
aravis/master | ARV_REGISTER_CACHE_POLICY_ENABLE | 5.067 |
aravis/master | ARV_REGISTER_CACHE_POLICY_DEBUG | 6.627 |
It looks like that with ENABLE it is a little faster than with the wip/cache branch, but is still more than 3 times slower than the 0.6.3 branch and is more than 100 times slower than Spinnaker.
I ran my application with ARV_DEBUG=genicam:3. This is the output: aravisDebug.txt
With genicam=3, we should see cache hits/miss debug output when the cache is either enabled or in debug mode. I don't see that in aravisDebug.txt.
Something like that:
Cache hits = 7 / 8 for GainRawAll_Imp
Cache hits = 7 / 8 for GainRawAll_Avl
Cache hits = 1 / 2 for Gain_Val
Cache hits = 0 / 1 for Gain_Min
Cache hits = 0 / 1 for Gain_Max
Cache hits = 2 / 3 for PixelFormat_Val
Cache hits = 4 / 5 for PixelFormat_Mono8_Avl
Cache hits = 4 / 5 for PixelFormat_Mono16_Avl
Cache hits = 4 / 5 for PixelFormat_RGB8Packed_Avl
Cache hits = 4 / 5 for PixelFormat_BayerGR8_Avl
Cache hits = 4 / 5 for PixelFormat_BayerRG8_Avl
Cache hits = 4 / 5 for PixelFormat_BayerGB8_Avl
...
With genicam=3, we should see cache hits/miss debug output when the cache is either enabled or in debug mode. I don't see that in aravisDebug.txt.
Yes, I was wondering about that.
I cannot figure out what I am doing wrong.
I am running the master branch. The aravis version returned with ARAVIS_MAJOR_VERSION, ARAVIS_MINOR_VERSION, ARAVIS_MICRO_VERSION is 0.7.2.
ARV_DEBUG is set as follows:
corvette:aravisIOC/iocBoot/iocAravis>echo $ARV_DEBUG
genicam:3
In my application I print out the value of arv_gc_get_register_cache_policy() whenever an integer feature is being set. In the text file above you will see lines like this:
2019/10/08 09:34:17.349 ADAravis::writeInt32 arv_gc_get_register_cache_policy = 1
This shows that the cache policy is set to Enable (1).
What could be causing the absence of the cache debugging messages?
This is the code where I set the cache policy. I do this as soon as I get the genicam object:
asynStatus ADAravis::makeCameraObject() {
const char *functionName = "makeCameraObject";
/* remove old camera if it exists */
if (this->camera != NULL) {
g_object_unref(this->camera);
this->camera = NULL;
}
/* remove ref to device and genicam */
this->device = NULL;
this->genicam = NULL;
/* connect to camera */
printf ("ADAravis: Looking for camera '%s'... \n", this->cameraName);
this->camera = arv_camera_new (this->cameraName);
if (this->camera == NULL) {
asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
"%s:%s: No camera found\n",
driverName, functionName);
return asynError;
}
/* Store device */
this->device = arv_camera_get_device(this->camera);
if (this->device == NULL) {
asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
"%s:%s: No device associated with camera\n",
driverName, functionName);
return asynError;
}
if (ARV_IS_GV_DEVICE(this->device)) {
// Automatically determine optimum packet size
arv_gv_device_auto_packet_size(ARV_GV_DEVICE(this->device));
// Uncomment this line to set jumbo packets
//arv_gv_device_set_packet_size(ARV_GV_DEVICE(this->device), 9000);
}
/* Store genicam */
this->genicam = arv_device_get_genicam (this->device);
if (this->genicam == NULL) {
asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
"%s:%s: No genicam element associated with camera\n",
driverName, functionName);
return asynError;
}
/* Set the cache policy */
arv_gc_set_register_cache_policy(this->genicam, ARV_REGISTER_CACHE_POLICY_ENABLE);
return asynSuccess;
}
The previous tests were run on a Centos 7 system with a BlackFlyS GigE camera.
Today I installed the master branch on an Ubuntu 18 system today. I built the same application and tested with an Oryx 10 GigE camera. I ran with cache enabled and ARV_DEBUG=genicam:3. The results are attached here: oryx_debug1.txt
Again I do not see the cache debug messages.
This table shows the time to read all of the features after changing ExposureTime.
Oryx 10G-51S5M | ||
---|---|---|
SDK | Caching | |
ADSpinnaker | N.A. | 0.039 |
aravis 0.6.3 | N.A. | 11.819 |
aravis/master | ARV_REGISTER_CACHE_POLICY_ENABLE | 5.107 |
So 0.7.2 with cache enabled is faster than 0.6.3, but much slower than Spinnaker.
Hi Mark,
I have pushed to master a new feature to arv-tool that shows the values of all the device features, with an optional display of the execution time and the slection of the cache policy.
Please attach the result of:
arv-tool-0.8 values -c disable -t -d genicam values
and
arv-tool-0.8 values -c enable -t -d genicam values
That will help to understand what you get.
Please note the value display is still incomplete, as arv-tool doesn't yet iterate over all the values of the feature pSelected node.
This is the output with disable: arv_tool_disable.txt
This is the output with enable: arv_tool_enable.txt
I see that the cache statistics are printed in the arv_gc_register_node_finalize() function. I am not seeing those messages. When is that method called?
Here are the results for an Oryx camera on Ubuntu 18. arv_tool_oryx_disable.txt arv_tool_oryx_enable.txt
I have now tested with all 3 caching options on both cameras, as well as 0.6.3 and Spinnaker.
BlackFlyS on Centos 7
BlackFlyS 13Y3M | ||
---|---|---|
SDK | Caching | Time (s) |
ADSpinnaker | N.A. | 0.036 |
aravis 0.6.3 | N.A. | 1.569 |
aravis/master | ARV_REGISTER_CACHE_POLICY_DISABLE | 6.612 |
aravis/master | ARV_REGISTER_CACHE_POLICY_DEBUG | 6.627 |
aravis/master | ARV_REGISTER_CACHE_POLICY_ENABLE | 5.067 |
Oryx on Ubuntu 18
Oryx 10G-51S5M | ||
---|---|---|
SDK | Caching | Time (s) |
ADSpinnaker | N.A. | 0.039 |
aravis 0.6.3 | N.A. | 11.819 |
aravis/master | ARV_REGISTER_CACHE_POLICY_DISABLE | 16.930 |
aravis/master | ARV_REGISTER_CACHE_POLICY_DEBUG | 16.738 |
aravis/master | ARV_REGISTER_CACHE_POLICY_ENABLE | 5.107 |
Major conclusions:
I have pushed a fix to master that handle the case of event features, which should improve the overall time of reading all the feature values.
Success!!!
Here is the performance now:
BlackFlyS 13Y3M | ||
---|---|---|
SDK | Caching | Time (s) |
ADSpinnaker | N.A. | 0.036 |
aravis 0.6.3 | N.A. | 1.569 |
aravis/master | ARV_REGISTER_CACHE_POLICY_DISABLE | 1.596 |
aravis/master | ARV_REGISTER_CACHE_POLICY_DEBUG | 1.594 |
aravis/master | ARV_REGISTER_CACHE_POLICY_ENABLE | 0.062 |
Oryx 10G-51S5M | ||
---|---|---|
SDK | Caching | Time (s) |
ADSpinnaker | N.A. | 0.039 |
aravis 0.6.3 | N.A. | 11.819 |
aravis/master | ARV_REGISTER_CACHE_POLICY_DISABLE | 11.729 |
aravis/master | ARV_REGISTER_CACHE_POLICY_DEBUG | |
aravis/master | ARV_REGISTER_CACHE_POLICY_ENABLE | 0.096 |
The performance with caching disabled is now the same as 0.6.3, rather than worse.
With caching the performance improves by factor of 25 for the BlackFlyS and 122 for the Oryx. The times are now very comparable to Spinnaker.
I think aravis is now completely usable for my application.
Thanks very much!
Ok, let's say cache is implemented almost correctly now.
I'm not activating it by default, because it seems camera genicam data don't always correctly declare the feature node cachable and invalidator properties.
If you find cache related issue, don't hesitate to open a new issue.
Cheers,
Emmanuel.
The code that is supposed to handle register cache in arvgcregisternode.c is broken: