· Engineering  · 44 min read

Ten PLC Protocols, Seven Vendors: How You Ask Beats What You Use

You cannot rank PLC protocols against each other: they run on different controllers, and the controller changes every number. What you can compare is a job. Ten protocols, seven vendors, the same values at the same rates: bytes on the wire, time per read and what each job costs the controller. How the client asked decided the cost more often than the protocol did.

You cannot rank PLC protocols against each other: they run on different controllers, and the controller changes every number. What you can compare is a job. Ten protocols, seven vendors, the same values at the same rates: bytes on the wire, time per read and what each job costs the controller. How the client asked decided the cost more often than the protocol did.
You cannot rank PLC protocols against each other. They run on different controllers, and the controller changes every number. What you can compare is a job: the same values, read at the same rate, on whatever the controller speaks. Across ten protocols and seven vendors, one thing decided the cost of that job more often than the protocol did: how the client asked.

1. A job, not a ranking

The Siemens article and the Beckhoff article each stayed inside one vendor, which kept them fair. Every row shared a controller, so a difference between rows was a difference between protocols.

This article crosses that line on purpose. Doing so takes care. An S7-1212C and a CompactLogix are different machines. Put an S7Comm figure from one next to a CIP figure from the other and you are comparing two computers, not two protocols.

But nobody picks a protocol in the abstract. A plant engineer has a controller that is already installed and a job to do: get these 2500 values into the historian twice a second. What that job costs on the controller in front of them is a fair question. For them it is the one that matters.

So this article compares three things, each in the way the data allows:

  • Bytes on the wire. For a binary protocol these depend on the protocol and on how the client asks, but not on the controller at all. They are the one figure that compares freely across vendors.

  • The time a read takes. That depends on the protocol, the controller and the client together. The article shows it per controller, for the same job, and every row names how the client asked.

  • What the job costs the controller. Every vendor measures that differently, so each controller reports it in its own terms, next to the others.

2. What was measured

Two kinds of run, both reading only.

A byte sweep. Nine tags that every protocol on the bench can express: whole scalars and whole arrays of BOOL, INT, DINT, REAL and STRING. Each target read every tag in its own request, then all nine together in one request, a hundred times. Bytes were counted inside the driver, at the transport, including the protocol’s envelope. Nine drivers took part, on eleven controllers.

Load runs. The same ladder on five of the seven vendors, Siemens, Beckhoff, Schneider Electric, Rockwell and Mitsubishi: 80, 500 or 2500 integers, read at a held rate from once every 2 s to every 10 ms, for 10 s each against an idle baseline, three passes in rotated order, with the drivers exactly as they ship. A positive control proved each controller’s figures could move before a quiet row was read as "no cost".

Table 1. The controllers.
ControllerVendorProtocols

S7-1212C, S7-1212C G2, S7-1511, S7-1516; S7-315 (byte sweep only)

Siemens

S7Comm, S7CommPlus, OPC UA, Modbus TCP, S7 Web API (as each CPU offers them)

CX9240, C6920 (TwinCAT 3); CX1010 (TwinCAT 2)

Beckhoff

ADS, Secure ADS, OPC UA (CX9240 only)

Modicon M580

Schneider Electric

UMAS, Modbus TCP

CompactLogix 5370

Rockwell Automation

EtherNet/IP (CIP)

MELSEC-Q Q03UDECPU

Mitsubishi Electric

MC protocol (3E binary), load and network only

ctrlX CORE X3

Bosch Rexroth

ctrlX Data Layer (REST over HTTPS), byte sweep only

PFC200 G2 (750-8212)

WAGO

OPC UA (CODESYS server), byte sweep only

One of each, apart from the Siemens CPUs. No figure here is a statement about a product family.

3. On the wire

Bytes are the one column that travels. Modbus TCP ran on four different Siemens CPUs in the sweep, with the same register map, and every byte figure came out identical on all four, while the time for the same work differed 3.3-fold. Two sweeps twelve days apart, with several driver releases in between, reproduced the bytes of S7Comm, Modbus TCP, OPC UA, UMAS and CIP exactly.

