diff options
Diffstat (limited to 'system/doc/efficiency_guide/drivers.xml')
-rw-r--r-- | system/doc/efficiency_guide/drivers.xml | 148 |
1 files changed, 148 insertions, 0 deletions
diff --git a/system/doc/efficiency_guide/drivers.xml b/system/doc/efficiency_guide/drivers.xml new file mode 100644 index 0000000000..9fe54fb19a --- /dev/null +++ b/system/doc/efficiency_guide/drivers.xml @@ -0,0 +1,148 @@ +<?xml version="1.0" encoding="latin1" ?> +<!DOCTYPE chapter SYSTEM "chapter.dtd"> + +<chapter> + <header> + <copyright> + <year>2009</year><year>2009</year> + <holder>Ericsson AB. All Rights Reserved.</holder> + </copyright> + <legalnotice> + The contents of this file are subject to the Erlang Public License, + Version 1.1, (the "License"); you may not use this file except in + compliance with the License. You should have received a copy of the + Erlang Public License along with this software. If not, it can be + retrieved online at http://www.erlang.org/. + + Software distributed under the License is distributed on an "AS IS" + basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + the License for the specific language governing rights and limitations + under the License. + + </legalnotice> + + <title>Drivers</title> + <prepared>Bjorn Gustavsson</prepared> + <docno></docno> + <date>2009-11-16</date> + <rev></rev> + <file>drivers.xml</file> + </header> + + <p>This chapter provides a (very) brief overview on how to write efficient + drivers. It is assumed that you already have a good understanding of + drivers.</p> + + <section> + <title>Drivers and concurrency</title> + + <p>The run-time system will always take a lock before running + any code in a driver.</p> + + <p>By default, that lock will be at the driver level, meaning that + if several ports has been opened to the same driver, only code for + one port at the same time can be running.</p> + + <p>A driver can be configured to instead have one lock for each port.</p> + + <p>If a driver is used in a functional way (i.e. it holds no state, + but only does some heavy calculation and returns a result), several + ports with registered names can be opened beforehand and the port to + be used can be chosen based on the scheduler ID like this:</p> + + <code type="none"> +-define(PORT_NAMES(), + {some_driver_01, some_driver_02, some_driver_03, some_driver_04, + some_driver_05, some_driver_06, some_driver_07, some_driver_08, + some_driver_09, some_driver_10, some_driver_11, some_driver_12, + some_driver_13, some_driver_14, some_driver_15, some_driver_16}). + +client_port() -> + element(erlang:system_info(scheduler_id) rem tuple_size(?PORT_NAMES()) + 1, + ?PORT_NAMES()).</code> + + <p>As long as there are no more than 16 schedulers, there will never + be any lock contention on the port lock for the driver.</p> + + </section> + + <section> + <title>Avoiding copying of binaries when calling a driver</title> + + <p>There are basically two ways to avoid copying a binary that is + sent to a driver.</p> + + <p>If the <c>Data</c> argument for + <seealso marker="erts:erlang#port_control/3">port_control/3</seealso> + is a binary, the driver will be passed a pointer to the contents of + the binary and the binary will not be copied. + If the <c>Data</c> argument is an iolist (list of binaries and lists), + all binaries in the iolist will be copied.</p> + + <p>Therefore, if you want to send both a pre-existing binary and some + additional data to a driver without copying the binary, you must call + <c>port_control/3</c> twice; once with the binary and once with the + additional data. However, that will only work if there is only one + process communicating with the port (because otherwise another process + could call the driver in-between the calls).</p> + + <p>Another way to avoid copying binaries is to implement an <c>outputv</c> + callback (instead of an <c>output</c> callback) in the driver. + If a driver has an <c>outputv</c> callback, refc binaries passed + in an iolist in the <c>Data</c> argument for + <seealso marker="erts:erlang#port_command/2">port_command/2</seealso> + will be passed as references to the driver.</p> + </section> + + <section> + <title>Returning small binaries from a driver</title> + + <p>The run-time system can represent binaries up to 64 bytes as + heap binaries. They will always be copied when sent in a messages, + but they will require less memory if they are not sent to another + process and garbage collection is cheaper.</p> + + <p>If you know that the binaries you return are always small, + you should use driver API calls that do not require a pre-allocated + binary, for instance + <seealso marker="erts:erl_driver#int driver_output-3">driver_output()</seealso> + or + <seealso marker="erts:erl_driver#int driver_output_term-3">driver_output_term()</seealso> + using the <c>ERL_DRV_BUF2BINARY</c> format, + to allow the run-time to construct a heap binary.</p> + + </section> + + <section> + <title>Returning big binaries without copying from a driver</title> + + <p>To avoid copying data when a big binary is sent or returned from + the driver to an Erlang process, the driver must first allocate the + binary and then send it to an Erlang process in some way.</p> + + <p>Use <seealso marker="erts:erl_driver#ErlDrvBinary* driver_alloc_binary-1">driver_alloc_binary()</seealso> to allocate a binary.</p> + + <p>There are several ways to send a binary created with + <c>driver_alloc_binary()</c>.</p> + + <list type="bulleted"> + <item><p>From the <c>control</c> callback, a binary can be returned provided + that + <seealso marker="erts:erl_driver#void set_port_control_flags-2">set_port_control()</seealso> + has been called with the flag value <c>PORT_CONTROL_FLAG_BINARY</c>.</p> + </item> + + <item><p>A single binary can be sent with + <seealso marker="erts:erl_driver#int driver_output_binary-6">driver_output_binary()</seealso>.</p></item> + + <item><p>Using + <seealso marker="erts:erl_driver#int driver_output_term-3">driver_output_term()</seealso> + or + <seealso marker="erts:erl_driver#int driver_send_term-4">driver_send_term()</seealso>, + a binary can be included in an Erlang term.</p> + </item> + </list> + + </section> + +</chapter> |