· Engineering  · 29 min read

Why Pay for the OPC UA Server on a Beckhoff Controller?

Every Beckhoff controller already speaks ADS. OPC UA is a licensed server on top. Measured from the controller’s own figures: reading natively by address barely registered, up to 2500 values every 10 ms. A busy OPC UA server put its work in the PLC task. Resolving names in the runtime on every read cost up to 46% of its CPU. A look at what the OPC UA license buys, and where each way of reading puts its work.

Every Beckhoff controller already speaks ADS. OPC UA is a licensed server on top. Measured from the controller’s own figures: reading natively by address barely registered, up to 2500 values every 10 ms. A busy OPC UA server put its work in the PLC task. Resolving names in the runtime on every read cost up to 46% of its CPU. A look at what the OPC UA license buys, and where each way of reading puts its work.
Every Beckhoff controller already speaks ADS. OPC UA is an extra, licensed server on top. So what does the license buy you, and what does it cost the controller? We measured it from the controller’s own figures. Reading by address over ADS barely registered, up to 2500 values every 10 ms. Once the OPC UA server was kept busy, its work landed inside the PLC task. Asked for 2500 variables every 10 ms, the OPC UA server answered 11.4 reads a second. ADS answered about 100, every read the client asked for.

1. The question

ADS is the protocol TwinCAT itself is built on. Engineering, the runtime and every Beckhoff tool talk to the controller over it. It is on every controller. It costs nothing extra.

OPC UA is something you add. Beckhoff’s server, TF6100, is a licensed TwinCAT function. Install it, license it, configure it, and any OPC UA client can browse the program’s variables by name. Standard protocol, standard security, standard tooling.

So when a project specifies OPC UA for a Beckhoff line, the question is worth asking out loud. Why pay for a second server on a controller that already has a native one?

The usual answer is interoperability. Often that answer is right. This article adds a question the license price does not show: what does each way of reading cost the controller itself?

A PLC runs its program in a fixed cycle and answers requests in the time that is left. Whatever a client asks for has to be paid for somewhere on that controller. Either inside the task that runs the machine or beside it. The interesting part is not only how much, but where the work lands and how it grows when you ask for more.

The Siemens article looked at the same kind of question from the client’s side. This one stays on the controller.

2. Before the first read

The license price is only part of what the OPC UA server costs. The rest is the effort of getting it running, and on Beckhoff hardware that effort is considerable.

On a Siemens controller, the OPC UA server is a setting in the device’s properties in TIA Portal. On our Linux-based Beckhoff controller it took four separate steps:

  1. Install it. Log in to the controller and install the server’s packages as root.

  2. Configure the server. This takes a separate configuration tool, outside the engineering environment.

  3. Configure the project. Back in TwinCAT engineering, enable the download of the symbol file in the PLC project’s properties. Then mark the variables the server should publish with an attribute in the PLC code. Anything unmarked stays invisible to OPC UA.

  4. License it. Generate a license request using the TAN Beckhoff sends on purchase. Email the request to an automated address. Receive a license file back, then install it manually in the engineering environment.

None of these steps is hard once you know it. Together they are a procedure someone has to document, and repeat on every controller.

ADS needs none of them. It is already running.

2.1. And after every change

The same difference shows up again when the program changes. Partway through this benchmark we added 2500 new variables to the running project and downloaded it to the CX9240.

Over ADS, the new variables were readable right after the download. No restart, no configuration. Our driver’s default mode, on-demand, keeps an address only until TwinCAT reports a program change, then looks the name up again.

Over OPC UA, they first had to be marked for publication in the PLC code. Even then, a browse of the server right after the download showed none of them, while the PLC was already running the new program. They appeared only after we restarted the controller. Beckhoff’s documentation describes the server reading the symbol file when TwinCAT starts. We did not find a setting that makes it reload after a download, though one may exist. We saw this once, on one controller with one TF6100 version.

Some integrators will call the first half of that a feature. With OPC UA, every published variable is a deliberate decision in the PLC project, and nothing leaves the controller by accident. With ADS, the PLC programmer does not have to think about the client at all. A variable can still be kept out of reach by marking it {attribute 'TcNoSymbol'}. OPC UA publishes nothing unless told to. ADS publishes everything unless told not to. Either can be what you want. What it costs is maintenance: with OPC UA, every new value a client needs is a change to the PLC project, and possibly a restart.

3. How I measured it