So a byte figure is a property of the protocol and of how the client asks. The controller that answered makes no difference.

Table 2. Bytes per request on the wire, nine values of the five types every protocol here can read. Where a protocol ran on several controllers, the range covers all of them.
Protocol, and how the client asksOne valueAll ninePer valueExchanges per read

UMAS

43.3 B

133.5 B

14.8

1

S7Comm, batched

68.0 B

168.5–191.5 B

18.7–21.3

1

Modbus TCP, batched

34.0 B

173.5 B

19.3

3.4

Modbus TCP

34.0 B

204.0 B

22.7

5.7

S7Comm

68.0 B

209.4 B

23.3

1

ADS, batched

268.8–297.3 B

236.5–256.0 B

26.3–28.4

1

  └ Secure ADS 🔒, certificates

501.4 B

362.0 B

40.2

1

  └ Secure ADS 🔒, pre-shared key

550.3 B

394.0 B

43.8

1

S7CommPlus, batched 🔒*

183.8–199.8 B

299.7–315.8 B

33.3–35.1

1

S7CommPlus 🔒*

177.0–193.0 B

429.7–453.8 B

47.7–50.4

1.5

OPC UA (SIMATIC)

187.8–188.2 B

439.0–441.0 B

48.8–49.0

1

  └ Sign and encrypt 🔒

269.3 B

520.0–528.0 B

57.8–58.7

1

CIP, batched

145.8 B

453.0 B

50.3

1

OPC UA (WAGO, CODESYS)

233.8 B

715.0 B

79.4

1

ctrlX Data Layer 🔒

604.8 B

1,259.8 B

140.0

1

S7 Web API 🔒

1,725.4–1,897.3 B

4,054.3–4,212.2 B

450.5–468.0

—

0100200300400500UMAS14.8S7Comm, batched18.7–21.3Modbus TCP, batched19.3Modbus TCP22.7S7Comm23.3ADS, batched26.3–28.4S7CommPlus, batched 🔒*33.3–35.1Secure ADS 🔒, certificates40.2Secure ADS 🔒, pre-shared key43.8S7CommPlus 🔒*47.7–50.4OPC UA (SIMATIC)48.8–49.0CIP, batched50.3OPC UA, Sign and encrypt 🔒 (SIMATIC)57.8–58.7OPC UA (WAGO, CODESYS)79.4ctrlX Data Layer 🔒140.0S7 Web API 🔒450.5–468.0bytes per value
Bytes per value on the wire, nine values per request. Longer is heavier.

🔒 marks the ways in that were measured with the channel encrypted and the client authenticated: Secure ADS, OPC UA with Sign and encrypt, S7CommPlus and the two interfaces over HTTPS. Everything else ran in the clear. In the tables, indented rows are the unindented row above them with security added.

*S7CommPlus comes in several versions. The older ones can run without any protection. Only the newest is fully secured, with the client authenticated and the channel encrypted. Our driver implements only that version, so every S7CommPlus figure in this article was measured with full security.

Five things stand out.

The spread is thirtyfold. The cheapest protocol moves under 15 bytes per value, the dearest over 450. Everything binary sits between 15 and 60. The two protocols built on HTTPS and JSON are in a different class.

How the client asks shows up here too. Modbus cannot name nine scattered values in one request. Asked plainly it needs 5.7 exchanges per read. Batched by the client it needs 3.4. UMAS, carried over Modbus TCP, names all nine and fetches them in one, and comes out 35% cheaper per value than plain Modbus. Batched S7CommPlus reads the same nine values about 30% lighter than plain. The effect grows with the read, as the next table shows.

Modern is not lighter, unless the client makes it so. On the same Siemens CPUs, plain S7CommPlus moves roughly twice the bytes per value of classic S7Comm. OPC UA and CIP land in the same band. What they buy is symbolic names, types and, for most of them, security. A lighter wire is not among them. Batched S7CommPlus is the exception: on large contiguous reads it costs what classic S7Comm does (see Large reads below).

