main addition is array performance example
This commit is contained in:
@@ -38,23 +38,18 @@
|
||||
<h1>pvDatabaseCPP</h1>
|
||||
<!-- Maturity: Working Draft or Request for Comments, or Recommendation, and date. -->
|
||||
|
||||
<h2 class="nocount">EPICS v4 Working Group, Working Draft, 06-Aug-2013</h2>
|
||||
<h2 class="nocount">EPICS v4 Working Group, Working Draft, 28-Aug-2013</h2>
|
||||
<dl>
|
||||
<dt>Latest version:</dt>
|
||||
<dd><a
|
||||
href="http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/pvDatabaseCPP/raw-file/tip/documentation/pvDatabaseCPP.html">pvDatabaseCPP.html</a>
|
||||
href="pvDatabaseCPP.html">pvDatabaseCPP.html</a>
|
||||
</dd>
|
||||
<dt>This version:</dt>
|
||||
<dd><a
|
||||
href=
|
||||
"http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/pvDatabaseCPP/raw-file/tip/documentation/pvDatabaseCPP_20130806.html">
|
||||
pvDatabaseCPP20130806.html</a>
|
||||
href= "pvDatabaseCPP_20130828.html">pvDatabaseCPP20130828.html</a>
|
||||
</dd>
|
||||
<dt>Previous version:</dt>
|
||||
<dd><a
|
||||
href=
|
||||
"http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/pvDatabaseCPP/raw-file/tip/documentation/pvDatabaseCPP_20130725.html">
|
||||
pvDatabaseCPP20130725.html</a>
|
||||
<dd><a href="pvDatabaseCPP_20130725.html">pvDatabaseCPP20130725.html</a>
|
||||
</dd>
|
||||
<dt>Editors:</dt>
|
||||
<dd>Marty Kraimer, BNL</dd>
|
||||
@@ -78,33 +73,44 @@ The minimum that an extenson must provide is a top level PVStructure and a proce
|
||||
|
||||
<h2 class="nocount">Status of this Document</h2>
|
||||
|
||||
<p>This is the 06-Aug-2013 version of the definition of pvDatabaseCPP.
|
||||
<p>This is the 28-Aug-2013 version of of pvDatabaseCPP.
|
||||
<p><b>NOTE:</b>
|
||||
This is built against pvDataCPP-md NOT against pvDataCPP.
|
||||
To build you must also
|
||||
checkout pvAccessCPP and build it against pvDataCPP-md.
|
||||
</p>
|
||||
</p>
|
||||
<p>All channel methods except channelRPCi, which is implemented
|
||||
<p>All channel methods except channelRPC, which is implemented
|
||||
by pvAccess, have been implemented.
|
||||
This project is ready for alpha users.
|
||||
</p>
|
||||
<p>Future enhancements in priority order:</p>
|
||||
<dl>
|
||||
<dt>Termination issues.</dt>
|
||||
<dd>There are memory leak and other issues when either the main programs or v3IOC terminates.</dd>
|
||||
<dt>Array performance</dt>
|
||||
<dd>Create an example record that continuously creates array data.
|
||||
The idea is to compare performance allocating memory from the
|
||||
heap vs using a free list.</dd>
|
||||
<dt>Separate example that also has pvaSrv</dt>
|
||||
<dd>Create a separate example that combines a V3IOC,
|
||||
a pvDatabase, and pvaSrv.</dd>
|
||||
a pvDatabase, and pvaSrv.
|
||||
This will not be done until pvDataCPP-md is merged into pvDataCPP.
|
||||
</dd>
|
||||
<dt>channelArray</dt>
|
||||
<dd>The arguments that have type <b>int</b> should be changed to <b>size_t</b>
|
||||
This will not be done until pvDataCPP-md is merged into pvDataCPP.
|
||||
</dd>
|
||||
<dt>arrayPerformanceMain</dt>
|
||||
<dd>When this is run without a pvAccess client the performance is great.
|
||||
But when a pvAccess client is monitoring then the preformance slows
|
||||
more then expected.
|
||||
I do not understand and must spend more time determining why.</dd>
|
||||
<dt>Monitor Algorithms</dt>
|
||||
<dd>Monitor algorithms have not been implemented.
|
||||
Thus all monitors are onPut.</dd>
|
||||
<dt>Testing</dt>
|
||||
<dd>Needs more testing</dd>
|
||||
<dd>Needs more testing.
|
||||
Also none of the examples that use pvAccess can be run with gdb.
|
||||
</dd>
|
||||
<dt>Termination issues.</dt>
|
||||
<dd>longArrayMonitor has memory leaks when main terminates.</dt>
|
||||
<dt>Create regression tests</dt>
|
||||
<dd>Currently only examples exist and have been used for testing.</dd>
|
||||
</dl>
|
||||
|
||||
<div id="toc">
|
||||
@@ -228,7 +234,7 @@ try starting exampleServerMain and exampleServer.
|
||||
<p>This example provides the exampleCounter record in addition to a number of other PVRecords.
|
||||
Like exampleCounter it can be started either as a standalone main program or as
|
||||
a part of a V3IOC.
|
||||
The exampleServer pvDatabase includes the following records:</p>
|
||||
The exampleServer pvDatabase has many records including the following:</p>
|
||||
<dl>
|
||||
<dt>exampleCounter</dt>
|
||||
<dd>A record that is an instance of exampleCounter described below.
|
||||
@@ -245,7 +251,7 @@ The exampleServer pvDatabase includes the following records:</p>
|
||||
<dd>Can be used by channelGet, channelPut, channelPutGet, and monitor.</dd>
|
||||
<dt>laptoprecordListPGRPC</dt>
|
||||
<dd>Implements the record expected by swtshell channelList.
|
||||
It can also be used via channelPutGet but unnecessary.</dd>
|
||||
It can also be used via channelPutGet.</dd>
|
||||
<dt>traceRecordPGRPC</dt>
|
||||
<dd>This can be used via channelPutGet to set the trace level of another record.</dd>
|
||||
</dl>
|
||||
@@ -253,14 +259,14 @@ The exampleServer pvDatabase includes the following records:</p>
|
||||
<h3>swtshell</h3>
|
||||
<p>The Java program
|
||||
<a
|
||||
href="http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/swtshellJava/raw-file/tip/documentation/swtshellJava.html">
|
||||
href="http://epics-pvdata.sourceforge.net/docbuild/swtshellJava/tip/documentation/swtshellJava.html">
|
||||
swtshell</a>
|
||||
can be used to access pvDatabase.</p>
|
||||
<p>In particular read the sections "Getting Started" and "Simple Example".
|
||||
They will work on the exampleServer with the following differences:
|
||||
<dl>
|
||||
<dt>startExample.zip</dt>
|
||||
<dd>Do NOT use this. Instead run exampleServer</dd>
|
||||
<dd>Do NOT use this. Instead run the exampleServer as described above.</dd>
|
||||
<dt>channelList result</dt>
|
||||
<dd>The result of channelList will show the list of records that
|
||||
exampleServer has rather than the records from startExample.zip</dd>
|
||||
@@ -270,7 +276,7 @@ They will work on the exampleServer with the following differences:
|
||||
<h3>Relationship with pvIOCJava.</h3>
|
||||
<p>This document descibes a C++ implementation of some of the components in pvIOCJava,
|
||||
which also implements a pvDatabase.
|
||||
PVDatabaseCPP extracts the core components required to create a network accessible database of smart
|
||||
PVDatabaseCPP implements the core components required to create a network accessible database of smart
|
||||
memory resident records.
|
||||
pvDatabaseCPP does not implement any of the specialized support that pvIOCJava
|
||||
provides.
|
||||
@@ -308,11 +314,11 @@ mrk> bin/linux-x86_64/exampleCounter
|
||||
by a pvAccess client.
|
||||
It is located in directory pvDatabaseCPP/example/exampleCounter.
|
||||
</dd>
|
||||
<dt>v3IOC/exampleCounter</dt>
|
||||
<dt>V3IOC/exampleCounter</dt>
|
||||
<dd>This is a directory that packages exampleCounter to make it
|
||||
part of a v3IOC.</dd>
|
||||
part of a V3IOC.</dd>
|
||||
<dt>iocBoot/exampleCounter</dt>
|
||||
<dd>A place to start exampleCounter as part of a v3IOC.
|
||||
<dd>A place to start exampleCounter as part of a V3IOC.
|
||||
It follows the normal iocCore conventions.</dd>
|
||||
</dl>
|
||||
<h4>ExampleCounter.h</h4>
|
||||
@@ -425,7 +431,7 @@ bool ExampleCounter::init()
|
||||
initPVRecord();
|
||||
epics::pvData::PVFieldPtr pvField;
|
||||
pvValue = getPVStructure()->getLongField("value");
|
||||
if(pvValue.get()==NULL) return false;
|
||||
if(pvValue==NULL) return false;
|
||||
return true;
|
||||
}
|
||||
</pre>
|
||||
@@ -487,19 +493,19 @@ This:
|
||||
<li>Prints exampleCounter on standard out.</li>
|
||||
<li>Runs forever until the user types exit on standard in.</li>
|
||||
</ul>
|
||||
<h4>v3IOC exampleCounter</h4>
|
||||
<h4>V3IOC exampleCounter</h4>
|
||||
<p>This has two subdirectories:
|
||||
<dl>
|
||||
<dt>Db</dt>
|
||||
<dd>This has a template for a single v3Record.</dd>
|
||||
<dt>src</dt>
|
||||
<dd>This has code to allow exampleCounter to reside in a v3IOC.</dd>
|
||||
<dd>This has code to allow exampleCounter to reside in a V3IOC.</dd>
|
||||
</dl>
|
||||
</p>
|
||||
<p>The src directory has the following components:</p>
|
||||
<dl>
|
||||
<dt>exampleCounterMain.cpp</dt>
|
||||
<dd>This is just a standard Main for a v3IOC.</dd>
|
||||
<dd>This is just a standard Main for a V3IOC.</dd>
|
||||
<dt>exampleCounterInclude.dbd</dt>
|
||||
<dd>This is:
|
||||
<pre>
|
||||
@@ -514,7 +520,7 @@ registrar("exampleCounterRegister")
|
||||
</dd>
|
||||
<dt>exampleCounter.cpp</dt>
|
||||
<dd>This is the code that registers a command the can be issued
|
||||
via the iocsh, which is the console for a v3IOC.
|
||||
via the iocsh, which is the console for a V3IOC.
|
||||
The example supports a single command:
|
||||
<pre>
|
||||
exampleCounterCreateRecord recordName
|
||||
@@ -561,9 +567,9 @@ The rest of this document discusses only the first phase.</p>
|
||||
<dt>PVRecord and PVDatabase</dt>
|
||||
<dd>Defined below.</dd>
|
||||
<dt>The localChannelProvider itself</dt>
|
||||
<dd>This is the pvAccess package in pvIOCJava.
|
||||
The localChannelProvider will access data from PVRecords.
|
||||
It will implement all channel methods.</dd>
|
||||
<dd>This is the C++ implementation of package pvAccess in pvIOCJava.
|
||||
The localChannelProvider accesses data from PVRecords.
|
||||
It implements all channel methods except channelRPC, which is implemented by pvAccessCPP.</dd>
|
||||
</dl>
|
||||
<h3>Minumum Features Required for pvRecord</h3>
|
||||
<p>The first phase will only implement record processing, i. e.
|
||||
@@ -590,7 +596,7 @@ The following are the minimium features required</p>
|
||||
<p>The following sections describes the classes required for the first phase.</p>
|
||||
|
||||
<h2>iocshell commands</h2>
|
||||
<p>The following iocsh commands are provided:</p>
|
||||
<p>The following iocsh commands are provided for a V3IOC:</p>
|
||||
<dl>
|
||||
<dt>startPVAClient</dt>
|
||||
<dd>Starts the client side of pvAccess.s
|
||||
@@ -608,15 +614,16 @@ The following are the minimium features required</p>
|
||||
<dd>Provides a list of all the pvRecords in database <b>master</b>
|
||||
It is similar to the iocsh command <b>dbl</b></dd>
|
||||
</dl>
|
||||
<p>The client commands are provided via PVAClientRegister.dbd and the othet commands
|
||||
<p>The client commands are provided via PVAClientRegister.dbd and the other commands
|
||||
via PVAServerRegister.dbd.</p>
|
||||
<p>In addition any code that implements a PVRecord must implement an ioc command.
|
||||
The directory example has examples of how to implement the registration code.
|
||||
See example/v3IOC/exampleCounter/src/ for a simple example.</p>
|
||||
See example/V3IOC/exampleCounter/src/ for a simple example.</p>
|
||||
|
||||
|
||||
<h2>database</h2>
|
||||
<p>This directory has the following files:</p>
|
||||
<h3>src/database</h3>
|
||||
<p>This Directory has the following files:</p>
|
||||
<dl>
|
||||
<dt>pvDatabase.h</dt>
|
||||
<dd>
|
||||
@@ -634,10 +641,10 @@ See example/v3IOC/exampleCounter/src/ for a simple example.</p>
|
||||
This can be used to create a "dumb" record where all changes are
|
||||
done by clients.
|
||||
</dd>
|
||||
<dt>exampleCounter.h</dt>
|
||||
<dd>
|
||||
This was described in the introduction.
|
||||
</dd>
|
||||
</dl>
|
||||
<h3>src/special</h3>
|
||||
<p>This directory has the following files:</p>
|
||||
<dl>
|
||||
<dt>powerSupplyRecordTest.h</dt>
|
||||
<dd>
|
||||
This provides code that simulates a power supply.
|
||||
@@ -663,6 +670,7 @@ result = master->addRecord(pvRecord);
|
||||
another record. See below for a discussion of trace level.</dd>
|
||||
|
||||
</dl>
|
||||
<h3>pvDatabase.h</h3>
|
||||
<p>The classes in pvDatabase.h describe a database of memory resident
|
||||
smart records.
|
||||
It describes the following classes:</p>
|
||||
@@ -1121,7 +1129,7 @@ The only algorithm currently implemented is <b>onPut</b>
|
||||
<p><b>epics::pvData::monitor</b> defines the monitor interfaces
|
||||
as seen by a client.
|
||||
See
|
||||
<a href="http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/pvDatabaseCPP/raw-file/tip/documentation/pvDatabaseCPP.html">pvDatabaseCPP.html</a>
|
||||
<a href="http://epics-pvdata.sourceforge.net/docbuild/pvDatabaseCPP/tip/documentation/pvDatabaseCPP.html">pvDatabaseCPP.html</a>
|
||||
For details.</p>
|
||||
<p>
|
||||
monitorFactory implements the
|
||||
@@ -1324,7 +1332,7 @@ i. e. copy on write semantics are enforced. This is done automatically
|
||||
by pvData and not by pvDatabase.</p>
|
||||
<h4>Some details</h4>
|
||||
<p>As mentioned before a pvDatabase server can be either a separate process,
|
||||
i. e. a main program, or can be part of a v3IOC.</p>
|
||||
i. e. a main program, or can be part of a V3IOC.</p>
|
||||
<p>A main pvDatabase server issues the following calls:</p>
|
||||
<pre>
|
||||
ClientFactory::start();
|
||||
@@ -1363,7 +1371,7 @@ examplePVADoubleArrayGet shows how to use pvAccess to get data.</p>
|
||||
<dd>This is the implementation code for the example.</dd>
|
||||
<dt>example/examplePVADoubleArrayGet</dt>
|
||||
<dd>This is the code that starts the example as a main program.</dd>
|
||||
<dt>example/v3IOC/examplePVADoubleArrayGet/src</dt>
|
||||
<dt>example/V3IOC/examplePVADoubleArrayGet/src</dt>
|
||||
<dd>This is the code for starting the example as part of a V3IOC.</dd>
|
||||
<dt>iocBoot/examplePVADoubleArrayGet</dt>
|
||||
<dd>This has the st.cmd files to start the example.</dd>
|
||||
@@ -1557,7 +1565,7 @@ This is the record that can be accessed via pvAccess if the channelName is
|
||||
<p>It the runs forever until the exit is typed.</p>
|
||||
|
||||
<h4>Start the example as part of a V3IOC</h4>
|
||||
The directory example/v3IOC/examplePVADoubleArrayGet has two subdirectories: Db and src.
|
||||
The directory example/V3IOC/examplePVADoubleArrayGet has two subdirectories: Db and src.
|
||||
These are like for any other V3IOC application.
|
||||
The Db directory is for a regular ai record.
|
||||
The src directory has code similar to any V3IOC application.
|
||||
@@ -1579,6 +1587,140 @@ where
|
||||
<dd>This creates the example using the remote channel provider.</dd>
|
||||
</dl>
|
||||
|
||||
<h2>Array Performance</h2>
|
||||
<p>Two main programs are available for testing the performance of large
|
||||
arrays: arrayPerformanceMain and longArrayMonitorMain.
|
||||
Each has support for <b>-help</b>.</p>
|
||||
<pre>
|
||||
mrk> pwd
|
||||
/home/hg/pvDatabaseCPP-md
|
||||
mrk> bin/linux-x86_64/arrayPerformanceMain -help
|
||||
arrayPerformanceMain recordName size delay providerName nMonitor useQueue
|
||||
default
|
||||
arrayPerformance arrayPerformance 50000000 0.001 local 1 false
|
||||
mrk> bin/linux-x86_64/longArrayMonitorMain -help
|
||||
longArrayMonitorMain channelName useQueue
|
||||
default
|
||||
longArrayMonitorMain arrayPerformance false
|
||||
mrk>
|
||||
</pre>
|
||||
<h3>Example output</h3>
|
||||
<pre>
|
||||
mrk> bin/linux-x86_64/arrayPerformanceMain
|
||||
arrayPerformance arrayPerformance 50000000 0.01 local 1 false
|
||||
...
|
||||
first 0 last 0 sum 0 elements/sec 525.011million changed {1, 2} overrun {}
|
||||
first 1 last 1 sum 50000000 elements/sec 494.511million changed {1, 2} overrun {}
|
||||
first 2 last 2 sum 100000000 elements/sec 515.34million changed {1, 2} overrun {}
|
||||
first 3 last 3 sum 150000000 elements/sec 154.402million changed {1, 2} overrun {}
|
||||
first 4 last 4 sum 200000000 elements/sec 513.414million changed {1, 2} overrun {}
|
||||
first 5 last 5 sum 250000000 elements/sec 473.672million changed {1, 2} overrun {}
|
||||
first 6 last 6 sum 300000000 elements/sec 503.855million changed {1, 2} overrun {}
|
||||
arrayPerformance value 8 time 1.66373 iterations/sec 4.80847 elements/sec 240.424million
|
||||
...
|
||||
</pre>
|
||||
<h3>arrayPerformance</h3>
|
||||
<p>
|
||||
This creates a PVRecord that has the structure:.
|
||||
<pre>
|
||||
recordName
|
||||
long[] value
|
||||
timeStamp timeStamp
|
||||
alarm alarm
|
||||
</pre>
|
||||
Thus it holds an array of 64 bit integers.</p>
|
||||
<p>The record has support that consists of a separate thread that runs
|
||||
until the record is destroyed executing the following algorithm:</p>
|
||||
<dl>
|
||||
<dt>report</dt>
|
||||
<dd>At least once a second it produces a report.
|
||||
In the above example output each line starting with
|
||||
<b>ArrayPerformance</b> is an arrayPerformance report.
|
||||
</dd>
|
||||
<dt>create array</dt>
|
||||
<dd>A new shared_vector is created and each element is set equal
|
||||
to the interation count.</dd>
|
||||
<dt>lock</dt>
|
||||
<dd>The arrayPerformance record is locked.</dd>
|
||||
<dt>Begin group put</dt>
|
||||
<dd>beginGroupReport is called.</dd>
|
||||
<dt>replace</dt>
|
||||
<dd>The value field of the record is replaced
|
||||
with the newly created shared_vector.</dd>
|
||||
<dt>process</dt>
|
||||
<dd>The record is then processed. This causes the timeStamp to
|
||||
be set to the current time.</dd>
|
||||
<dt>End group put</dt>
|
||||
<dd>endGroupPut is called.</dd>
|
||||
<dt>unlock</dt>
|
||||
<dd>The arrayPerformance record is unlocked.</dd>
|
||||
<dt>delay</dt>
|
||||
<dd>If delay is greater than zero epicsThreadSleep is called.</dd>
|
||||
</dl>
|
||||
<p>The arguments for arrayPerforamanceMain are:</p>
|
||||
<dl>
|
||||
<dt>recordName</dt>
|
||||
<dd>The name for the arrayPerform record.</dd>
|
||||
<dt>size</dt>
|
||||
<dd>The size for the long array of the value field.</dd>
|
||||
<dt>delay</dt>
|
||||
<dd>The time in seconds to sleep after each iteration.</dd>
|
||||
<dt>providerName</dt>
|
||||
<dd>The name of the channel provider for the longArrayMonitors
|
||||
created by the main program. This must be either <b>local</b>
|
||||
or <b>pvAccess</b>.
|
||||
</dd>
|
||||
<dt>nMonitor</dt>
|
||||
<dd>The number of longArrayMonitors to create.</dd>
|
||||
<dt>useQueue</dt>
|
||||
<dd>Should the longArrayMonitors use a queue?
|
||||
This must be <b>true</b> or <b>false</b>.
|
||||
</dd>
|
||||
</dl>
|
||||
<h3>longArrayMonitor</h3>
|
||||
<p>This is a pvAccess client that monitors an arrayPerformance record.
|
||||
It generates a report for each monitor event.
|
||||
In the example output shown above each line starting with <b>first</b>
|
||||
is a report.</p>
|
||||
<p>The arguments for longArrayMonitorMain are:</p>
|
||||
<dl>
|
||||
<dt>channelName</dt>
|
||||
<dt>useQueue</dt>
|
||||
</dl>
|
||||
<h3>Some results</h3>
|
||||
<p>The results were from my laptop.
|
||||
It has a 2.2Ghz intel core i7 with 4Gbytes of memory.
|
||||
The operating system is linux fedora 16.</p>
|
||||
<p>When test are performed with large arrays it is a good idea to also
|
||||
run a system monitor facility and check memory and swap history.
|
||||
If a test configuration causes physical memory to be exhausted
|
||||
then performance becomes <b>very</b> poor.
|
||||
You do not want to do this.</p>
|
||||
<h4>arrayPerformance results</h4>
|
||||
<p>The simplest test to run arrayPerformance with the defaults:</p>
|
||||
<pre>
|
||||
mrk> pwd
|
||||
/home/hg/pvDatabaseCPP-md
|
||||
mrk> bin/linux-x86_64/arrayPerformanceMain
|
||||
</pre>
|
||||
<p>This means that the array will hold 50 million elements.
|
||||
The delay will be a millisecond.
|
||||
There will be a single monitor and it will connect directly
|
||||
to the local channelProvider, i. e. it will not use any network
|
||||
connection.</p>
|
||||
<p>The report shows that arrayPerformance can perform about 8 iterations per second
|
||||
and is putting about 350million elements per second.
|
||||
Since each element is an int64 this means about 2.8gigaBytes per second.
|
||||
</p>
|
||||
<p>When no monitors are requested and a remote longArrayMonitorMain is run:<p>
|
||||
<pre>
|
||||
mr> pwd
|
||||
/home/hg/pvDatabaseCPP-md
|
||||
mrk> bin/linux-x86_64/longArrayMonitorMain
|
||||
</pre>
|
||||
<p>The performance drops to about 90million elements per second.
|
||||
In addition the time between reports varies from just over 1 second to 3 seconds.
|
||||
I do not understand why.</p>
|
||||
|
||||
</div>
|
||||
</body>
|
||||
|
||||
Reference in New Issue
Block a user