A client reads N integers from a TwinCAT 3 controller. N is 80, 500 or 2500. It either polls at a held rate (every 2 s, 500 ms, 200 ms, 50 ms, 20 ms or 10 ms) or subscribes to the values.

The values come in two shapes: elements of one array, and separately 2500 distinct variables. The array is never read as a whole. Each value is its own item in the read, addressing one element, so 2500 values are 2500 items either way. The difference turns out to matter a great deal for OPC UA.

While it does, I read the controller’s own figures beside the workload:

  • The PLC task’s execution time. The task runs every 10 ms. This is how long each cycle of it takes. The machine’s program lives here.

  • TwinCAT’s CPU usage for work outside the task. Communication, symbol lookups, the OPC UA server’s own processing: anything the runtime does beside the program.

Every rate is held for 10 s and compared against an idle baseline. Every measurement runs three passes, in rotated order. A positive control proves the figures can move at all before a flat row is read as "no cost". Without it, a quiet row could simply mean the probe was not looking.

Two controllers:

  • a CX9240, TwinCAT 3.1.2127, with the OPC UA server TF6100

  • a C6920, TwinCAT 3.1.1926, ADS only on this bench

So every OPC UA figure below comes from the CX9240. The C6920 shows how the ADS results change on a different machine.

4. Six ways to read a symbol over ADS

An ADS client names a variable by its symbol. The runtime serves memory by address. Every client has to turn one into the other somewhere. Where it does that turns out to matter a great deal.

The driver measured here can do it six ways (symbol-resolution=…​). Together they cover how ADS clients in general work. on-demand is our driver’s default. Other drivers might default to other modes:

Table 1. The six symbol-resolution modes.
ModeWhat happens on the wire

on-demand (ToddySoft default)

a symbol’s address is looked up the first time it is read and kept until TwinCAT reports a program change; reads go by address

table

the runtime’s whole symbol and type tables are fetched when connecting; reads go by address

per-request

the address is looked up again for every read, then read by address

by-name

the runtime is asked to read by symbol name, and resolves the name itself on every read

handle-on-demand

a handle is requested per symbol on first use and read through until the program changes

handle-per-request