OPC UA servers differ, too. The same nine values cost 49 bytes each from the SIMATIC servers and 79 from the WAGO’s CODESYS server. The protocol is the same; the server decides how much it sends.

Security costs bytes, not many. Secure ADS adds 12 to 17 bytes per value over ADS without it, OPC UA’s Sign and encrypt about 9 to 10. What grows is the fixed part of each request.

Three caveats travel with the table. The ctrlX figures count the application’s bytes only. Measured separately at the network, HTTP headers and TLS add about 680 bytes per request, which puts its nine values near 1,940 bytes. ADS resolves each name on its first read, so its single-value request carries that lookup and comes out heavier than the nine-value one. And "per value" is only comparable at a stated count. Divide by nine and the fixed envelope of each request is still in the figure. At larger reads the cheap binary protocols drop much further per value than the table shows.

3.1. Large reads

The table above reads nine scattered values. The jobs below read up to 2500 neighbors. A capture beside the load runs measured exactly those reads on the wire, at 80, 500 and 2500 values. These figures are whole Ethernet frames in both directions, acknowledgements included, so they run slightly higher than the driver’s own count above.

Table 3. Bytes on the wire per value, both directions. Where a way of asking ran on several controllers, the range covers all of them. 🔒 encrypted and authenticated.
Protocol, and how the client asks80 values500 values2500 values

ADS, batched

5.7

2.6

2.2

  └ Secure ADS 🔒

7.0–7.4

2.8–2.9

2.3

MC protocol, batched

4.4

2.4

2.3

S7CommPlus, batched 🔒*

6.3–6.5

3.0

2.4

CIP, range read

5.6

2.6

2.4

S7Comm, batched

4.7

2.9–4.3

2.5–4.1

Modbus TCP, batched

4.3–4.4

3.5

3.5

UMAS

11.3

10.5

10.4

ADS, handles kept

21.7

19.7–19.8

19.6–19.8

S7Comm

23.1–31.5

20.8–29.0

20.6–28.7

S7CommPlus 🔒*

39.5–40.7

38.8–39.9

38.8–39.9

OPC UA, separate variables

44.9–50.7

42.6–46.6

42.0

ADS, by name

43.2–52.1

42.4–52.2

42.9–52.1

CIP, batched

40.8–52.1

47.3–52.4

49.1–53.7

OPC UA, array elements

52.3–57.5

50.4–55.1

51.3–55.6

ADS

93.4–103.1

86.8–97.6

86.9–96.1

S7 Web API 🔒

154.2–154.5

—

—

Modbus TCP

185.0–187.4

185.0–187.7

—

MC protocol

196.0

196.0

196.0

CIP

274.9

275.3

—

Two groups, about twenty times apart. Ways of asking that read a byte range carry the value and little else: 2.2 to 4.1 bytes per value at 2500. Ways that name every value carry the name, the address or the handle too, and land between about 20 and 56. UMAS sits between the two at about 10. Plain ADS, a handle per value, lands near 90. One request per value adds the frames on top and lands at 185 to 275.

Batching moved S7CommPlus from one group to the other. Plain, it carries about 40 bytes per value. Batched, 2.4, the same as classic S7Comm. The protocol did not change. The client did.

The network is never the limit. The heaviest case, batched ADS reading 2500 values back to back on the CX9240, moves under 7 Mbit/s. Every controller here has at least a 100 Mbit/s port.

4. The same job on every controller

Now the two questions that depend on the controller: how long does a read take, and what does it cost the machine? Two jobs, each run on every controller that offers a way to do it.

First, what "cost" means on each family, because no two measure it the same way:

  • Siemens S7: the share of the scan cycle spent on communication. A CPU reserves a slice of its cycle for it, 20% by default on an S7-1200. A job that reaches that limit stops growing the cycle and starts waiting. Marked at the limit below.

  • Beckhoff TwinCAT: the PLC task runs every 10 ms. Shown is how much its execution time grew at the 95th percentile, plus TwinCAT’s CPU usage for work outside the task.

  • Schneider M580: the MAST task’s mean execution time, idle 2.6 µs, measured by the program itself.

  • Rockwell CompactLogix: communication runs in a time slice taken from the continuous task. Shown is the share of that task’s scans a job takes away.

  • Mitsubishi MELSEC-Q: client requests are served at the end of every scan, within a share of scan time set by Service Processing. Shown is how much the mean scan changed. The Q03UDE was measured at its factory 10% and at 50%, so it appears twice.

Rows with the protocol’s plain name show what the protocol does on its own, which is what an ordinary client sends. Plain Modbus TCP, MC protocol and CIP send one request per value. Plain S7Comm sends one item per value, several items to a request, and plain S7CommPlus names every value as an item of its own. Plain ADS takes a handle for every value and releases it after the read, Beckhoff’s documented basic pattern. Plain UMAS names every variable.

Every other row is ToddySoft Connect’s addition to the same protocol. Batched combines neighboring values into range requests: S7Comm, Modbus TCP, the MC protocol, ADS by address, and S7CommPlus where the data block has standard (non-optimized) access. CIP, range read reads the array as one range; CIP, batched packs element reads into shared messages. ADS, by name lets the runtime resolve every name on every read. UMAS, by address reads located variables by their address.

A read that takes longer than the interval cannot keep up. The client sends one read at a time, so that job simply runs slower than asked. The Keeps up column says which.

4.1. 80 values, twenty times a second

A screen or a dashboard: 80 values every 50 ms.

Table 4. 80 values every 50 ms. Time is the median per read. Siemens OPC UA reads separate variables where the CPU has room for them; on the S7-1212C only array elements fit. 🔒 encrypted and authenticated.
ControllerHowPer readKeeps upCost to the controller

S7-1212C

Modbus TCP, batched

7.2 ms

yes

9% of the cycle

S7-1212C

S7Comm, batched

12 ms

yes

7% of the cycle

S7-1212C

S7CommPlus, batched 🔒*

29 ms

yes

14% of the cycle

S7-1212C

S7Comm

182 ms

no

at the limit

S7-1212C

S7CommPlus 🔒*

240 ms

no

at the limit

S7-1212C

OPC UA (array elements)

730 ms

no

at the limit

S7-1212C

Modbus TCP

1.0 s

no

at the limit

S7-1212C G2

Modbus TCP, batched

3.5 ms

yes

0%

S7-1212C G2

S7Comm, batched

4.0 ms

yes

0%

S7-1212C G2

S7CommPlus, batched 🔒*

5.8 ms

yes

0%

S7-1212C G2

S7Comm

12 ms

yes

0%

S7-1212C G2

S7CommPlus 🔒*

20 ms

yes

1%

S7-1212C G2

OPC UA

26 ms

yes

1%

S7-1212C G2

S7 Web API 🔒

155 ms

no

2%

S7-1212C G2

Modbus TCP

258 ms

no

0%

S7-1511

Modbus TCP, batched

4.2 ms

yes

1%

S7-1511

S7Comm, batched

4.3 ms

yes

0%

S7-1511

S7CommPlus, batched 🔒*

7.9 ms

yes

0%

S7-1511

S7Comm

30 ms

yes

1%

S7-1511

S7CommPlus 🔒*

57 ms

no

0%

S7-1511

Modbus TCP

357 ms

no

13% of the cycle

S7-1511

S7 Web API 🔒

378 ms

no

1%

S7-1511

OPC UA

460 ms

no

0%

S7-1516

S7Comm, batched

3.2 ms

yes

0%

S7-1516

Modbus TCP, batched

4.5 ms

yes

0%

S7-1516

S7Comm

8.8 ms

yes

0%

S7-1516

Modbus TCP

418 ms

no

1% (one pass)

CX9240

ADS, batched

3.0 ms

yes

task +1.8 µs, CPU 4%

CX9240

ADS, by name

4.5 ms

yes

not stable

CX9240

OPC UA, separate variables

5.8 ms

yes

not stable

CX9240

ADS

11 ms

yes

not stable

CX9240

OPC UA, array elements

29 ms

yes

not stable

C6920