for every read: request a handle, read through it, release it — what pyads’ `read_by_name does

Beside them I measured on-demand over Secure ADS, both with a pre-shared key and with certificates. On the OPC UA side, three security levels: None, Sign, and Sign and encrypt (Basic256Sha256). None of them made a measurable difference to the load on the controller. Secure ADS measured the same as plain ADS, and the three OPC UA levels measured the same as each other. For OPC UA that held on the client too: every security level read at the same rate.

5. Polling

5.1. ADS: reading by address costs next to nothing

on-demand, table and per-request all end in a read by address. They kept the PLC task at its idle 2 µs up to one read every 200 ms, and within about 3 µs of it at the fastest rates. TwinCAT’s CPU figure stayed at its idle level throughout.

The heaviest case on the bench counts too: 2500 values every 10 ms. With on-demand, the CX9240 achieved 98.9 reads a second there, at 8 ms per read.

These figures cover reading, not connecting. table does its work up front: it fetches the whole symbol and type tables every time it connects. On a large installation those tables can run to several hundred kilobytes. At one of our beta testers they were more than a megabyte. on-demand fetches only the symbols a client actually reads.

5.2. ADS: resolving names in the runtime costs its CPU

The other three make the runtime do more than find an address: read every value by name, or issue a handle for it and read through that. At 2500 values and 20 ms or faster, that shows up clearly:

Table 2. TwinCAT CPU usage outside the PLC task. 2500 values, polled every 20 ms or faster.
ModeCX9240C6920

by-name

45–46%

18–19%

handle-per-request

36%

10–11%

handle-on-demand

9% (idle 5%)

about 1%

address-based modes

idle (4–7%)

idle (0%)

Same protocol. Same controller. Same values. Between the first and last rows, the only difference is how much work the runtime does for each value.

The two controllers put that work in different places. On the CX9240 the PLC task’s execution time rises with it, to 9–11 µs. On the C6920 the task stays at 2.4 µs, and the work lands outside it entirely.

handle-per-request deserves a second look. Request a handle, read, release it: a common Python library does exactly that in its read_by_name call. On the CX9240, at this rate and size, it kept 36% of TwinCAT’s CPU busy.

5.3. OPC UA: the task pays while the server is busy

OPC UA behaves differently from every ADS mode. Its cost shows up in the PLC task itself.

At slow rates the task does not notice it. Once reads keep the server busy most of the time, the task’s median execution time rises to about 15–19 µs, against 2 µs idle.

When that happens depends on how long a read takes, and so on what is read. For 2500 separate variables, from one read every 50 ms. For 2500 elements of one array, already from one read every 500 ms.

5.4. ADS and OPC UA side by side

Same controller, the CX9240. ADS in its default mode against the OPC UA server, first for what polling costs the controller:

Table 3. What polling costs the controller. CX9240, PLC task idle about 2 µs.
ADS, on-demandOPC UA

Slow rates

idle

idle

Fast rates, server kept busy

2–4.5 µs

about 15–19 µs

Where the work lands

barely anywhere

in the PLC task

Security

Secure ADS (TLS, signed and encrypted): no difference

OPC UA Sign, Sign and encrypt: no difference

Then for what it delivers. Asked for a read every 10 ms:

Table 4. Reads per second achieved when asked for one every 10 ms, and the median time per read. CX9240, any OPC UA security level.
ValuesADS, on-demandOPC UA, separate variablesOPC UA, array elements, one item each

80

99.7/s, 2.2 ms

99.7/s, 5.1 ms

34/s, 29 ms

500

99.7/s, 3.4 ms

52/s, 19 ms

5.6/s, 175 ms

2500

99.2/s, 6.7 ms

11.4/s, 85 ms

1.1/s, 893 ms

The ADS figures are for separate variables. Over the array, ADS kept the same rate, at 8 ms per read of 2500.

ADS by address answers about 100 reads a second at every size. The test asked for exactly that many, so the figure is a limit of the test, not of ADS. A read took 2.2 ms to 6.7 ms, so the controller spent most of each 10 ms interval waiting for the next request.

The client sends one read at a time and waits for the answer. When a read takes longer than 10 ms, the next one starts as soon as it returns, so nothing is dropped or queued. Where the OPC UA figures fall short of 100, the server was answering back to back. They are real limits of the server.

For OPC UA, how the values are stored matters as much as the protocol. The same server answered 2500 separate variables about ten times as fast as 2500 array elements, each addressed on its own. Our first run read only the array, and showed ADS about 65 times ahead at 2500 values. Most of that gap came from the array, not from OPC UA as such.

Most systems on a shopfloor poll: historians, dashboards, SCADA. For them the fair comparison is the separate-variable column, and ADS still keeps a clear lead. At 80 values both kept up with a read every 10 ms. At 500 values ADS was about five times as fast. At 2500 it read the values in 6.7 ms, where the OPC UA server needed 85 ms, about thirteen times as long.

6. Subscriptions

Subscribing moves the work into the controller. The client stops asking. The controller has to watch the values and report them.

The table below mixes two kinds of subscription. All rows but one are cyclic: the client names an interval, and the controller works on the values at that interval. What it does then differs by protocol:

  • ADS sends every value, every interval, whether it changed or not.

  • OPC UA samples every value at the interval, then sends only the ones that changed.

One row is on change: no interval at all, the controller reports a value only when it changes.

The first run used values that never change, elements of one array. That measures what it costs the controller to sample and watch, but not to deliver. A second run, further down, changes the values.

On the CX9240, both protocols reach the PLC task, in different ways.

Table 5. PLC task median execution time while subscribed. CX9240, idle about 2 µs, values not changing, elements of one array.
ValuesSubscriptionADS, on-demandOPC UA

80

cyclic, 200 ms

2.4 µs

2.2 µs

80

cyclic, 20 ms

2.8 µs

9.2 µs

80

cyclic, 10 ms

2.9 µs

12 µs

500

cyclic, 200 ms

3.4 µs

2.3 µs

500

cyclic, 50 ms

3.5 µs

8.6 µs

500

cyclic, 10 ms

4.8 µs

9.4 µs

2500

on change

6.1 µs

2.2 µs

2500

cyclic, 500 ms

5.4 µs

7.5 µs

2500

cyclic, 10 ms

11 µs

8.9 µs

The two grow along different curves.

ADS grows with the number of values and how often it sends them. More values, faster, costs more. Gradually.

OPC UA behaves like a step. Sampling slowly costs nothing measurable. Sampling fast costs about 9 µs, almost regardless of size.

So a small, fast OPC UA subscription costs the task about three times what ADS does. At 2500 values every 10 ms the two look about equal. Keep in mind that the OPC UA server had nothing to send here, while ADS sent every value at every interval.

Over 2500 separate variables the picture moves towards ADS. ADS costs the same as over the array, 11.8 µs at 10 ms. Fast OPC UA sampling costs more, about 17 µs instead of 9. There, ADS subscriptions cost the task about 5 µs less than OPC UA.

Secure ADS costs the same as plain ADS here too.

On the C6920, ADS subscriptions leave the PLC task flat. Only the CPU figure moves, to 1–2%.

6.1. When the values change

For the second run, every one of 2500 variables changes once a second:

Table 6. PLC task median execution time, and values delivered per variable and second. CX9240, 2500 variables each changing once a second, idle 3.1 µs with the changing program running.
SubscriptionTask, ADSDelivered, ADSTask, OPC UADelivered, OPC UA

on change

11.5 µs

every change (1/s)

3.2 µs

about 95% of the changes

cyclic, 2 s

7.6 µs

0.5/s

3.1 µs

0.5/s

cyclic, 10 ms

13 µs

100/s

19 µs

the changes (1/s)

For ADS, delivering changes costs more than watching for them. 2500 variables changing once a second cost the task 11.5 µs, against 6 µs for watching the same 2500 while nothing changed.

The "cyclic" rows are not like for like, because the two protocols do different things with an interval. ADS delivers every value at that interval. The OPC UA server, here and on the two Siemens controllers we tried, reported only changes, sampled at the interval. The fair comparison is therefore ADS on change against OPC UA at a rate:

  • To see changes promptly, OPC UA has to sample fast. At 10 ms it cost the task 19 µs. ADS on change delivered every change for 11.5 µs.

  • If a change can wait, OPC UA sampling every 2 s cost only 3.1 µs, the cheapest row in the table. A change could then take up to two seconds to arrive.

The OPC UA on-change row saw about 95% of the changes because our client sampled it only once a second. It will be re-measured once that is fixed.

7. What it costs the network

So far every figure was about the controller. The same reads also cross the network, and there the protocol and the client’s habits show up in bytes.

Two separate runs measured this, both on the CX9240, counting every byte of request and answer.

The first reads the same 56 values of mixed types over both protocols:

Table 7. Bytes on the wire for one read of the same 56 values. CX9240.
How you readBytes per read

ADS

623 B

Secure ADS, pre-shared key

762 B

Secure ADS, certificates

730 B

OPC UA, None

2,880 B

OPC UA, Sign

2,944 B

OPC UA, Sign and encrypt

2,960 B

OPC UA moves about four and a half times the bytes ADS does for the same values. Security adds little to either: about a fifth to ADS, a few percent to OPC UA.

The second reads 3000 integers of one array over ADS, in each of the ways a client can ask:

Table 8. Bytes on the wire for one read of 3000 integers over ADS. CX9240.
How the client asksBytes per readPer value

on-demand, neighboring values combined into one read (our driver’s default)

6.1 KB

2.0 B

on-demand, one item per value

54.6 KB

18.2 B

handle-on-demand

62.1 KB

20.7 B

by-name

143.5 KB

47.8 B

handle-per-request

265.1 KB

88.4 B

An integer is two bytes. So the first row moves the data and almost nothing else. The client sees that the values sit next to each other and asks for the whole span at once. Every other row pays a header per value, and the name-based modes also send the name, or a handle, for every value on every read.

At the rates in this article that adds up. 2500 values every 10 ms come to about 0.5 MB a second read the first way, and about 4.5 MB a second with one item per value. Those totals are our arithmetic from the bytes per read, not a separate measurement.

We did not measure OPC UA’s bytes at those sizes. At 56 values it was already the heaviest row.

8. So is the OPC UA server worth it?

A disclosure first. I work on ToddySoft Connect. It provides both drivers measured here, the ADS one and the OPC UA one, and every number came out of its test suite. The OPC UA server on the controller is Beckhoff’s own. You should know that before you weigh my conclusions.

With that said, here is what the figures support.

If you need high-frequency data, the license buys you less of it. Polled every 10 ms, ADS delivered every read we asked for, at every size we tried. The OPC UA server kept up at 80 values. At 500 separate variables it managed 52 reads a second, at 2500 about 11. If your data needs to be fresh every few tens of milliseconds, that settles the question before the license price comes up.

If you poll, the native protocol is the one the controller barely notices. ADS by address kept the PLC task within about 3 µs of idle at every size and rate we tried. OPC UA left the task alone at slow rates. Once its server was kept busy, the task paid 15–19 µs, against 2–4.5 µs for ADS at the same rate.

Skipping the license only helps if the ADS client reads well. Resolve once and read by address, and the controller stays idle. Ask the runtime to resolve on every read, and the same data can take a third of TwinCAT’s CPU or more.

The mode you get is usually an implementation detail of your driver. The ToddySoft driver supports all six. Its default, on-demand, resolves each name once and then reads by address, which puts it in the rows that left the controller idle. If you are writing your own client, or choosing a library, find out which of the six it uses.

Subscriptions are closer. Neither protocol wins everywhere. Small and fast favors ADS by about three times in the task. Over 2500 separate variables, ADS is still about 5 µs cheaper. With changing values, ADS on change delivered every change for less than OPC UA needed to sample fast. OPC UA is cheapest where a change is allowed to wait: sampling every 2 s cost the task almost nothing.

The license is not the whole bill. The setup is paid again on every controller: installed as root, configured in two places, licensed by email. Every new variable is then a change to the PLC code, and on our controller a restart. ADS is there from the start and picked up new variables as soon as they were downloaded.

ADS is also the lighter load on the network. For the same 56 values, ADS moved 623 bytes per read and OPC UA 2,880, about four and a half times the network volume.

Security is not a reason to buy it. Secure ADS measured the same as plain ADS, with a pre-shared key and with certificates. The three OPC UA security levels measured the same as each other.

So the license buys neither speed nor a lighter load on the controller. What it buys is real all the same. Every other system on the floor can read OPC UA without knowing anything about Beckhoff. It brings an information model and security an auditor recognizes. Its cost in the task is measured in microseconds. If a system you cannot change only speaks OPC UA, that alone settles it.

If the client is yours, the choice is open. The Siemens article makes the longer case for putting the unified API in your application and letting each device speak what it speaks best. On a Beckhoff controller, what it speaks best is ADS.

The figures say the two ways in put their work in different places. A busy OPC UA server puts part of it in the task that runs your machine. ADS by address puts almost none anywhere. On a busy controller, weigh that before you weigh the license.

9. What to keep in mind

  • Two controllers, one of each. No figure here is a statement about TwinCAT in general. The two controllers already differ in where the work lands. On the CX9240, name resolution and ADS subscriptions both nudge the PLC task. On the C6920, neither does.

  • For OPC UA, how the values are stored matters. The same server answered 2500 separate variables about ten times as fast as 2500 array elements, each addressed on its own. Use the figure that matches how your project stores its values.

  • The network figures come from separate runs. The ADS-against-OPC UA comparison reads 56 values of mixed types, not the 80, 500 or 2500 of the load runs, and OPC UA’s bytes were not measured at those sizes. The megabytes per second are our arithmetic from bytes per read, not a measurement of the network.

  • "Cyclic" does not mean the same on both sides. ADS cyclic subscriptions deliver every value at every interval. The OPC UA servers we tried delivered changes only, sampled at the interval.

  • Microseconds are small. The task’s cycle is 10 000 µs. The largest cost above, 19 µs, is under 0.2% of it. What these figures show is where a protocol’s work lands and how it scales, not that either one will stretch a 10 ms cycle on its own.

10. The point

The license is the cost you see. The other one lands on the controller.

Read natively by address, and the controller hardly knows you are there. Make the runtime resolve names on every read, and one of our two controllers spent up to 46% of its CPU doing it. Keep the OPC UA server busy, and the task that runs the machine pays for it.

None of those costs is large on its own. They are the kind that add up one dashboard at a time. So before you buy a second server for a controller that already has one, find out what the first one can do.

Back to Blog

Related Posts

View All Posts »
Five Doors Into One Siemens Controller: What Each One Costs You

Five Doors Into One Siemens Controller: What Each One Costs You

How you ask a Siemens PLC for data matters more than which protocol you use. Reading the same hundred values off the same controller, a client that groups its requests is a hundred times faster on Modbus and five to fifteen times faster on S7Comm. That is larger than any difference between the protocols themselves. A measured look at what protocol and driver choice costs a PLC, a network and your budget.

Live chat is disabled. Cookie consent is required to use this feature. If you don't see a consent banner, an ad-blocker or privacy extension may be preventing it from appearing. Live-Chat ist deaktiviert. Cookie-Zustimmung ist erforderlich, um diese Funktion zu nutzen. Falls Sie kein Zustimmungsbanner sehen, verhindert möglicherweise ein Werbeblocker oder eine Datenschutz-Erweiterung dessen Anzeige.