ADS, batched

3.3 ms

yes

task +0.1 µs, CPU 0%

C6920

ADS, by name

3.5 ms

yes

task +0.1 µs, CPU 0%

C6920

ADS

8.2 ms

yes

task +0.2 µs, CPU 1%

CX1010

ADS, batched

2.3 ms

yes

not stable

CX1010

ADS, by name

7.2 ms

yes

not stable

CX1010

ADS

12 ms

yes

not stable

M580

UMAS, by address

9.9 ms

yes

MAST +0.1 µs

M580

Modbus TCP, batched

9.9 ms

yes

MAST +0.1 µs

M580

UMAS

10 ms

yes

MAST +0.1 µs

M580

Modbus TCP

800 ms

no

MAST +0.2 µs

CompactLogix

CIP, range read

6.7 ms

yes

1% of scans

CompactLogix

CIP, batched

43 ms

no

9% of scans

CompactLogix

CIP

684 ms

no

5% of scans

Q03UDE, 10%

MC protocol, batched

7.9 ms

yes

scan unaffected

Q03UDE, 10%

MC protocol

773 ms

no

scan unaffected

Q03UDE, 50%

MC protocol, batched

3.1 ms

yes

scan +27 µs (2%)

Q03UDE, 50%

MC protocol

270 ms

no

not stable

4.2. 2500 values, twice a second

A historian or a SCADA poll set: 2500 values every 500 ms.

Table 5. 2500 values every 500 ms. Time is the median per read. The S7-1511 reads 2500 OPC UA values only as array elements, in three requests. 🔒 encrypted and authenticated.
ControllerHowPer readKeeps upCost to the controller

S7-1212C

S7CommPlus, batched 🔒*

152 ms

yes

5% of the cycle

S7-1212C

S7Comm, batched

401 ms

yes

16% of the cycle

S7-1212C

S7Comm

5.4 s

no

at the limit

S7-1212C

S7CommPlus 🔒*

7.8 s

no

at the limit

S7-1212C

OPC UA

—

no

serves 1000 values at most

S7-1212C

Modbus TCP, batched

—

no

beyond what it serves

S7-1212C

Modbus TCP

—

no

beyond what it serves

S7-1212C G2

S7Comm, batched

35 ms

yes

0%

S7-1212C G2

S7CommPlus, batched 🔒*

37 ms

yes

0%

S7-1212C G2

Modbus TCP, batched

76 ms

yes

0%

S7-1212C G2

S7Comm

241 ms

yes

0%

S7-1212C G2

S7CommPlus 🔒*

980 ms

no

1%

S7-1212C G2

OPC UA

—

no

serves 1000 values at most

S7-1212C G2

Modbus TCP

—

no

refused by the controller

S7-1511

S7Comm, batched

47 ms

yes

0%

S7-1511

S7CommPlus, batched 🔒*

57 ms

yes

0%

S7-1511

Modbus TCP, batched

106 ms

yes

3% of the cycle

S7-1511

S7Comm

855 ms

no

1%

S7-1511

S7CommPlus 🔒*

2.2 s

no

0%

S7-1511

OPC UA (array elements)

32.5 s

no

0%

S7-1511

Modbus TCP

—

no

refused by the controller

S7-1516

S7Comm, batched

35 ms

yes

0%

S7-1516

Modbus TCP, batched

115 ms

yes

0%

S7-1516

S7Comm

203 ms

yes

1%

S7-1516

Modbus TCP

—

no

refused by the controller

CX9240

ADS, batched

20 ms

yes

task +0.4 µs, CPU 5%

CX9240

ADS, by name

67 ms

yes

not stable

CX9240

OPC UA, separate variables

92 ms

yes

not stable

CX9240

ADS

112 ms

yes

task +12 µs, CPU 10%

CX9240

OPC UA, array elements

894 ms

no

not stable

C6920

ADS, batched

18 ms

yes

task +0.1 µs, CPU 0%

C6920

ADS, by name

37 ms

yes

task +0.2 µs, CPU 1%

C6920

ADS

62 ms

yes

not stable

CX1010

ADS, batched

17 ms

yes

not stable

CX1010

ADS, by name

170 ms

yes

task +0.8 µs, CPU 1%

CX1010

ADS

336 ms

yes

not stable

M580

UMAS, by address

193 ms

yes

MAST +0.1 µs

M580

UMAS

196 ms

yes

MAST +0.2 µs

M580

Modbus TCP, batched

208 ms

yes

MAST +0.1 µs

M580

Modbus TCP

—

no

refused by the controller

CompactLogix

CIP, range read

28 ms

yes

1% of scans

CompactLogix

CIP, batched

1.3 s

no

12% of scans

CompactLogix

CIP

—

no

beyond what it serves

Q03UDE, 10%

MC protocol, batched

50 ms

yes

scan unaffected

Q03UDE, 10%

MC protocol

24.2 s

no

scan unaffected

Q03UDE, 50%

MC protocol, batched

21 ms

yes

scan +10 µs (1%)

Q03UDE, 50%

MC protocol

8.4 s

no

not stable

Read times are the median at the job’s own rate. Keeps up means at least 95% of the reads arrived on schedule; a read close to the interval can still miss it often enough to fail. Not stable means the three passes disagreed on the controller’s figure, and such a cell is not quoted. On TwinCAT every ADS row reads elements of one array; OPC UA on the CX9240 is shown for both shapes. The C6920 and the CX1010 have no OPC UA server on this bench.

4.3. What the two jobs say

Most controllers do not notice either job, when the client asks well. The G2, the S7-1511, the S7-1516, the two TwinCAT 3 Beckhoffs, the M580 and the Q03UDE kept their programs at or near idle for every cheap way of asking. On the M580 no protocol moved its 2.6 µs MAST task by more than 0.4 µs at any rate. If your hardware is current and your client is sensible, the controller is rarely where the cost lands.

The old S7-1212C is the exception, showing the whole curve. Batched S7CommPlus does the historian job at 5% of its cycle, batched S7Comm at 16%. Every other way it offers reaches the limit. At 2500 values the batched S7CommPlus read is the cheaper one, because classic S7Comm negotiates 240-byte requests on this CPU and needs 24 of them where S7CommPlus needs one. OPC UA already costs it 8% at one read of 80 values every 2 s and reaches the limit at one every 500 ms.

The protocol decides whether the job fits at all. The two S7-1200s serve at most 1000 values over OPC UA, so 2500 do not publish there at all. The S7-1511 reads them only as array elements, in three requests and 33 seconds. Plain S7CommPlus does not keep up with the historian job on any Siemens CPU here. Batched, it keeps up on all three that speak it.

How the client asks decides the rest. On every vendor, the same data asked for the naive way was slower, often by one or two orders of magnitude, and on most families it cost the controller more:

Table 6. The same data, asked for well and asked for badly, on each family. Read time per read at one read every 2 s. 🔒 encrypted and authenticated.
Controller, valuesAsked wellAsked badlySlower by

S7-1212C, 2500

S7CommPlus, batched 🔒*: 157 ms

S7CommPlus 🔒*: 7.8 s

50 times

S7-1511, 2500

S7Comm, batched: 51 ms

S7Comm: 847 ms

17 times

CX1010, 2500

ADS, batched: 16 ms

ADS: 334 ms

21 times

CX9240, 2500

ADS, batched: 20 ms

ADS: 112 ms

5.6 times

M580, 500

Modbus TCP, batched: 41 ms

Modbus TCP: 5.0 s

123 times

CompactLogix, 500

CIP, range read: 7.5 ms

CIP: 4.3 s

571 times

Q03UDE (10%), 2500

MC protocol, batched: 51 ms

MC protocol: 24.2 s

475 times

Where the plain form sends one request per value, as Modbus, CIP and the MC protocol do, the gap is two to three orders of magnitude. The controllers often refuse the plain form at 500 or 2500 values altogether.

The M580 is the one controller where asking badly cost the program nothing. The M580 paid differently: it stopped answering. A controller protecting itself against a flood of small requests is a sensible design. For the client, it means silently getting no data.

The setting that splits time between program and clients decides who waits. The Q03UDE shows it most clearly. At its factory 10% it never let a client slow its scan, under any load: clients waited instead, 7.9 ms for 80 values. At 50% the same read took 3.1 ms. The scan paid for that: it was 220 µs longer at idle, and a client asking one value per request added about 400 µs more. Siemens calls the same trade-off the communication load, Rockwell the time slice.

Even the price of asking badly depends on the controller. Reading 2500 values with a handle per value took the C6920 62 ms, the CX9240 112 ms and the TwinCAT 2 CX1010 336 ms, against 17 to 20 ms batched on all three. The same plain ADS, the same values: a sixfold spread from the controller alone.

5. So what should you do?

Check how your client asks before you blame the protocol or the controller. On every vendor here, the gap between asking well and asking badly was larger than the gap between protocols. Read a range, not a list of elements. Let the client combine neighbors. Resolve names once, not on every read.

Size the job before you pick the protocol. A dashboard of 80 values is easy for almost anything on this bench. A historian of 2500 values twice a second rules out several protocols on some CPUs outright, for reasons that have nothing to do with speed: node limits and refused reads.

Look at the wire when the network is shared. Between the cheapest and the dearest protocol there is a factor of thirty in bytes per value. Across hundreds of devices on one segment that is the difference between noise and a planning problem.

Know the setting that splits time between program and clients. Every family here has one, under a different name. The setting decides whether a busy client slows the machine or simply waits. Each controller carries its own.

Measure your oldest controller, not your newest. On current hardware most jobs cost the program next to nothing. On the one old CPU here, every protocol had a limit, and the heavier ones reached it first.

A disclosure, as in the other two articles. I work on ToddySoft Connect, which provides drivers for every protocol in this article, and every number came out of its test suite. Having all ten in one library is also why they could be measured with the same client software. You should know about my interest before you weigh my conclusions.

6. What we got wrong

Three published conclusions from this work were wrong. Each was caught by someone asking an obvious question of a number that looked fine.

"UMAS is the most economical protocol on the bench." UMAS and Modbus had never been compared. They sat in different tables, with different tags on different controllers. Put side by side on nine scattered values, UMAS was cheaper, because it fetches in one exchange what Modbus needs several for. Read side by side on one controller over one contiguous block, the two were equal in time and in cost to the controller. Both results hold. They answer different questions.

"Bytes per value mean the same thing at any read size." They do not. Dividing by the count removes what grows with the values, not the fixed envelope of each request. Between 25 values and 9, batched Modbus nearly doubled per value, while plain Modbus did not move at all.

"OPC UA is an order of magnitude slower." On TwinCAT and on the Siemens G2 that was mostly the shape of the data. Array elements addressed one by one are OPC UA’s slow path. Read as separate variables, the same servers were up to ten times faster. On the S7-1511 the server stayed slow either way.

7. What this does not tell you

  • One controller per family, apart from Siemens. The figures describe these machines, not a product line.

  • Reads only. Nothing here writes.

  • Subscriptions are left out. They were measured on Siemens and Beckhoff only, and behave differently enough to need their own comparison. The two vendor articles cover them.

  • Many TwinCAT cost figures were not stable. On the CX9240 and the CX1010 the three passes often disagreed about the task’s 95th percentile. Those cells say so instead of quoting a number.

  • Idle programs. Every controller ran a light program. A controller already busy has less room than any figure here suggests.

  • The ctrlX took part in the byte sweep only. Its load was not measured.

8. The point

There is no fastest protocol. There is a controller that is already installed, a job it has to do, and a client that asks for the data well or badly.

Across ten protocols and seven vendors, the client’s habits moved the cost more often than the choice of protocol did. So before the next protocol debate, look at how your client asks. Of every fix on this bench it is the cheapest. On most controllers it is the only one you need.

9. Version history

  • 2026-10-06: First published.

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.

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

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 40% of its CPU. A look at what the OPC UA license buys, and where each way of reading puts its work.

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.