Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Don't undermine efforts to get ECN in the internet by enabling DCTCP unilaterally #9

Open
rscheff opened this issue Feb 22, 2023 · 43 comments

Comments

@rscheff
Copy link

rscheff commented Feb 22, 2023

DCTCP is not safe for deployment across uncontrolled paths, where the other endhost, and the forwarding nodes in between are not within the same administrative control.

DCTCP does not negotiate its modified semantics of the IP ECN markings.

For tangible gains, DCTCP requires the congested queue(s) to adhere to an ECN marking policy, which is very detrimental to classic ECN (similar to RoCE v2 with DCQCN).

Deploying any aspect of DCTCP unilaterally, may case significant (undesired) side effects:

  • DCTCP on one host, no network support, no remote host support -> classic TCP (leave at Cubic)
  • DCTCP on one host, classical ECN support in the network, no remote host support -> classic TCP
  • DCTCP on one host, DCTCP-stlye network marking, no remote host support -> no change to this session, very problematic to classic TCP with ECN over the switch doing DCTCP style marking
  • DCTCP on one host, no network support, TCP ECN on remote host -> classic TCP
  • DCTCP on one host, classic ECN network marking, TCP ECN on remote host -> very similar behavior to classic TCP + ECN
  • DCTCP on one host, classic ECN network marking, DCTCP on remote host -> ursurping network bandwidth and squeezing out classic TCP and TCP+ECN
  • DCTCP on one host, DCTCP-style network marking, DCTCP on remote host -> very good latency and bandwidht between for this session, very detrimental side effects to classic TCP and TCP+ECN

In short: There is a reason, why DCTCP has "data center" (all gear is in a single administrative control domain) in its name.

Also,as the above matrix shows, many realistic deployment scenarios will not gain any benefits by enabling DCTCP - but this may encourage further changes which will be very problematic, or alert ISP operators to very "interesting" behavior.

Afaik, as part of the built-in datacenter profile, W10/W11 TCP will activate DCTCP only, when the measured RTT is less than 6 ms to the remote host.

Creating a custom profile bypasses this RTT (latency / distance) safety check entirely.

If one wishes to enable DCTCP within the confines of the network operated locally, firewall rules should clear the TCP ECN (NOT the IP ECN) bits "AE"/"NS", "ECE" and "CWR" when forwarding traffic to the public internet. Or have dedicated internal NICs running DCTCP, while external facing interfaces run with Cubic.

@MysticFoxDE
Copy link
Owner

MysticFoxDE commented Feb 23, 2023

Hi @rscheff,

I'm stressed, so I have to keep my answer short.
I've also written many longer novels on this topic at Spiceworks.
CUBIC is NOT designed for high speed low latency connections but for high speed high latency connections and DCTCP is designed for high speed low latency networks.
For the majority of mainly (European) industrial customers, the latter and not the former is important.

For more information from third-party sources see here.
https://core.ac.uk/download/pdf/153572182.pdf
https://legacy.netdevconf.info/2.2/papers/brakmo-tcpcongestionanalysis-talk.pdf
https://opennetworking.org/wp-content/uploads/2021/05/2021-P4-WS-Yanfang-Le-Abstract.pdf

I would like to write my closing words in German, because I can't express it well in English.

Was meine persönliche Meinung angeht, so können sich alle entsprechenden IT-Hersteller alle Optimierungen, die nur noch auf Public-Cloud ausgerichtet sind, sonst wohin schieben.

Please don't take it personally, the above statement is more aimed at Microsoft, Google, Apple & Co.

Best Regards from Germany
Alex

@rscheff
Copy link
Author

rscheff commented Feb 23, 2023

I'm afraid you entirely missed my point.

DCTCP is a modified (proportional) reaction to ECN marks. But the congestion window is still governed by either NewReno (early versions of DCTCP in W10) or Cubic (currently) when ramping up.

Without congestion (loss or marks), you don't need to control the reaction - as it never happens in the first place. E.g. enabling Ethernet flow control (PFC) in a local environment may remove all losses or markings (thus any reaction by TCP to that now missing signal is irrelevant). In such cases, having an infinite slow start threshold, and maybe even an infinite initial window (which is not in the set of tunings, but many *nix and *bsd OS allow tuning this) is all you need to get perfect throughput from the get-go, if there are no other competing flows present, or the flow control reaction is fast enough that the buffers provided by the intermediate switches can deal with the bursts. Latency only occurs within the send Q, while the sender is not allowed (by flow control) to transmit.

Further, unilateral activating DCTCP on only one or both Hosts, will again NOT have any effect - you'll simply revert back to standard NewReno or Cubic CC, in the presence of packet drops. Which are likely to happen, if you don't have end-to-end flow control, or sufficient bandwidth in relationship to the transfer speeds by the applications. So, again, no gain (but no problem).

But with more and more ISPs starting to realize that ECN marking does not incur the latency cost of retransmissions, there is an uptick in use of (vendor default) ECN. And with that, classic TCP will suffer when competing on a bottleneck queue with a DCTCP sender, to the point where classic TCP only progresses at a snails pace.

DCTCP only improves the in-network latency when also the Queues on the switches operate with ECN marking based on instantaneous queue depth (instead of an EDWA derivate thereof), with either instant (original DCTCP paper) or very steep (many subsequent studies with real datacenter traffic) marking probablity onset.

However, that way of marking TCP packets is incompatible with non-DCTCP traffic - where is dramatically hurts performance. Simultaneously, DCTCP itself has no means to let the network devices differentiate between DCTCP traffic, and non-DCTCP TCP traffic. Therefore, there is extreme irony in your statment

[...] IT-Hersteller alle Optimierungen, die nur noch auf Public-Cloud ausgerichtet sind, sonst wohin schieben.

since DCTCP is the epitome of an optimization, which is extremely narrowly an optimization for (pulic) cloud workloads, where one has to content with massive Incast inducing, e.g. map-reduce or NoSQL type workloads.

To repeat: Most of the optimizations are well known for latency-bound, low bandwidth (comparatively; this may still mean 1 GB/s transfer speeds across a 100G link) environments. And there is nothing wrong with that, as all the observed improvements there can also be had to some extent over the public internet.

Reducing the Delayed ACK time down to 1 ms may cause some spurious retransmissions (but Linux hosts, if these are downloaded from by a W11 client, are quite good at rewinding erranous congestion window adjustments) - and that particular aspect was tuned down over the years from 1000 ms originally down to 400, 200, and nowadays typically 40 ms already in the defaults.

In closing: I'm not disputing that DCTCP has some very nice properties, which many in the IT industry running local (on prem) datacenters could benefit from. The issue is, that deploying DCTCP is not as simple as unilaterally turning on DCTCP, or even on both end hosts. It also requires some tuning of the intermediate switches, and DCTCP traffic has to "live" in a Queue of its own - as the agressive ECN marking needed by DCTCP is incompatible with classic (high latency) TCP. And on the edge (links to remote location, public internet), firewalls better get set up to disable DCTCP by clearing the TCP CWR, ECE bits in outgoing TCP SYN packets - unless the TCP AE (formerly known as TCP NS) bit is set. (To make sure one doesn't need to adjust the firewall policies again, once L4S gets deployed, and proper handling of these different semantics is done automatically).

A DCTCP sender not able to negotiate for TCP ECN will simply revert to standard NewReno or Cubic behavior (which is still the underpinnings of DCTCP really).

@MysticFoxDE
Copy link
Owner

Hi @rscheff,

Richard, I don't find your arguments uninteresting or unimportant, so I deliberately left this post open.
However, my energy is pretty much drained this week, so I'd like to move this thematically very complex conversation to next week.

Best Regards from Germany
Alex

P.S.
Please do an ISCSI test on one of your test NetApps, once with CUBIC and then with DCTCP with a random workload and 4K block size.
😉

@rscheff
Copy link
Author

rscheff commented Feb 23, 2023

Test environment:

1G (yes, sorry all I could cobble together remotely on short notice) physical machine, connected via 3 L2 hops (interconnects 40G and 100G) to a reasonable decent iscsi storage box.

Unilateral deployment of DCTCP here (no network or server side changes).

Microsoft Windows [Version 10.0.19045.2604]
(c) Microsoft Corporation. All rights reserved.

rndtest:

[global]
size=100m
directory=L\:\
thread
iodepth=32
direct=1
group_reporting
ioengine=windowsaio
runtime=60
time_based

[rand-read]
rw=randread
blocksize=4k
stonewall

C:\Program Files\fio>fio rndtest
rand-read: (g=0): rw=randread, bs=(R) 4096B-4096B, (W) 4096B-4096B, (T) 4096B-4096B, ioengine=windowsaio, iodepth=32
fio-3.20-dirty
Starting 1 thread
Jobs: 1 (f=1): [r(1)][100.0%][r=98.3MiB/s][r=25.2k IOPS][eta 00m:00s]
rand-read: (groupid=0, jobs=1): err= 0: pid=11276: Thu Feb 23 15:47:37 2023
read: IOPS=24.7k, BW=96.5MiB/s (101MB/s)(5789MiB/60002msec)
slat (usec): min=7, max=12600, avg=16.65, stdev=17.37
clat (nsec): min=811, max=14568k, avg=1237704.66, stdev=237394.43
lat (usec): min=342, max=14587, avg=1254.35, stdev=238.27
clat percentiles (usec):
| 1.00th=[ 750], 5.00th=[ 906], 10.00th=[ 979], 20.00th=[ 1057],
| 30.00th=[ 1123], 40.00th=[ 1172], 50.00th=[ 1221], 60.00th=[ 1270],
| 70.00th=[ 1319], 80.00th=[ 1418], 90.00th=[ 1532], 95.00th=[ 1614],
| 99.00th=[ 1827], 99.50th=[ 1942], 99.90th=[ 2343], 99.95th=[ 2638],
| 99.99th=[ 3949]
bw ( KiB/s): min=84859, max=102213, per=100.00%, avg=98901.59, stdev=4290.26, samples=116
iops : min=21214, max=25553, avg=24725.03, stdev=1072.55, samples=116
lat (nsec) : 1000=0.01%
lat (usec) : 2=0.01%, 4=0.01%, 20=0.01%, 50=0.01%, 100=0.01%
lat (usec) : 250=0.01%, 500=0.16%, 750=0.86%, 1000=11.19%
lat (msec) : 2=87.45%, 4=0.33%, 10=0.01%, 20=0.01%
cpu : usr=3.33%, sys=38.33%, ctx=0, majf=0, minf=0
IO depths : 1=0.1%, 2=0.1%, 4=0.2%, 8=0.8%, 16=52.0%, 32=46.9%, >=64=0.0%
submit : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
complete : 0=0.0%, 4=96.5%, 8=2.0%, 16=1.3%, 32=0.1%, 64=0.0%, >=64=0.0%
issued rwts: total=1482091,0,0,0 short=0,0,0,0 dropped=0,0,0,0
latency : target=0, window=0, percentile=100.00%, depth=32

Run status group 0 (all jobs):
READ: bw=96.5MiB/s (101MB/s), 96.5MiB/s-96.5MiB/s (101MB/s-101MB/s), io=5789MiB (6071MB), run=60002-60002msec

iPerf3 pure TCP troughput test

C:\Program Files\fio>iperf3 -c 10.65.58.55
Connecting to host 10.65.58.55, port 5201
[ 4] local 10.65.51.30 port 53407 connected to 10.65.58.55 port 5201
[ ID] Interval Transfer Bandwidth
[ 4] 0.00-1.00 sec 112 MBytes 940 Mbits/sec
[ 4] 1.00-2.00 sec 112 MBytes 936 Mbits/sec
[ 4] 2.00-3.00 sec 112 MBytes 942 Mbits/sec
[ 4] 3.00-4.00 sec 112 MBytes 941 Mbits/sec
[ 4] 4.00-5.00 sec 112 MBytes 942 Mbits/sec
[ 4] 5.00-6.00 sec 112 MBytes 942 Mbits/sec
[ 4] 6.00-7.00 sec 112 MBytes 942 Mbits/sec
[ 4] 7.00-8.00 sec 112 MBytes 942 Mbits/sec
[ 4] 8.00-9.00 sec 112 MBytes 941 Mbits/sec
[ 4] 9.00-10.00 sec 112 MBytes 941 Mbits/sec


[ ID] Interval Transfer Bandwidth
[ 4] 0.00-10.00 sec 1.10 GBytes 941 Mbits/sec sender
[ 4] 0.00-10.00 sec 1.10 GBytes 941 Mbits/sec receiver

iperf Done.

Switching to DCTCP

C:\Program Files\fio>netstat -antxyp tcp

Active Connections

Proto Local Address Foreign Address State Template
:
TCP 10.65.51.30:53330 10.65.58.55:3260 ESTABLISHED Internet
:

C:\Program Files\fio>netsh int tcp set supplemental internet congestionprovider=dctcp
Ok.

Validating that old iscsi session is torn, and a new one with DCTCP established

C:\Program Files\fio>netstat -antxyp tcp | find /i "3260"
TCP 10.65.51.30:53330 10.65.58.55:3260 ESTABLISHED Internet

C:\Program Files\fio>netstat -antxyp tcp | find /i "3260"
TCP 10.65.51.30:53330 10.65.58.55:3260 TIME_WAIT Not Applicable

C:\Program Files\fio>netstat -antxyp tcp | find /i "3260"
TCP 10.65.51.30:53330 10.65.58.55:3260 TIME_WAIT Not Applicable
TCP 10.65.51.30:53647 10.65.58.55:3260 ESTABLISHED Internet

C:\Program Files\fio>netstat -antxyp tcp | find /i "3260"
TCP 10.65.51.30:53647 10.65.58.55:3260 ESTABLISHED Internet

DCTCP congestion control:

C:\Program Files\fio>fio rndtest -runtime=300
rand-read: (g=0): rw=randread, bs=(R) 4096B-4096B, (W) 4096B-4096B, (T) 4096B-4096B, ioengine=windowsaio, iodepth=32
fio-3.20-dirty
Starting 1 thread
Jobs: 1 (f=1): [r(1)][100.0%][r=96.7MiB/s][r=24.8k IOPS][eta 00m:00s]
rand-read: (groupid=0, jobs=1): err= 0: pid=9960: Thu Feb 23 18:49:42 2023
read: IOPS=24.6k, BW=96.2MiB/s (101MB/s)(5772MiB/60002msec)
slat (usec): min=7, max=1326, avg=15.50, stdev=12.53
clat (usec): min=41, max=16017, avg=1247.21, stdev=241.38
lat (usec): min=382, max=16054, avg=1262.71, stdev=242.06
clat percentiles (usec):
| 1.00th=[ 717], 5.00th=[ 898], 10.00th=[ 979], 20.00th=[ 1074],
| 30.00th=[ 1139], 40.00th=[ 1188], 50.00th=[ 1237], 60.00th=[ 1287],
| 70.00th=[ 1336], 80.00th=[ 1401], 90.00th=[ 1532], 95.00th=[ 1631],
| 99.00th=[ 1844], 99.50th=[ 1991], 99.90th=[ 2573], 99.95th=[ 2868],
| 99.99th=[ 4047]
bw ( KiB/s): min=81385, max=108124, per=100.00%, avg=98586.22, stdev=3234.26, samples=116
iops : min=20346, max=27031, avg=24646.22, stdev=808.59, samples=116
lat (usec) : 50=0.01%, 100=0.01%, 250=0.01%, 500=0.08%, 750=1.24%
lat (usec) : 1000=10.29%
lat (msec) : 2=87.92%, 4=0.46%, 10=0.01%, 20=0.01%
cpu : usr=3.33%, sys=33.33%, ctx=0, majf=0, minf=0
IO depths : 1=0.1%, 2=0.1%, 4=0.1%, 8=0.5%, 16=53.9%, 32=45.5%, >=64=0.0%
submit : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
complete : 0=0.0%, 4=96.5%, 8=2.1%, 16=1.3%, 32=0.1%, 64=0.0%, >=64=0.0%
issued rwts: total=1477504,0,0,0 short=0,0,0,0 dropped=0,0,0,0
latency : target=0, window=0, percentile=100.00%, depth=32

Run status group 0 (all jobs):
READ: bw=96.2MiB/s (101MB/s), 96.2MiB/s-96.2MiB/s (101MB/s-101MB/s), io=5772MiB (6052MB), run=60002-60002msec

read only summary:

cubic:
lat (nsec) : 1000=0.01%
lat (usec) : 2=0.01%, 4=0.01%, 20=0.01%, 50=0.01%, 100=0.01%
lat (usec) : 250=0.01%, 500=0.16%, 750=0.86%, 1000=11.19%
lat (msec) : 2=87.45%, 4=0.33%, 10=0.01%, 20=0.01%
lat (usec): min=342, max=14587, avg=1254.35, stdev=238.27
dctcp:
lat (usec) : 50=0.01%, 100=0.01%, 250=0.01%, 500=0.08%, 750=1.24%
lat (usec) : 1000=10.29%
lat (msec) : 2=87.92%, 4=0.46%, 10=0.01%, 20=0.01%
lat (usec): min=382, max=16054, avg=1262.71, stdev=242.06

Cubic marginally better (but probably not statistically significant).

Read and Write tests with DCTCP:

[global]
size=100m
directory=L\:\
thread
iodepth=32
direct=1
group_reporting
ioengine=windowsaio
ramp_time=15
runtime=300
time_based
write_lat_log=4krandom

[rand-read]
rw=randread
blocksize=4k
stonewall

[rand-write]
rw=randwrite
blocksize=4k
stonewall 

C:\Program Files\fio>fio rndtest
rand-read: (g=0): rw=randread, bs=(R) 4096B-4096B, (W) 4096B-4096B, (T) 4096B-4096B, ioengine=windowsaio, iodepth=32
rand-write: (g=1): rw=randwrite, bs=(R) 4096B-4096B, (W) 4096B-4096B, (T) 4096B-4096B, ioengine=windowsaio, iodepth=32
fio-3.20-dirty
Starting 2 threads
Jobs: 1 (f=1): [_(1),w(1)][100.0%][w=109MiB/s][w=27.8k IOPS][eta 00m:00s]
rand-read: (groupid=0, jobs=1): err= 0: pid=16280: Thu Feb 23 19:09:47 2023
read: IOPS=24.5k, BW=95.8MiB/s (100MB/s)(28.1GiB/300002msec)
slat (usec): min=7, max=12735, avg=14.86, stdev=12.92
clat (nsec): min=1625, max=14785k, avg=1259142.60, stdev=216652.72
lat (usec): min=368, max=14805, avg=1274.00, stdev=218.37
clat percentiles (usec):
| 1.00th=[ 799], 5.00th=[ 938], 10.00th=[ 1012], 20.00th=[ 1106],
| 30.00th=[ 1156], 40.00th=[ 1205], 50.00th=[ 1254], 60.00th=[ 1287],
| 70.00th=[ 1336], 80.00th=[ 1401], 90.00th=[ 1516], 95.00th=[ 1614],
| 99.00th=[ 1778], 99.50th=[ 1942], 99.90th=[ 2573], 99.95th=[ 2933],
| 99.99th=[ 4113]
bw ( KiB/s): min=81048, max=105637, per=100.00%, avg=98110.32, stdev=2190.68, samples=337
iops : min=20262, max=26409, avg=24527.21, stdev=547.66, samples=337
lat (usec) : 2=0.01%, 4=0.01%, 50=0.01%, 100=0.01%, 250=0.01%
lat (usec) : 500=0.03%, 750=0.52%, 1000=8.26%
lat (msec) : 2=90.79%, 4=0.39%, 10=0.01%, 20=0.01%
cpu : usr=4.67%, sys=35.33%, ctx=0, majf=0, minf=0
IO depths : 1=0.1%, 2=0.1%, 4=0.1%, 8=0.2%, 16=53.6%, 32=46.2%, >=64=0.0%
submit : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
complete : 0=0.0%, 4=96.3%, 8=2.2%, 16=1.4%, 32=0.1%, 64=0.0%, >=64=0.0%
issued rwts: total=7357263,0,0,0 short=0,0,0,0 dropped=0,0,0,0
latency : target=0, window=0, percentile=100.00%, depth=32
rand-write: (groupid=1, jobs=1): err= 0: pid=11396: Thu Feb 23 19:09:47 2023
write: IOPS=27.6k, BW=108MiB/s (113MB/s)(31.5GiB/300002msec); 0 zone resets
slat (usec): min=11, max=4103, avg=28.00, stdev=17.32
clat (usec): min=4, max=15792, avg=1061.24, stdev=238.37
lat (usec): min=429, max=16236, avg=1089.23, stdev=237.59
clat percentiles (usec):
| 1.00th=[ 652], 5.00th=[ 766], 10.00th=[ 840], 20.00th=[ 906],
| 30.00th=[ 963], 40.00th=[ 996], 50.00th=[ 1037], 60.00th=[ 1074],
| 70.00th=[ 1123], 80.00th=[ 1172], 90.00th=[ 1287], 95.00th=[ 1418],
| 99.00th=[ 1860], 99.50th=[ 2114], 99.90th=[ 2802], 99.95th=[ 3228],
| 99.99th=[ 6063]
bw ( KiB/s): min=95137, max=113071, per=100.00%, avg=110322.10, stdev=2853.83, samples=584
iops : min=23784, max=28267, avg=27580.18, stdev=713.46, samples=584
lat (usec) : 10=0.01%, 250=0.01%, 500=0.02%, 750=3.88%, 1000=36.41%
lat (msec) : 2=59.03%, 4=0.64%, 10=0.02%, 20=0.01%
cpu : usr=6.33%, sys=60.67%, ctx=0, majf=0, minf=0
IO depths : 1=0.1%, 2=0.1%, 4=0.1%, 8=0.2%, 16=71.1%, 32=28.7%, >=64=0.0%
submit : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
complete : 0=0.0%, 4=95.2%, 8=3.7%, 16=1.1%, 32=0.1%, 64=0.0%, >=64=0.0%
issued rwts: total=0,8265177,0,0 short=0,0,0,0 dropped=0,0,0,0
latency : target=0, window=0, percentile=100.00%, depth=32

Run status group 0 (all jobs):
READ: bw=95.8MiB/s (100MB/s), 95.8MiB/s-95.8MiB/s (100MB/s-100MB/s), io=28.1GiB (30.1GB), run=300002-300002msec

Run status group 1 (all jobs):
WRITE: bw=108MiB/s (113MB/s), 108MiB/s-108MiB/s (113MB/s-113MB/s), io=31.5GiB (33.9GB), run=300002-300002msec

Read and Write tests Cubic:

C:\Program Files\fio>fio rndtest
rand-read: (g=0): rw=randread, bs=(R) 4096B-4096B, (W) 4096B-4096B, (T) 4096B-4096B, ioengine=windowsaio, iodepth=32
rand-write: (g=1): rw=randwrite, bs=(R) 4096B-4096B, (W) 4096B-4096B, (T) 4096B-4096B, ioengine=windowsaio, iodepth=32
fio-3.20-dirty
Starting 2 threads
Jobs: 1 (f=1): [_(1),f(1)][100.0%][eta 00m:00s]
rand-read: (groupid=0, jobs=1): err= 0: pid=16184: Thu Feb 23 19:28:32 2023
read: IOPS=24.6k, BW=96.2MiB/s (101MB/s)(28.2GiB/300002msec)
slat (usec): min=7, max=4033, avg=14.89, stdev=12.06
clat (usec): min=2, max=13835, avg=1252.40, stdev=214.38
lat (usec): min=387, max=13854, avg=1267.28, stdev=215.82
clat percentiles (usec):
| 1.00th=[ 791], 5.00th=[ 938], 10.00th=[ 1012], 20.00th=[ 1090],
| 30.00th=[ 1156], 40.00th=[ 1205], 50.00th=[ 1237], 60.00th=[ 1287],
| 70.00th=[ 1336], 80.00th=[ 1401], 90.00th=[ 1516], 95.00th=[ 1598],
| 99.00th=[ 1762], 99.50th=[ 1909], 99.90th=[ 2540], 99.95th=[ 2900],
| 99.99th=[ 4047]
bw ( KiB/s): min=86928, max=106715, per=100.00%, avg=98636.68, stdev=1947.86, samples=320
iops : min=21732, max=26678, avg=24658.77, stdev=486.93, samples=320
lat (usec) : 4=0.01%, 10=0.01%, 50=0.01%, 100=0.01%, 250=0.01%
lat (usec) : 500=0.03%, 750=0.62%, 1000=8.63%
lat (msec) : 2=90.35%, 4=0.36%, 10=0.01%, 20=0.01%
cpu : usr=5.33%, sys=35.33%, ctx=0, majf=0, minf=0
IO depths : 1=0.1%, 2=0.1%, 4=0.1%, 8=0.3%, 16=53.6%, 32=46.1%, >=64=0.0%
submit : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
complete : 0=0.0%, 4=96.3%, 8=2.2%, 16=1.4%, 32=0.1%, 64=0.0%, >=64=0.0%
issued rwts: total=7389599,0,0,0 short=0,0,0,0 dropped=0,0,0,0
latency : target=0, window=0, percentile=100.00%, depth=32
rand-write: (groupid=1, jobs=1): err= 0: pid=13536: Thu Feb 23 19:28:32 2023
write: IOPS=27.6k, BW=108MiB/s (113MB/s)(31.6GiB/300001msec); 0 zone resets
slat (usec): min=11, max=9591, avg=28.83, stdev=19.00
clat (usec): min=71, max=12563, avg=1042.21, stdev=228.50
lat (usec): min=435, max=13152, avg=1071.05, stdev=227.58
clat percentiles (usec):
| 1.00th=[ 644], 5.00th=[ 758], 10.00th=[ 816], 20.00th=[ 889],
| 30.00th=[ 938], 40.00th=[ 988], 50.00th=[ 1020], 60.00th=[ 1057],
| 70.00th=[ 1106], 80.00th=[ 1156], 90.00th=[ 1254], 95.00th=[ 1385],
| 99.00th=[ 1795], 99.50th=[ 2024], 99.90th=[ 2671], 99.95th=[ 3032],
| 99.99th=[ 5211]
bw ( KiB/s): min=87533, max=112849, per=100.00%, avg=110604.00, stdev=2494.51, samples=585
iops : min=21883, max=28212, avg=27650.64, stdev=623.63, samples=585
lat (usec) : 100=0.01%, 250=0.01%, 500=0.03%, 750=4.59%, 1000=39.36%
lat (msec) : 2=55.50%, 4=0.52%, 10=0.02%, 20=0.01%
cpu : usr=7.00%, sys=59.33%, ctx=0, majf=0, minf=0
IO depths : 1=0.1%, 2=0.1%, 4=0.1%, 8=0.2%, 16=74.2%, 32=25.6%, >=64=0.0%
submit : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
complete : 0=0.0%, 4=94.4%, 8=3.9%, 16=1.6%, 32=0.1%, 64=0.0%, >=64=0.0%
issued rwts: total=0,8287331,0,0 short=0,0,0,0 dropped=0,0,0,0
latency : target=0, window=0, percentile=100.00%, depth=32

Run status group 0 (all jobs):
READ: bw=96.2MiB/s (101MB/s), 96.2MiB/s-96.2MiB/s (101MB/s-101MB/s), io=28.2GiB (30.3GB), run=300002-300002msec

Run status group 1 (all jobs):
WRITE: bw=108MiB/s (113MB/s), 108MiB/s-108MiB/s (113MB/s-113MB/s), io=31.6GiB (33.9GB), run=300001-300001msec

Summary:

Cubic:
rd lat (usec): min=387, max=13854, avg=1267.28, stdev=215.82
wr lat (usec): min=435, max=13152, avg=1071.05, stdev=227.58
DCTCP:
rd lat (usec): min=368, max=14805, avg=1274.00, stdev=218.37
wr lat (usec): min=429, max=16236, avg=1089.23, stdev=237.59

Cubic marginally better (but probably not statistically significant).

I would really like to see a scenario, where unilateral, or even bilateral (both end hosts) deliver improved latency/throughput, just by using DCTCP For the reasons explained in my earlier statements, this would be very unexpected. Switching the entire profile around does toggle some autotunings in W11, so the profile should be kept idential in all other aspects between these runs.

@MysticFoxDE
Copy link
Owner

MysticFoxDE commented Feb 27, 2023

Hi Richard,

was dagegen, wenn wir in dieser thematisch komplizierten Unterhaltung auf deutsch wechseln
Dass würde mir, vor allem Zeitlich sehr entgegen kommen.
Die Essenz kann man dann ja immer noch übersetzen.

Gruss Alex

@rscheff
Copy link
Author

rscheff commented Feb 27, 2023

Gerne. Auch gerne PM...

@MysticFoxDE
Copy link
Owner

MysticFoxDE commented Feb 27, 2023

Moin Richard,

wir können gerne auch weiterhin offen plaudern, habe nichts zu verstecken.

Ich habe bei Cubic bisher deutlich grössere Latenzschwankungen gesehen wie bei DCTCP und diese Erfahrungen unterstreicht auch der folgende Artikel.
https://www.ietf.org/proceedings/94/slides/slides-94-dispatch-2.pdf
Hier sind insbesondere Seite 12 und 13 sehr interessant.

Wenn ich es zeitlich noch schaffe, dann lasse ich auf den beiden High-Performance Workstations, die eigentlich diese Woche zum Kunden gehen müssen, auch noch einen neuen "DCTCP VS CUBIC" Test laufen.

Des weiteren sehe ich gerade, dass du bei deinen Tests einen Worker hast lesen lassen und einen Schreiben, ich dachte da aber eher an einen Test mit (readwrite=rw oder rw=randrw ) und iodepth=4, sprich, abwechselnd Lesen und Schreiben mit nur einem Worker. Hierbei solltest du zwischen CUBIC und DCTCP schon einen deutlicheren Unterschied sehen.

So jetzt muss ich aber ins Nest.
Sorry für die Kürze, musste heute jedoch ein gestorbenes SGW wiederbeleben und bin nun selber erledigt. 🥱

Beste Grüsse aus BaWü
Alex

@rscheff
Copy link
Author

rscheff commented Feb 28, 2023

Dir ist aber schon klar, dass diese L4S Präsentation genau meinen Punkt unterstreicht, oder?

Exakt das Beispiel dass du nennst, zeigt was möglich ist, wenn alle beteiligten Geräte entsprechende Verbesserungen erfahren:

Der Sender macht "DCTCP" (also DCTCP artige, proportionale Reduktion der Transfergeschwindigkeit). Der Empfänger liefert die Signale aus dem Netzwerk möglichst rasch, und unverfälscht retour. Und das Netzwerk kann diesen Low-Latency Traffic identifizieren und benutzt IP ECN in einer an deren Semantik, als bei klassichem TCP ECN.

Um es zum 3. (4.?) mal zu wiederholen:

  • Unilateral DCTCP (von Microsoft) zu aktivieren, hilft nicht. Im besten Fall ist das exakt gleich gut, oder gleich schlecht, wie Cubic oder Newreno zu fahren.

  • DCTCP auf beiden Seiten zu aktivieren, ist ebenfalls nicht hilfreich - es fehlen immer noch die ECN markierungen aus dem Netzwerk.

  • IP ECN im Netzwerk mit Standardparametern zu aktivieren, während TCP ECN verhandelt wird, und entweder die eine oder die andere Seite mit DCTCP unterwegs ist, hilft ebenfalls nicht. Auch hier ist das Verhalten faktisch ident mit dem klassichen Verhalten von TCP Cubic mit ECN, oder TCP NewReno mit ECN (als Nebeneffekt wie TCP ECN nach RFC3168 implementiert ist).

  • Nur wenn man nun abschliessend DCTCP beidseitig aktiviert, und im Netz klassische IP ECN Markierungen oder die modifizierte Markierungsmethode die für DCTCP notwendig ist, einsetzen - dann haben zwar diese DCTCP Sessions einen Vorteil, aber das führt zwangsläufig zu einer katastrophalen Benachteiligung von klassischem TCP (also TCP ohne ECN, oder TCP mit RFC3168 ECN). Also klassisches (Internet) TCP funktioniert in beiden Fällen des Einsatzes von IP ECN auf den Switches nicht mehr während auch eine DCTCP Session aktiv ist.

Und mangels eines eindeutigen Signals eines DCTCP Hosts an das Netzwerk, dass der Traffic diese modifizierten Semantiken nutzt, und da es bislang keine Kopplung des Congestion (Überlast) Signals zwischen einer Queue die für DCTCP eingerichtet ist, und einer Queue für "normalen" Traffic, kann man faktisch beide Varianten nicht gleichzeitig über das gleiche Netz laufen lassen. Oder man muß administrativ entsprechend für Trennung sorgen (ACLs auf Src+Dst L3 basis, für jedes Paar von Geräten, die bekanntermassen DCTCP aktiv haben - und deren Traffic dann eine eigene Queue nutzt).

Das hilft aber immer noch nicht für die Fairness zwischen DCTCP und TCP (entschärft aber das Problem etwas).

Die Presentation von Koen zeigt jedoch auf, was möglich ist, wenn man das L4S Framework umsetzt. Das besteht aber, um es nochmal explizit zu sagen, aus deutlich mehr als "wir schalten mal DCTCP auf dem Server ein":

  • DCTCP artige proportionale Nachsteuerung der Senderate
  • Saubere Verhandlung eines besseren ECN Signalisierungsprotokolls in TCP*
  • Markierung des L4S Traffics sodass Netzwerkgeräte den Traffic mit dem passenden ECN-markierungen (oder Drops) versehen
  • Kopplung der p2 (klassisches TCP) und p (DCTCP/L4S/DCQCN) Queues mithilfe des DualQ-AQM Verfahrens damit eine Koexistenz zwischen normalem, nicht-ECN TCP und L4S Traffic möglich ist.

'* Disclaimer: Ich bin einer der Autoren dieses Teilaspekts in L4S: AccECN

@MysticFoxDE
Copy link
Owner

MysticFoxDE commented Feb 28, 2023

@rscheff

Moin Richard,

ich habe es heute morgen nun doch geschafft den "CUBIC VS DCTCP" Test auf den beiden Powerworkstations zu machen. 😁

Folgend die Ergebnisse:
(Ich habe zur Sicherheit jeweils 5 Testläufe gemacht.)

W11 22H2 CUBIC TO W11 22H2 CUBIC:

C:\WORK\DISKSPD>diskspd -t4 -o4 -b4k -si4k -w50 -d60 -Su -D -L \\172.16.200.2\TEST\IO20G.dat

Command Line: diskspd -t4 -o4 -b4k -si4k -w50 -d60 -Su -D -L \\172.16.200.2\TEST\IO20G.dat

Input parameters:

        timespan:   1
        -------------
        duration: 60s
        warm up time: 5s
        cool down time: 0s
        measuring latency
        gathering IOPS at intervals of 1000ms
        random seed: 0
        path: '\\172.16.200.2\TEST\IO20G.dat'
                think time: 0ms
                burst size: 0
                software cache disabled
                using hardware write cache, writethrough off
                performing mix test (read/write ratio: 50/50)
                block size: 4096
                using interlocked sequential I/O (stride: 4096)
                number of outstanding I/O operations: 4
                thread stride size: 0
                threads per file: 4
                using I/O Completion Ports
                IO priority: normal

System information:

        computer name: DESKTOP-DML65F5
        start time: 2023/02/28 08:41:53 UTC

Results for timespan 1:
*******************************************************************************

actual test time:       60.01s
thread count:           4
proc count:             24

CPU |  Usage |  User  |  Kernel |  Idle
-------------------------------------------
   0|  53.42%|   0.62%|   52.80%|  46.58%
   1|   0.05%|   0.00%|    0.05%|  99.95%
   2|   0.00%|   0.00%|    0.00%| 100.00%
   3|   0.00%|   0.00%|    0.00%| 100.00%
   4|   2.32%|   0.08%|    2.24%|  97.68%
   5|   0.21%|   0.08%|    0.13%|  99.79%
   6|   0.10%|   0.05%|    0.05%|  99.90%
   7|   0.00%|   0.00%|    0.00%| 100.00%
   8|   2.81%|   0.05%|    2.76%|  97.19%
   9|   1.07%|   0.00%|    1.07%|  98.93%
  10|   1.04%|   0.00%|    1.04%|  98.96%
  11|   0.00%|   0.00%|    0.00%| 100.00%
  12|   0.23%|   0.03%|    0.21%|  99.77%
  13|   0.00%|   0.00%|    0.00%| 100.00%
  14|   0.03%|   0.03%|    0.00%|  99.97%
  15|   0.00%|   0.00%|    0.00%| 100.00%
  16|   0.00%|   0.00%|    0.00%| 100.00%
  17|   0.00%|   0.00%|    0.00%| 100.00%
  18|   0.00%|   0.00%|    0.00%| 100.00%
  19|   0.00%|   0.00%|    0.00%| 100.00%
  20|   0.00%|   0.00%|    0.00%| 100.00%
  21|   0.00%|   0.00%|    0.00%| 100.00%
  22|   0.00%|   0.00%|    0.00%| 100.00%
  23|   0.00%|   0.00%|    0.00%| 100.00%
-------------------------------------------
avg.|   2.55%|   0.04%|    2.51%|  97.45%

Total IO
thread |       bytes     |     I/Os     |    MiB/s   |  I/O per s |  AvgLat  | IopsStdDev | LatStdDev |  file
------------------------------------------------------------------------------------------------------------------
     0 |      4151554048 |      1013563 |      65.98 |   16889.97 |    0.235 |     647.55 |     0.087 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     1 |      6038204416 |      1474171 |      95.96 |   24565.52 |    0.163 |     148.35 |     0.041 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     2 |      6087663616 |      1486246 |      96.75 |   24766.74 |    0.161 |     152.94 |     0.041 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     3 |      6087979008 |      1486323 |      96.75 |   24768.02 |    0.161 |     144.61 |     0.041 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
------------------------------------------------------------------------------------------------------------------
total:       22365401088 |      5460303 |     355.43 |   90990.25 |    0.175 |     505.31 |     0.060

Read IO
thread |       bytes     |     I/Os     |    MiB/s   |  I/O per s |  AvgLat  | IopsStdDev | LatStdDev |  file
------------------------------------------------------------------------------------------------------------------
     0 |      2074935296 |       506576 |      32.97 |    8441.56 |    0.233 |     324.57 |     0.087 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     1 |      3017904128 |       736793 |      47.96 |   12277.89 |    0.158 |     109.32 |     0.040 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     2 |      3044147200 |       743200 |      48.38 |   12384.65 |    0.157 |      92.20 |     0.040 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     3 |      3042537472 |       742807 |      48.35 |   12378.10 |    0.157 |      98.51 |     0.040 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
------------------------------------------------------------------------------------------------------------------
total:       11179524096 |      2729376 |     177.66 |   45482.20 |    0.171 |     274.97 |     0.060

Write IO
thread |       bytes     |     I/Os     |    MiB/s   |  I/O per s |  AvgLat  | IopsStdDev | LatStdDev |  file
------------------------------------------------------------------------------------------------------------------
     0 |      2076618752 |       506987 |      33.00 |    8448.41 |    0.238 |     335.01 |     0.086 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     1 |      3020300288 |       737378 |      48.00 |   12287.63 |    0.167 |     103.65 |     0.041 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     2 |      3043516416 |       743046 |      48.37 |   12382.09 |    0.166 |     106.58 |     0.041 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     3 |      3045441536 |       743516 |      48.40 |   12389.92 |    0.166 |     106.03 |     0.041 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
------------------------------------------------------------------------------------------------------------------
total:       11185876992 |      2730927 |     177.77 |   45508.05 |    0.179 |     294.14 |     0.059



total:
  %-ile |  Read (ms) | Write (ms) | Total (ms)
----------------------------------------------
    min |      0.073 |      0.078 |      0.073
   25th |      0.134 |      0.140 |      0.137
   50th |      0.158 |      0.167 |      0.162
   75th |      0.200 |      0.210 |      0.205
   90th |      0.241 |      0.250 |      0.245
   95th |      0.264 |      0.274 |      0.269
   99th |      0.327 |      0.339 |      0.333
3-nines |      0.457 |      0.462 |      0.460
4-nines |      1.154 |      0.619 |      0.720
5-nines |      1.967 |      0.865 |      1.839
6-nines |      4.363 |      4.397 |      4.363
7-nines |     32.079 |     31.989 |     32.079
8-nines |     32.079 |     31.989 |     32.079
9-nines |     32.079 |     31.989 |     32.079
    max |     32.079 |     31.989 |     32.079

C:\WORK\DISKSPD>diskspd -t4 -o4 -b4k -si4k -w50 -d60 -Su -D -L \\172.16.200.2\TEST\IO20G.dat

Command Line: diskspd -t4 -o4 -b4k -si4k -w50 -d60 -Su -D -L \\172.16.200.2\TEST\IO20G.dat

Input parameters:

        timespan:   1
        -------------
        duration: 60s
        warm up time: 5s
        cool down time: 0s
        measuring latency
        gathering IOPS at intervals of 1000ms
        random seed: 0
        path: '\\172.16.200.2\TEST\IO20G.dat'
                think time: 0ms
                burst size: 0
                software cache disabled
                using hardware write cache, writethrough off
                performing mix test (read/write ratio: 50/50)
                block size: 4096
                using interlocked sequential I/O (stride: 4096)
                number of outstanding I/O operations: 4
                thread stride size: 0
                threads per file: 4
                using I/O Completion Ports
                IO priority: normal

System information:

        computer name: DESKTOP-DML65F5
        start time: 2023/02/28 08:43:49 UTC

Results for timespan 1:
*******************************************************************************

actual test time:       60.01s
thread count:           4
proc count:             24

CPU |  Usage |  User  |  Kernel |  Idle
-------------------------------------------
   0|  55.92%|   0.99%|   54.93%|  44.08%
   1|   0.03%|   0.00%|    0.03%|  99.97%
   2|   0.00%|   0.00%|    0.00%| 100.00%
   3|   0.03%|   0.00%|    0.03%|  99.97%
   4|   0.05%|   0.00%|    0.05%|  99.95%
   5|   0.00%|   0.00%|    0.00%| 100.00%
   6|   0.00%|   0.00%|    0.00%| 100.00%
   7|   0.00%|   0.00%|    0.00%| 100.00%
   8|   8.41%|   0.08%|    8.33%|  91.59%
   9|   0.13%|   0.00%|    0.13%|  99.87%
  10|   1.98%|   0.08%|    1.90%|  98.02%
  11|   0.00%|   0.00%|    0.00%| 100.00%
  12|   0.05%|   0.03%|    0.03%|  99.95%
  13|   0.05%|   0.05%|    0.00%|  99.95%
  14|   0.18%|   0.03%|    0.16%|  99.82%
  15|   0.00%|   0.00%|    0.00%| 100.00%
  16|   0.00%|   0.00%|    0.00%| 100.00%
  17|   0.00%|   0.00%|    0.00%| 100.00%
  18|   0.00%|   0.00%|    0.00%| 100.00%
  19|   0.00%|   0.00%|    0.00%| 100.00%
  20|   0.00%|   0.00%|    0.00%| 100.00%
  21|   0.00%|   0.00%|    0.00%| 100.00%
  22|   0.00%|   0.00%|    0.00%| 100.00%
  23|   0.00%|   0.00%|    0.00%| 100.00%
-------------------------------------------
avg.|   2.78%|   0.05%|    2.73%|  97.22%

Total IO
thread |       bytes     |     I/Os     |    MiB/s   |  I/O per s |  AvgLat  | IopsStdDev | LatStdDev |  file
------------------------------------------------------------------------------------------------------------------
     0 |      4131713024 |      1008719 |      65.66 |   16809.99 |    0.237 |     693.22 |     0.062 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     1 |      6080765952 |      1484562 |      96.64 |   24739.77 |    0.162 |     131.57 |     0.041 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     2 |      6129713152 |      1496512 |      97.42 |   24938.92 |    0.160 |     137.47 |     0.041 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     3 |      6131744768 |      1497008 |      97.45 |   24947.18 |    0.160 |     143.56 |     0.041 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
------------------------------------------------------------------------------------------------------------------
total:       22473936896 |      5486801 |     357.17 |   91435.86 |    0.175 |     460.51 |     0.054

Read IO
thread |       bytes     |     I/Os     |    MiB/s   |  I/O per s |  AvgLat  | IopsStdDev | LatStdDev |  file
------------------------------------------------------------------------------------------------------------------
     0 |      2065047552 |       504162 |      32.82 |    8401.71 |    0.234 |     350.05 |     0.062 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     1 |      3039363072 |       742032 |      48.30 |   12365.74 |    0.157 |     106.19 |     0.040 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     2 |      3064918016 |       748271 |      48.71 |   12469.71 |    0.156 |      92.78 |     0.041 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     3 |      3064307712 |       748122 |      48.70 |   12467.22 |    0.156 |     116.62 |     0.041 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
------------------------------------------------------------------------------------------------------------------
total:       11233636352 |      2742587 |     178.53 |   45704.38 |    0.171 |     263.34 |     0.054

Write IO
thread |       bytes     |     I/Os     |    MiB/s   |  I/O per s |  AvgLat  | IopsStdDev | LatStdDev |  file
------------------------------------------------------------------------------------------------------------------
     0 |      2066665472 |       504557 |      32.84 |    8408.29 |    0.239 |     353.22 |     0.062 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     1 |      3041402880 |       742530 |      48.34 |   12374.04 |    0.166 |     106.12 |     0.041 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     2 |      3064795136 |       748241 |      48.71 |   12469.21 |    0.164 |     105.33 |     0.042 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     3 |      3067437056 |       748886 |      48.75 |   12479.96 |    0.164 |     102.41 |     0.040 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
------------------------------------------------------------------------------------------------------------------
total:       11240300544 |      2744214 |     178.64 |   45731.49 |    0.178 |     270.53 |     0.054



total:
  %-ile |  Read (ms) | Write (ms) | Total (ms)
----------------------------------------------
    min |      0.073 |      0.078 |      0.073
   25th |      0.133 |      0.139 |      0.136
   50th |      0.157 |      0.165 |      0.161
   75th |      0.199 |      0.209 |      0.204
   90th |      0.241 |      0.250 |      0.245
   95th |      0.266 |      0.275 |      0.271
   99th |      0.331 |      0.342 |      0.337
3-nines |      0.466 |      0.472 |      0.470
4-nines |      1.165 |      0.637 |      0.752
5-nines |      2.085 |      0.997 |      1.973
6-nines |      4.485 |      4.493 |      4.491
7-nines |      8.364 |      8.395 |      8.395
8-nines |      8.364 |      8.395 |      8.395
9-nines |      8.364 |      8.395 |      8.395
    max |      8.364 |      8.395 |      8.395

C:\WORK\DISKSPD>diskspd -t4 -o4 -b4k -si4k -w50 -d60 -Su -D -L \\172.16.200.2\TEST\IO20G.dat

Command Line: diskspd -t4 -o4 -b4k -si4k -w50 -d60 -Su -D -L \\172.16.200.2\TEST\IO20G.dat

Input parameters:

        timespan:   1
        -------------
        duration: 60s
        warm up time: 5s
        cool down time: 0s
        measuring latency
        gathering IOPS at intervals of 1000ms
        random seed: 0
        path: '\\172.16.200.2\TEST\IO20G.dat'
                think time: 0ms
                burst size: 0
                software cache disabled
                using hardware write cache, writethrough off
                performing mix test (read/write ratio: 50/50)
                block size: 4096
                using interlocked sequential I/O (stride: 4096)
                number of outstanding I/O operations: 4
                thread stride size: 0
                threads per file: 4
                using I/O Completion Ports
                IO priority: normal

System information:

        computer name: DESKTOP-DML65F5
        start time: 2023/02/28 08:45:07 UTC

Results for timespan 1:
*******************************************************************************

actual test time:       60.01s
thread count:           4
proc count:             24

CPU |  Usage |  User  |  Kernel |  Idle
-------------------------------------------
   0|  30.70%|   0.44%|   30.25%|  69.30%
   1|   0.08%|   0.00%|    0.08%|  99.92%
   2|   0.29%|   0.00%|    0.29%|  99.71%
   3|   0.00%|   0.00%|    0.00%| 100.00%
   4|   0.03%|   0.00%|    0.03%|  99.97%
   5|   0.00%|   0.00%|    0.00%| 100.00%
   6|   0.00%|   0.00%|    0.00%| 100.00%
   7|   0.00%|   0.00%|    0.00%| 100.00%
   8|  14.66%|   0.31%|   14.35%|  85.34%
   9|   0.00%|   0.00%|    0.00%| 100.00%
  10|   0.60%|   0.03%|    0.57%|  99.40%
  11|   0.81%|   0.00%|    0.81%|  99.19%
  12|   0.00%|   0.00%|    0.00%| 100.00%
  13|   0.00%|   0.00%|    0.00%| 100.00%
  14|   0.05%|   0.00%|    0.05%|  99.95%
  15|   0.08%|   0.00%|    0.08%|  99.92%
  16|   0.00%|   0.00%|    0.00%| 100.00%
  17|   0.03%|   0.03%|    0.00%|  99.97%
  18|   0.00%|   0.00%|    0.00%| 100.00%
  19|   0.00%|   0.00%|    0.00%| 100.00%
  20|   0.00%|   0.00%|    0.00%| 100.00%
  21|   0.00%|   0.00%|    0.00%| 100.00%
  22|   0.00%|   0.00%|    0.00%| 100.00%
  23|   0.03%|   0.00%|    0.03%|  99.97%
-------------------------------------------
avg.|   1.97%|   0.03%|    1.94%|  98.03%

Total IO
thread |       bytes     |     I/Os     |    MiB/s   |  I/O per s |  AvgLat  | IopsStdDev | LatStdDev |  file
------------------------------------------------------------------------------------------------------------------
     0 |      4319358976 |      1054531 |      68.64 |   17571.17 |    0.226 |      83.04 |     0.054 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     1 |      6032429056 |      1472761 |      95.86 |   24539.95 |    0.163 |     118.13 |     0.041 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     2 |      6066360320 |      1481045 |      96.40 |   24677.98 |    0.162 |     128.64 |     0.060 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     3 |      6079508480 |      1484255 |      96.61 |   24731.47 |    0.162 |     108.63 |     0.041 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
------------------------------------------------------------------------------------------------------------------
total:       22497656832 |      5492592 |     357.50 |   91520.58 |    0.174 |     374.12 |     0.056

Read IO
thread |       bytes     |     I/Os     |    MiB/s   |  I/O per s |  AvgLat  | IopsStdDev | LatStdDev |  file
------------------------------------------------------------------------------------------------------------------
     0 |      2159009792 |       527102 |      34.31 |    8782.86 |    0.224 |      73.83 |     0.056 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     1 |      3014975488 |       736078 |      47.91 |   12264.94 |    0.158 |     100.27 |     0.040 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     2 |      3033477120 |       740595 |      48.20 |   12340.20 |    0.158 |      99.11 |     0.057 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     3 |      3038384128 |       741793 |      48.28 |   12360.16 |    0.157 |      88.85 |     0.041 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
------------------------------------------------------------------------------------------------------------------
total:       11245846528 |      2745568 |     178.70 |   45748.16 |    0.171 |     235.14 |     0.055

Write IO
thread |       bytes     |     I/Os     |    MiB/s   |  I/O per s |  AvgLat  | IopsStdDev | LatStdDev |  file
------------------------------------------------------------------------------------------------------------------
     0 |      2160349184 |       527429 |      34.33 |    8788.31 |    0.228 |      69.80 |     0.053 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     1 |      3017453568 |       736683 |      47.95 |   12275.02 |    0.167 |      92.02 |     0.041 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     2 |      3032883200 |       740450 |      48.19 |   12337.78 |    0.166 |      93.23 |     0.063 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     3 |      3041124352 |       742462 |      48.33 |   12371.31 |    0.166 |      89.51 |     0.041 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
------------------------------------------------------------------------------------------------------------------
total:       11251810304 |      2747024 |     178.80 |   45772.42 |    0.178 |     223.92 |     0.056



total:
  %-ile |  Read (ms) | Write (ms) | Total (ms)
----------------------------------------------
    min |      0.075 |      0.077 |      0.075
   25th |      0.134 |      0.140 |      0.137
   50th |      0.159 |      0.168 |      0.163
   75th |      0.200 |      0.210 |      0.205
   90th |      0.238 |      0.247 |      0.243
   95th |      0.259 |      0.267 |      0.263
   99th |      0.305 |      0.314 |      0.310
3-nines |      0.396 |      0.400 |      0.398
4-nines |      1.222 |      0.585 |      0.764
5-nines |      3.639 |      1.914 |      2.800
6-nines |     15.174 |     16.070 |     15.176
7-nines |     15.176 |     16.083 |     16.083
8-nines |     15.176 |     16.083 |     16.083
9-nines |     15.176 |     16.083 |     16.083
    max |     15.176 |     16.083 |     16.083

C:\WORK\DISKSPD>diskspd -t4 -o4 -b4k -si4k -w50 -d60 -Su -D -L \\172.16.200.2\TEST\IO20G.dat

Command Line: diskspd -t4 -o4 -b4k -si4k -w50 -d60 -Su -D -L \\172.16.200.2\TEST\IO20G.dat

Input parameters:

        timespan:   1
        -------------
        duration: 60s
        warm up time: 5s
        cool down time: 0s
        measuring latency
        gathering IOPS at intervals of 1000ms
        random seed: 0
        path: '\\172.16.200.2\TEST\IO20G.dat'
                think time: 0ms
                burst size: 0
                software cache disabled
                using hardware write cache, writethrough off
                performing mix test (read/write ratio: 50/50)
                block size: 4096
                using interlocked sequential I/O (stride: 4096)
                number of outstanding I/O operations: 4
                thread stride size: 0
                threads per file: 4
                using I/O Completion Ports
                IO priority: normal

System information:

        computer name: DESKTOP-DML65F5
        start time: 2023/02/28 08:47:07 UTC

Results for timespan 1:
*******************************************************************************

actual test time:       60.01s
thread count:           4
proc count:             24

CPU |  Usage |  User  |  Kernel |  Idle
-------------------------------------------
   0|  25.18%|   0.42%|   24.77%|  74.82%
   1|   0.05%|   0.03%|    0.03%|  99.95%
   2|   0.05%|   0.00%|    0.05%|  99.95%
   3|   8.93%|   0.55%|    8.39%|  91.07%
   4|   4.87%|   0.13%|    4.74%|  95.13%
   5|   0.00%|   0.00%|    0.00%| 100.00%
   6|   0.10%|   0.05%|    0.05%|  99.90%
   7|   0.00%|   0.00%|    0.00%| 100.00%
   8|   7.14%|   0.44%|    6.69%|  92.86%
   9|   0.03%|   0.03%|    0.00%|  99.97%
  10|   0.65%|   0.00%|    0.65%|  99.35%
  11|   0.31%|   0.05%|    0.26%|  99.69%
  12|   0.10%|   0.08%|    0.03%|  99.90%
  13|   0.00%|   0.00%|    0.00%| 100.00%
  14|   0.03%|   0.00%|    0.03%|  99.97%
  15|   0.00%|   0.00%|    0.00%| 100.00%
  16|   0.03%|   0.03%|    0.00%|  99.97%
  17|   0.00%|   0.00%|    0.00%| 100.00%
  18|   0.00%|   0.00%|    0.00%| 100.00%
  19|   0.05%|   0.05%|    0.00%|  99.95%
  20|   0.03%|   0.00%|    0.03%|  99.97%
  21|   0.03%|   0.00%|    0.03%|  99.97%
  22|   0.00%|   0.00%|    0.00%| 100.00%
  23|   0.00%|   0.00%|    0.00%| 100.00%
-------------------------------------------
avg.|   1.98%|   0.08%|    1.91%|  98.02%

Total IO
thread |       bytes     |     I/Os     |    MiB/s   |  I/O per s |  AvgLat  | IopsStdDev | LatStdDev |  file
------------------------------------------------------------------------------------------------------------------
     0 |      4579344384 |      1118004 |      72.78 |   18631.62 |    0.213 |    2489.94 |     0.084 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     1 |      6001967104 |      1465324 |      95.39 |   24419.73 |    0.164 |     216.17 |     0.043 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     2 |      6032605184 |      1472804 |      95.88 |   24544.39 |    0.163 |     175.27 |     0.045 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     3 |      5989396480 |      1462255 |      95.19 |   24368.59 |    0.164 |     665.55 |     0.054 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
------------------------------------------------------------------------------------------------------------------
total:       22603313152 |      5518387 |     359.24 |   91964.32 |    0.174 |    2793.47 |     0.060

Read IO
thread |       bytes     |     I/Os     |    MiB/s   |  I/O per s |  AvgLat  | IopsStdDev | LatStdDev |  file
------------------------------------------------------------------------------------------------------------------
     0 |      2289668096 |       559001 |      36.39 |    9315.79 |    0.211 |    1253.82 |     0.093 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     1 |      2999676928 |       732343 |      47.67 |   12204.55 |    0.159 |     133.04 |     0.042 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     2 |      3016650752 |       736487 |      47.94 |   12273.61 |    0.159 |     105.56 |     0.045 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     3 |      2993287168 |       730783 |      47.57 |   12178.55 |    0.160 |     335.84 |     0.052 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
------------------------------------------------------------------------------------------------------------------
total:       11299282944 |      2758614 |     179.58 |   45972.50 |    0.170 |    1418.83 |     0.063

Write IO
thread |       bytes     |     I/Os     |    MiB/s   |  I/O per s |  AvgLat  | IopsStdDev | LatStdDev |  file
------------------------------------------------------------------------------------------------------------------
     0 |      2289676288 |       559003 |      36.39 |    9315.83 |    0.216 |    1239.42 |     0.075 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     1 |      3002290176 |       732981 |      47.72 |   12215.18 |    0.168 |     128.88 |     0.043 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     2 |      3015954432 |       736317 |      47.93 |   12270.78 |    0.167 |     114.19 |     0.045 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     3 |      2996109312 |       731472 |      47.62 |   12190.03 |    0.168 |     347.91 |     0.055 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
------------------------------------------------------------------------------------------------------------------
total:       11304030208 |      2759773 |     179.66 |   45991.82 |    0.177 |    1390.23 |     0.058



total:
  %-ile |  Read (ms) | Write (ms) | Total (ms)
----------------------------------------------
    min |      0.073 |      0.079 |      0.073
   25th |      0.135 |      0.141 |      0.138
   50th |      0.159 |      0.168 |      0.163
   75th |      0.197 |      0.207 |      0.202
   90th |      0.234 |      0.243 |      0.239
   95th |      0.255 |      0.263 |      0.259
   99th |      0.300 |      0.309 |      0.305
3-nines |      0.398 |      0.398 |      0.398
4-nines |      1.525 |      0.755 |      1.252
5-nines |      4.409 |      4.439 |      4.417
6-nines |     30.228 |      9.142 |      9.362
7-nines |     30.408 |     30.480 |     30.480
8-nines |     30.408 |     30.480 |     30.480
9-nines |     30.408 |     30.480 |     30.480
    max |     30.408 |     30.480 |     30.480

C:\WORK\DISKSPD>diskspd -t4 -o4 -b4k -si4k -w50 -d60 -Su -D -L \\172.16.200.2\TEST\IO20G.dat

Command Line: diskspd -t4 -o4 -b4k -si4k -w50 -d60 -Su -D -L \\172.16.200.2\TEST\IO20G.dat

Input parameters:

        timespan:   1
        -------------
        duration: 60s
        warm up time: 5s
        cool down time: 0s
        measuring latency
        gathering IOPS at intervals of 1000ms
        random seed: 0
        path: '\\172.16.200.2\TEST\IO20G.dat'
                think time: 0ms
                burst size: 0
                software cache disabled
                using hardware write cache, writethrough off
                performing mix test (read/write ratio: 50/50)
                block size: 4096
                using interlocked sequential I/O (stride: 4096)
                number of outstanding I/O operations: 4
                thread stride size: 0
                threads per file: 4
                using I/O Completion Ports
                IO priority: normal

System information:

        computer name: DESKTOP-DML65F5
        start time: 2023/02/28 08:48:15 UTC

Results for timespan 1:
*******************************************************************************

actual test time:       60.01s
thread count:           4
proc count:             24

CPU |  Usage |  User  |  Kernel |  Idle
-------------------------------------------
   0|  14.94%|   0.23%|   14.71%|  85.06%
   1|   0.05%|   0.00%|    0.05%|  99.95%
   2|   0.05%|   0.00%|    0.05%|  99.95%
   3|  37.98%|   0.47%|   37.52%|  62.02%
   4|   0.10%|   0.00%|    0.10%|  99.90%
   5|   0.13%|   0.03%|    0.10%|  99.87%
   6|   0.18%|   0.03%|    0.16%|  99.82%
   7|   0.00%|   0.00%|    0.00%| 100.00%
   8|   7.47%|   0.18%|    7.29%|  92.53%
   9|   1.02%|   0.08%|    0.94%|  98.98%
  10|   1.59%|   0.03%|    1.56%|  98.41%
  11|   0.00%|   0.00%|    0.00%| 100.00%
  12|   0.73%|   0.05%|    0.68%|  99.27%
  13|   0.00%|   0.00%|    0.00%| 100.00%
  14|   0.00%|   0.00%|    0.00%| 100.00%
  15|   0.00%|   0.00%|    0.00%| 100.00%
  16|   0.00%|   0.00%|    0.00%| 100.00%
  17|   0.00%|   0.00%|    0.00%| 100.00%
  18|   0.00%|   0.00%|    0.00%| 100.00%
  19|   0.03%|   0.00%|    0.03%|  99.97%
  20|   0.03%|   0.00%|    0.03%|  99.97%
  21|   0.03%|   0.03%|    0.00%|  99.97%
  22|   0.03%|   0.03%|    0.00%|  99.97%
  23|   0.05%|   0.03%|    0.03%|  99.95%
-------------------------------------------
avg.|   2.68%|   0.05%|    2.63%|  97.32%

Total IO
thread |       bytes     |     I/Os     |    MiB/s   |  I/O per s |  AvgLat  | IopsStdDev | LatStdDev |  file
------------------------------------------------------------------------------------------------------------------
     0 |      5629652992 |      1374427 |      89.47 |   22903.15 |    0.174 |    3453.96 |     0.066 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     1 |      6059749376 |      1479431 |      96.30 |   24652.91 |    0.162 |     164.92 |     0.046 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     2 |      6035419136 |      1473491 |      95.91 |   24553.93 |    0.163 |     155.06 |     0.044 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     3 |      4568190976 |      1115281 |      72.60 |   18584.80 |    0.214 |    3170.88 |     0.080 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
------------------------------------------------------------------------------------------------------------------
total:       22293012480 |      5442630 |     354.28 |   90694.79 |    0.176 |     597.33 |     0.062

Read IO
thread |       bytes     |     I/Os     |    MiB/s   |  I/O per s |  AvgLat  | IopsStdDev | LatStdDev |  file
------------------------------------------------------------------------------------------------------------------
     0 |      2813476864 |       686884 |      44.71 |   11446.08 |    0.170 |    1732.72 |     0.064 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     1 |      3028701184 |       739429 |      48.13 |   12321.68 |    0.158 |     111.15 |     0.045 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     2 |      3017973760 |       736810 |      47.96 |   12278.04 |    0.158 |     106.10 |     0.044 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     3 |      2282323968 |       557208 |      36.27 |    9285.19 |    0.211 |    1597.70 |     0.079 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
------------------------------------------------------------------------------------------------------------------
total:       11142475776 |      2720331 |     177.07 |   45331.00 |    0.172 |     312.24 |     0.062

Write IO
thread |       bytes     |     I/Os     |    MiB/s   |  I/O per s |  AvgLat  | IopsStdDev | LatStdDev |  file
------------------------------------------------------------------------------------------------------------------
     0 |      2816176128 |       687543 |      44.75 |   11457.07 |    0.178 |    1723.66 |     0.067 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     1 |      3031048192 |       740002 |      48.17 |   12331.23 |    0.166 |     118.75 |     0.045 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     2 |      3017445376 |       736681 |      47.95 |   12275.89 |    0.167 |     105.68 |     0.043 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     3 |      2285867008 |       558073 |      36.33 |    9299.61 |    0.217 |    1576.08 |     0.081 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
------------------------------------------------------------------------------------------------------------------
total:       11150536704 |      2722299 |     177.20 |   45363.79 |    0.180 |     355.66 |     0.063



total:
  %-ile |  Read (ms) | Write (ms) | Total (ms)
----------------------------------------------
    min |      0.075 |      0.076 |      0.075
   25th |      0.134 |      0.140 |      0.137
   50th |      0.158 |      0.167 |      0.162
   75th |      0.200 |      0.211 |      0.206
   90th |      0.242 |      0.251 |      0.247
   95th |      0.266 |      0.275 |      0.271
   99th |      0.330 |      0.342 |      0.337
3-nines |      0.474 |      0.475 |      0.475
4-nines |      1.513 |      0.730 |      1.253
5-nines |      4.213 |      4.429 |      4.332
6-nines |     13.816 |     13.754 |     13.754
7-nines |     16.045 |     16.068 |     16.068
8-nines |     16.045 |     16.068 |     16.068
9-nines |     16.045 |     16.068 |     16.068
    max |     16.045 |     16.068 |     16.068

C:\WORK\DISKSPD>

W11 22H2 DCTCP TO W11 22H2 DCTCP:

C:\WORK\DISKSPD>diskspd -t4 -o4 -b4k -si4k -w50 -d60 -Su -D -L \\172.16.200.2\TEST\IO20G.dat

Command Line: diskspd -t4 -o4 -b4k -si4k -w50 -d60 -Su -D -L \\172.16.200.2\TEST\IO20G.dat

Input parameters:

        timespan:   1
        -------------
        duration: 60s
        warm up time: 5s
        cool down time: 0s
        measuring latency
        gathering IOPS at intervals of 1000ms
        random seed: 0
        path: '\\172.16.200.2\TEST\IO20G.dat'
                think time: 0ms
                burst size: 0
                software cache disabled
                using hardware write cache, writethrough off
                performing mix test (read/write ratio: 50/50)
                block size: 4096
                using interlocked sequential I/O (stride: 4096)
                number of outstanding I/O operations: 4
                thread stride size: 0
                threads per file: 4
                using I/O Completion Ports
                IO priority: normal

System information:

        computer name: DESKTOP-DML65F5
        start time: 2023/02/28 08:53:51 UTC

Results for timespan 1:
*******************************************************************************

actual test time:       60.01s
thread count:           4
proc count:             24

CPU |  Usage |  User  |  Kernel |  Idle
-------------------------------------------
   0|  20.93%|   0.21%|   20.72%|  79.07%
   1|   0.03%|   0.00%|    0.03%|  99.97%
   2|   0.08%|   0.05%|    0.03%|  99.92%
   3|  17.10%|   0.62%|   16.48%|  82.90%
   4|  11.87%|   0.36%|   11.51%|  88.13%
   5|   0.00%|   0.00%|    0.00%| 100.00%
   6|   0.18%|   0.05%|    0.13%|  99.82%
   7|   0.00%|   0.00%|    0.00%| 100.00%
   8|   4.17%|   0.47%|    3.70%|  95.83%
   9|   0.03%|   0.00%|    0.03%|  99.97%
  10|   1.64%|   0.10%|    1.54%|  98.36%
  11|   1.46%|   0.10%|    1.35%|  98.54%
  12|   0.18%|   0.05%|    0.13%|  99.82%
  13|   0.00%|   0.00%|    0.00%| 100.00%
  14|   0.10%|   0.03%|    0.08%|  99.90%
  15|   0.03%|   0.03%|    0.00%|  99.97%
  16|   0.21%|   0.08%|    0.13%|  99.79%
  17|   0.00%|   0.00%|    0.00%| 100.00%
  18|   0.00%|   0.00%|    0.00%| 100.00%
  19|   0.36%|   0.36%|    0.00%|  99.64%
  20|   0.52%|   0.29%|    0.23%|  99.48%
  21|   0.44%|   0.31%|    0.13%|  99.56%
  22|   0.08%|   0.08%|    0.00%|  99.92%
  23|   0.00%|   0.00%|    0.00%| 100.00%
-------------------------------------------
avg.|   2.48%|   0.13%|    2.34%|  97.52%

Total IO
thread |       bytes     |     I/Os     |    MiB/s   |  I/O per s |  AvgLat  | IopsStdDev | LatStdDev |  file
------------------------------------------------------------------------------------------------------------------
     0 |      5661138944 |      1382114 |      89.96 |   23029.69 |    0.173 |    5340.38 |     0.083 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     1 |      6885642240 |      1681065 |     109.42 |   28011.01 |    0.143 |     348.99 |     0.034 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     2 |      6885363712 |      1680997 |     109.41 |   28009.88 |    0.143 |     423.53 |     0.049 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     3 |      6074753024 |      1483094 |      96.53 |   24712.29 |    0.161 |    4847.09 |     0.058 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
------------------------------------------------------------------------------------------------------------------
total:       25506897920 |      6227270 |     405.32 |  103762.86 |    0.154 |    4956.58 |     0.059

Read IO
thread |       bytes     |     I/Os     |    MiB/s   |  I/O per s |  AvgLat  | IopsStdDev | LatStdDev |  file
------------------------------------------------------------------------------------------------------------------
     0 |      2829123584 |       690704 |      44.96 |   11508.96 |    0.171 |    2674.09 |     0.084 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     1 |      3440775168 |       840033 |      54.68 |   13997.18 |    0.141 |     190.49 |     0.036 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     2 |      3441770496 |       840276 |      54.69 |   14001.23 |    0.141 |     205.67 |     0.056 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     3 |      3035840512 |       741172 |      48.24 |   12349.89 |    0.159 |    2424.25 |     0.059 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
------------------------------------------------------------------------------------------------------------------
total:       12747509760 |      3112185 |     202.57 |   51857.27 |    0.152 |    2463.00 |     0.061

Write IO
thread |       bytes     |     I/Os     |    MiB/s   |  I/O per s |  AvgLat  | IopsStdDev | LatStdDev |  file
------------------------------------------------------------------------------------------------------------------
     0 |      2832015360 |       691410 |      45.00 |   11520.73 |    0.174 |    2668.25 |     0.083 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     1 |      3444867072 |       841032 |      54.74 |   14013.83 |    0.144 |     202.63 |     0.032 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     2 |      3443593216 |       840721 |      54.72 |   14008.65 |    0.144 |     241.76 |     0.042 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     3 |      3038912512 |       741922 |      48.29 |   12362.39 |    0.163 |    2425.39 |     0.057 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
------------------------------------------------------------------------------------------------------------------
total:       12759388160 |      3115085 |     202.76 |   51905.59 |    0.156 |    2504.21 |     0.057



total:
  %-ile |  Read (ms) | Write (ms) | Total (ms)
----------------------------------------------
    min |      0.072 |      0.071 |      0.071
   25th |      0.124 |      0.127 |      0.125
   50th |      0.138 |      0.142 |      0.140
   75th |      0.164 |      0.169 |      0.167
   90th |      0.209 |      0.213 |      0.211
   95th |      0.238 |      0.244 |      0.241
   99th |      0.313 |      0.324 |      0.319
3-nines |      0.478 |      0.474 |      0.475
4-nines |      1.927 |      0.978 |      1.631
5-nines |      4.537 |      4.379 |      4.517
6-nines |     13.499 |     12.917 |     13.498
7-nines |     16.885 |     16.876 |     16.885
8-nines |     16.885 |     16.876 |     16.885
9-nines |     16.885 |     16.876 |     16.885
    max |     16.885 |     16.876 |     16.885

C:\WORK\DISKSPD>diskspd -t4 -o4 -b4k -si4k -w50 -d60 -Su -D -L \\172.16.200.2\TEST\IO20G.dat

Command Line: diskspd -t4 -o4 -b4k -si4k -w50 -d60 -Su -D -L \\172.16.200.2\TEST\IO20G.dat

Input parameters:

        timespan:   1
        -------------
        duration: 60s
        warm up time: 5s
        cool down time: 0s
        measuring latency
        gathering IOPS at intervals of 1000ms
        random seed: 0
        path: '\\172.16.200.2\TEST\IO20G.dat'
                think time: 0ms
                burst size: 0
                software cache disabled
                using hardware write cache, writethrough off
                performing mix test (read/write ratio: 50/50)
                block size: 4096
                using interlocked sequential I/O (stride: 4096)
                number of outstanding I/O operations: 4
                thread stride size: 0
                threads per file: 4
                using I/O Completion Ports
                IO priority: normal

System information:

        computer name: DESKTOP-DML65F5
        start time: 2023/02/28 08:55:35 UTC

Results for timespan 1:
*******************************************************************************

actual test time:       60.01s
thread count:           4
proc count:             24

CPU |  Usage |  User  |  Kernel |  Idle
-------------------------------------------
   0|  32.45%|   0.42%|   32.03%|  67.55%
   1|   0.16%|   0.00%|    0.16%|  99.84%
   2|   0.05%|   0.00%|    0.05%|  99.95%
   3|   0.00%|   0.00%|    0.00%| 100.00%
   4|   0.05%|   0.03%|    0.03%|  99.95%
   5|   0.00%|   0.00%|    0.00%| 100.00%
   6|   0.03%|   0.03%|    0.00%|  99.97%
   7|   8.62%|   0.10%|    8.52%|  91.38%
   8|   9.53%|   0.21%|    9.32%|  90.47%
   9|   0.03%|   0.03%|    0.00%|  99.97%
  10|   0.65%|   0.05%|    0.60%|  99.35%
  11|   2.66%|   0.08%|    2.58%|  97.34%
  12|   0.75%|   0.10%|    0.65%|  99.25%
  13|   0.03%|   0.00%|    0.03%|  99.97%
  14|   0.26%|   0.03%|    0.23%|  99.74%
  15|   0.00%|   0.00%|    0.00%| 100.00%
  16|   0.03%|   0.00%|    0.03%|  99.97%
  17|   0.03%|   0.03%|    0.00%|  99.97%
  18|   0.00%|   0.00%|    0.00%| 100.00%
  19|   0.00%|   0.00%|    0.00%| 100.00%
  20|   0.00%|   0.00%|    0.00%| 100.00%
  21|   0.00%|   0.00%|    0.00%| 100.00%
  22|   0.00%|   0.00%|    0.00%| 100.00%
  23|   0.00%|   0.00%|    0.00%| 100.00%
-------------------------------------------
avg.|   2.30%|   0.05%|    2.26%|  97.70%

Total IO
thread |       bytes     |     I/Os     |    MiB/s   |  I/O per s |  AvgLat  | IopsStdDev | LatStdDev |  file
------------------------------------------------------------------------------------------------------------------
     0 |      5129240576 |      1252256 |      81.51 |   20867.05 |    0.190 |    4434.02 |     0.069 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     1 |      6835412992 |      1668802 |     108.63 |   27808.19 |    0.144 |     683.33 |     0.042 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     2 |      6883233792 |      1680477 |     109.39 |   28002.74 |    0.143 |     635.08 |     0.033 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     3 |      6888792064 |      1681834 |     109.47 |   28025.35 |    0.143 |     613.58 |     0.032 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
------------------------------------------------------------------------------------------------------------------
total:       25736679424 |      6283369 |     409.00 |  104703.32 |    0.152 |    4838.65 |     0.048

Read IO
thread |       bytes     |     I/Os     |    MiB/s   |  I/O per s |  AvgLat  | IopsStdDev | LatStdDev |  file
------------------------------------------------------------------------------------------------------------------
     0 |      2563051520 |       625745 |      40.73 |   10427.14 |    0.189 |    2218.33 |     0.068 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     1 |      3415699456 |       833911 |      54.28 |   13895.93 |    0.142 |     367.64 |     0.044 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     2 |      3440832512 |       840047 |      54.68 |   13998.18 |    0.141 |     327.75 |     0.035 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     3 |      3442528256 |       840461 |      54.71 |   14005.08 |    0.141 |     315.53 |     0.034 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
------------------------------------------------------------------------------------------------------------------
total:       12862111744 |      3140164 |     204.40 |   52326.33 |    0.151 |    2437.74 |     0.049

Write IO
thread |       bytes     |     I/Os     |    MiB/s   |  I/O per s |  AvgLat  | IopsStdDev | LatStdDev |  file
------------------------------------------------------------------------------------------------------------------
     0 |      2566189056 |       626511 |      40.78 |   10439.91 |    0.192 |    2218.18 |     0.070 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     1 |      3419713536 |       834891 |      54.34 |   13912.26 |    0.146 |     334.17 |     0.039 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     2 |      3442401280 |       840430 |      54.71 |   14004.56 |    0.144 |     323.20 |     0.031 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     3 |      3446263808 |       841373 |      54.77 |   14020.27 |    0.144 |     325.16 |     0.030 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
------------------------------------------------------------------------------------------------------------------
total:       12874567680 |      3143205 |     204.60 |   52377.00 |    0.154 |    2412.91 |     0.047



total:
  %-ile |  Read (ms) | Write (ms) | Total (ms)
----------------------------------------------
    min |      0.073 |      0.073 |      0.073
   25th |      0.124 |      0.127 |      0.126
   50th |      0.139 |      0.143 |      0.141
   75th |      0.163 |      0.168 |      0.166
   90th |      0.203 |      0.207 |      0.205
   95th |      0.230 |      0.235 |      0.233
   99th |      0.298 |      0.306 |      0.302
3-nines |      0.418 |      0.421 |      0.420
4-nines |      1.633 |      0.712 |      1.047
5-nines |      2.555 |      2.051 |      2.446
6-nines |      6.546 |     16.087 |     16.087
7-nines |     16.127 |     16.198 |     16.198
8-nines |     16.127 |     16.198 |     16.198
9-nines |     16.127 |     16.198 |     16.198
    max |     16.127 |     16.198 |     16.198

C:\WORK\DISKSPD>diskspd -t4 -o4 -b4k -si4k -w50 -d60 -Su -D -L \\172.16.200.2\TEST\IO20G.dat

Command Line: diskspd -t4 -o4 -b4k -si4k -w50 -d60 -Su -D -L \\172.16.200.2\TEST\IO20G.dat

Input parameters:

        timespan:   1
        -------------
        duration: 60s
        warm up time: 5s
        cool down time: 0s
        measuring latency
        gathering IOPS at intervals of 1000ms
        random seed: 0
        path: '\\172.16.200.2\TEST\IO20G.dat'
                think time: 0ms
                burst size: 0
                software cache disabled
                using hardware write cache, writethrough off
                performing mix test (read/write ratio: 50/50)
                block size: 4096
                using interlocked sequential I/O (stride: 4096)
                number of outstanding I/O operations: 4
                thread stride size: 0
                threads per file: 4
                using I/O Completion Ports
                IO priority: normal

System information:

        computer name: DESKTOP-DML65F5
        start time: 2023/02/28 08:58:43 UTC

Results for timespan 1:
*******************************************************************************

actual test time:       60.01s
thread count:           4
proc count:             24

CPU |  Usage |  User  |  Kernel |  Idle
-------------------------------------------
   0|  95.81%|   1.43%|   94.38%|   4.19%
   1|   0.08%|   0.00%|    0.08%|  99.92%
   2|   0.21%|   0.03%|    0.18%|  99.79%
   3|   0.03%|   0.03%|    0.00%|  99.97%
   4|   0.26%|   0.00%|    0.26%|  99.74%
   5|   0.00%|   0.00%|    0.00%| 100.00%
   6|   0.10%|   0.03%|    0.08%|  99.90%
   7|   0.00%|   0.00%|    0.00%| 100.00%
   8|   0.83%|   0.00%|    0.83%|  99.17%
   9|   0.44%|   0.00%|    0.44%|  99.56%
  10|   1.33%|   0.05%|    1.28%|  98.67%
  11|   0.00%|   0.00%|    0.00%| 100.00%
  12|   0.03%|   0.00%|    0.03%|  99.97%
  13|   0.00%|   0.00%|    0.00%| 100.00%
  14|   0.00%|   0.00%|    0.00%| 100.00%
  15|   0.05%|   0.05%|    0.00%|  99.95%
  16|   0.05%|   0.03%|    0.03%|  99.95%
  17|   0.00%|   0.00%|    0.00%| 100.00%
  18|   0.00%|   0.00%|    0.00%| 100.00%
  19|   0.00%|   0.00%|    0.00%| 100.00%
  20|   0.00%|   0.00%|    0.00%| 100.00%
  21|   0.03%|   0.03%|    0.00%|  99.97%
  22|   0.00%|   0.00%|    0.00%| 100.00%
  23|   0.03%|   0.00%|    0.03%|  99.97%
-------------------------------------------
avg.|   4.14%|   0.07%|    4.07%|  95.86%

Total IO
thread |       bytes     |     I/Os     |    MiB/s   |  I/O per s |  AvgLat  | IopsStdDev | LatStdDev |  file
------------------------------------------------------------------------------------------------------------------
     0 |      6066294784 |      1481029 |      96.41 |   24680.64 |    0.162 |     168.96 |     0.035 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     1 |      6240366592 |      1523527 |      99.18 |   25388.84 |    0.157 |     177.88 |     0.037 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     2 |      6323081216 |      1543721 |     100.49 |   25725.37 |    0.155 |     253.51 |     0.081 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     3 |      6341287936 |      1548166 |     100.78 |   25799.44 |    0.155 |     188.30 |     0.036 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
------------------------------------------------------------------------------------------------------------------
total:       24971030528 |      6096443 |     396.85 |  101594.29 |    0.157 |     750.72 |     0.051

Read IO
thread |       bytes     |     I/Os     |    MiB/s   |  I/O per s |  AvgLat  | IopsStdDev | LatStdDev |  file
------------------------------------------------------------------------------------------------------------------
     0 |      3031392256 |       740086 |      48.18 |   12333.18 |    0.161 |     106.44 |     0.037 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     1 |      3119747072 |       761657 |      49.58 |   12692.65 |    0.157 |     107.76 |     0.040 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     2 |      3161079808 |       771748 |      50.24 |   12860.81 |    0.155 |     138.82 |     0.076 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     3 |      3168501760 |       773560 |      50.36 |   12891.01 |    0.154 |     120.64 |     0.038 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
------------------------------------------------------------------------------------------------------------------
total:       12480720896 |      3047051 |     198.35 |   50777.64 |    0.157 |     359.10 |     0.051

Write IO
thread |       bytes     |     I/Os     |    MiB/s   |  I/O per s |  AvgLat  | IopsStdDev | LatStdDev |  file
------------------------------------------------------------------------------------------------------------------
     0 |      3034902528 |       740943 |      48.23 |   12347.46 |    0.163 |     105.77 |     0.033 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     1 |      3120619520 |       761870 |      49.59 |   12696.20 |    0.158 |     131.83 |     0.034 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     2 |      3162001408 |       771973 |      50.25 |   12864.56 |    0.156 |     147.01 |     0.085 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     3 |      3172786176 |       774606 |      50.42 |   12908.44 |    0.156 |     137.46 |     0.033 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
------------------------------------------------------------------------------------------------------------------
total:       12490309632 |      3049392 |     198.50 |   50816.65 |    0.158 |     436.95 |     0.052



total:
  %-ile |  Read (ms) | Write (ms) | Total (ms)
----------------------------------------------
    min |      0.068 |      0.074 |      0.068
   25th |      0.142 |      0.144 |      0.143
   50th |      0.153 |      0.155 |      0.154
   75th |      0.167 |      0.168 |      0.168
   90th |      0.179 |      0.181 |      0.181
   95th |      0.189 |      0.191 |      0.190
   99th |      0.221 |      0.222 |      0.222
3-nines |      0.385 |      0.349 |      0.363
4-nines |      2.023 |      1.778 |      1.913
5-nines |      4.130 |      4.559 |      4.295
6-nines |     16.145 |     16.086 |     16.119
7-nines |     27.231 |     27.136 |     27.231
8-nines |     27.231 |     27.136 |     27.231
9-nines |     27.231 |     27.136 |     27.231
    max |     27.231 |     27.136 |     27.231

C:\WORK\DISKSPD>diskspd -t4 -o4 -b4k -si4k -w50 -d60 -Su -D -L \\172.16.200.2\TEST\IO20G.dat

Command Line: diskspd -t4 -o4 -b4k -si4k -w50 -d60 -Su -D -L \\172.16.200.2\TEST\IO20G.dat

Input parameters:

        timespan:   1
        -------------
        duration: 60s
        warm up time: 5s
        cool down time: 0s
        measuring latency
        gathering IOPS at intervals of 1000ms
        random seed: 0
        path: '\\172.16.200.2\TEST\IO20G.dat'
                think time: 0ms
                burst size: 0
                software cache disabled
                using hardware write cache, writethrough off
                performing mix test (read/write ratio: 50/50)
                block size: 4096
                using interlocked sequential I/O (stride: 4096)
                number of outstanding I/O operations: 4
                thread stride size: 0
                threads per file: 4
                using I/O Completion Ports
                IO priority: normal

System information:

        computer name: DESKTOP-DML65F5
        start time: 2023/02/28 09:00:24 UTC

Results for timespan 1:
*******************************************************************************

actual test time:       60.01s
thread count:           4
proc count:             24

CPU |  Usage |  User  |  Kernel |  Idle
-------------------------------------------
   0|  84.59%|   1.22%|   83.36%|  15.41%
   1|   0.03%|   0.00%|    0.03%|  99.97%
   2|   0.00%|   0.00%|    0.00%| 100.00%
   3|   0.00%|   0.00%|    0.00%| 100.00%
   4|   2.19%|   0.03%|    2.16%|  97.81%
   5|   0.03%|   0.00%|    0.03%|  99.97%
   6|   0.13%|   0.03%|    0.10%|  99.87%
   7|   0.00%|   0.00%|    0.00%| 100.00%
   8|   8.57%|   0.00%|    8.57%|  91.43%
   9|   0.52%|   0.03%|    0.49%|  99.48%
  10|   2.32%|   0.00%|    2.32%|  97.68%
  11|   0.00%|   0.00%|    0.00%| 100.00%
  12|   0.05%|   0.00%|    0.05%|  99.95%
  13|   0.00%|   0.00%|    0.00%| 100.00%
  14|   0.03%|   0.03%|    0.00%|  99.97%
  15|   0.00%|   0.00%|    0.00%| 100.00%
  16|   0.00%|   0.00%|    0.00%| 100.00%
  17|   0.00%|   0.00%|    0.00%| 100.00%
  18|   0.03%|   0.03%|    0.00%|  99.97%
  19|   0.00%|   0.00%|    0.00%| 100.00%
  20|   0.00%|   0.00%|    0.00%| 100.00%
  21|   0.00%|   0.00%|    0.00%| 100.00%
  22|   0.00%|   0.00%|    0.00%| 100.00%
  23|   0.00%|   0.00%|    0.00%| 100.00%
-------------------------------------------
avg.|   4.10%|   0.06%|    4.05%|  95.90%

Total IO
thread |       bytes     |     I/Os     |    MiB/s   |  I/O per s |  AvgLat  | IopsStdDev | LatStdDev |  file
------------------------------------------------------------------------------------------------------------------
     0 |      6139871232 |      1498992 |      97.57 |   24977.70 |    0.160 |    1356.91 |     0.037 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     1 |      6300409856 |      1538186 |     100.12 |   25630.79 |    0.156 |    1122.77 |     0.038 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     2 |      6392381440 |      1560640 |     101.58 |   26004.94 |    0.154 |    1003.56 |     0.037 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     3 |      6394494976 |      1561156 |     101.62 |   26013.54 |    0.154 |    1009.77 |     0.037 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
------------------------------------------------------------------------------------------------------------------
total:       25227157504 |      6158974 |     400.89 |  102626.98 |    0.156 |    4491.17 |     0.037

Read IO
thread |       bytes     |     I/Os     |    MiB/s   |  I/O per s |  AvgLat  | IopsStdDev | LatStdDev |  file
------------------------------------------------------------------------------------------------------------------
     0 |      3068215296 |       749076 |      48.76 |   12481.85 |    0.159 |     678.58 |     0.040 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     1 |      3149733888 |       768978 |      50.05 |   12813.48 |    0.155 |     576.14 |     0.040 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     2 |      3195711488 |       780203 |      50.78 |   13000.52 |    0.153 |     503.92 |     0.040 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     3 |      3195396096 |       780126 |      50.78 |   12999.24 |    0.153 |     506.54 |     0.038 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
------------------------------------------------------------------------------------------------------------------
total:       12609056768 |      3078383 |     200.37 |   51295.09 |    0.155 |    2248.13 |     0.040

Write IO
thread |       bytes     |     I/Os     |    MiB/s   |  I/O per s |  AvgLat  | IopsStdDev | LatStdDev |  file
------------------------------------------------------------------------------------------------------------------
     0 |      3071655936 |       749916 |      48.81 |   12495.85 |    0.161 |     684.30 |     0.034 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     1 |      3150675968 |       769208 |      50.07 |   12817.31 |    0.157 |     558.29 |     0.035 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     2 |      3196669952 |       780437 |      50.80 |   13004.42 |    0.154 |     508.49 |     0.034 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     3 |      3199098880 |       781030 |      50.84 |   13014.30 |    0.155 |     516.13 |     0.036 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
------------------------------------------------------------------------------------------------------------------
total:       12618100736 |      3080591 |     200.52 |   51331.88 |    0.157 |    2251.62 |     0.035



total:
  %-ile |  Read (ms) | Write (ms) | Total (ms)
----------------------------------------------
    min |      0.076 |      0.076 |      0.076
   25th |      0.140 |      0.142 |      0.141
   50th |      0.152 |      0.154 |      0.153
   75th |      0.166 |      0.168 |      0.167
   90th |      0.180 |      0.182 |      0.181
   95th |      0.189 |      0.191 |      0.190
   99th |      0.220 |      0.221 |      0.221
3-nines |      0.322 |      0.311 |      0.316
4-nines |      1.984 |      1.257 |      1.808
5-nines |      4.038 |      3.692 |      3.744
6-nines |      4.933 |      4.332 |      4.891
7-nines |      5.081 |      4.980 |      5.081
8-nines |      5.081 |      4.980 |      5.081
9-nines |      5.081 |      4.980 |      5.081
    max |      5.081 |      4.980 |      5.081

C:\WORK\DISKSPD>diskspd -t4 -o4 -b4k -si4k -w50 -d60 -Su -D -L \\172.16.200.2\TEST\IO20G.dat

Command Line: diskspd -t4 -o4 -b4k -si4k -w50 -d60 -Su -D -L \\172.16.200.2\TEST\IO20G.dat

Input parameters:

        timespan:   1
        -------------
        duration: 60s
        warm up time: 5s
        cool down time: 0s
        measuring latency
        gathering IOPS at intervals of 1000ms
        random seed: 0
        path: '\\172.16.200.2\TEST\IO20G.dat'
                think time: 0ms
                burst size: 0
                software cache disabled
                using hardware write cache, writethrough off
                performing mix test (read/write ratio: 50/50)
                block size: 4096
                using interlocked sequential I/O (stride: 4096)
                number of outstanding I/O operations: 4
                thread stride size: 0
                threads per file: 4
                using I/O Completion Ports
                IO priority: normal

System information:

        computer name: DESKTOP-DML65F5
        start time: 2023/02/28 09:04:13 UTC

Results for timespan 1:
*******************************************************************************

actual test time:       60.01s
thread count:           4
proc count:             24

CPU |  Usage |  User  |  Kernel |  Idle
-------------------------------------------
   0|  51.13%|   0.91%|   50.22%|  48.87%
   1|   0.26%|   0.05%|    0.21%|  99.74%
   2|   0.26%|   0.03%|    0.23%|  99.74%
   3|   0.00%|   0.00%|    0.00%| 100.00%
   4|  40.05%|   0.08%|   39.97%|  59.95%
   5|   0.00%|   0.00%|    0.00%| 100.00%
   6|   0.08%|   0.00%|    0.08%|  99.92%
   7|   0.00%|   0.00%|    0.00%| 100.00%
   8|   1.07%|   0.00%|    1.07%|  98.93%
   9|   0.65%|   0.00%|    0.65%|  99.35%
  10|   1.93%|   0.08%|    1.85%|  98.07%
  11|   0.16%|   0.00%|    0.16%|  99.84%
  12|   0.00%|   0.00%|    0.00%| 100.00%
  13|   0.00%|   0.00%|    0.00%| 100.00%
  14|   0.00%|   0.00%|    0.00%| 100.00%
  15|   0.05%|   0.00%|    0.05%|  99.95%
  16|   0.03%|   0.00%|    0.03%|  99.97%
  17|   0.03%|   0.03%|    0.00%|  99.97%
  18|   0.00%|   0.00%|    0.00%| 100.00%
  19|   0.00%|   0.00%|    0.00%| 100.00%
  20|   0.03%|   0.00%|    0.03%|  99.97%
  21|   0.03%|   0.03%|    0.00%|  99.97%
  22|   0.00%|   0.00%|    0.00%| 100.00%
  23|   0.00%|   0.00%|    0.00%| 100.00%
-------------------------------------------
avg.|   3.99%|   0.05%|    3.94%|  96.01%

Total IO
thread |       bytes     |     I/Os     |    MiB/s   |  I/O per s |  AvgLat  | IopsStdDev | LatStdDev |  file
------------------------------------------------------------------------------------------------------------------
     0 |      6505668608 |      1588298 |     103.39 |   26468.73 |    0.151 |    1914.99 |     0.039 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     1 |      6603923456 |      1612286 |     104.96 |   26868.48 |    0.149 |    1574.21 |     0.042 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     2 |      6647169024 |      1622844 |     105.64 |   27044.43 |    0.148 |    1361.30 |     0.078 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     3 |      6651625472 |      1623932 |     105.71 |   27062.56 |    0.148 |    1364.80 |     0.038 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
------------------------------------------------------------------------------------------------------------------
total:       26408386560 |      6447360 |     419.70 |  107444.20 |    0.149 |    6207.09 |     0.052

Read IO
thread |       bytes     |     I/Os     |    MiB/s   |  I/O per s |  AvgLat  | IopsStdDev | LatStdDev |  file
------------------------------------------------------------------------------------------------------------------
     0 |      3251474432 |       793817 |      51.68 |   13228.83 |    0.150 |     961.44 |     0.043 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     1 |      3300507648 |       805788 |      52.45 |   13428.33 |    0.148 |     790.86 |     0.045 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     2 |      3322982400 |       811275 |      52.81 |   13519.77 |    0.147 |     682.21 |     0.083 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     3 |      3323887616 |       811496 |      52.83 |   13523.45 |    0.147 |     689.94 |     0.041 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
------------------------------------------------------------------------------------------------------------------
total:       13198852096 |      3222376 |     209.77 |   53700.37 |    0.148 |    3109.71 |     0.056

Write IO
thread |       bytes     |     I/Os     |    MiB/s   |  I/O per s |  AvgLat  | IopsStdDev | LatStdDev |  file
------------------------------------------------------------------------------------------------------------------
     0 |      3254194176 |       794481 |      51.72 |   13239.90 |    0.152 |     958.73 |     0.036 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     1 |      3303415808 |       806498 |      52.50 |   13440.16 |    0.150 |     790.90 |     0.040 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     2 |      3324186624 |       811569 |      52.83 |   13524.67 |    0.149 |     686.42 |     0.073 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
     3 |      3327737856 |       812436 |      52.89 |   13539.11 |    0.149 |     683.98 |     0.035 | \\172.16.200.2\TEST\IO20G.dat (20GiB)
------------------------------------------------------------------------------------------------------------------
total:       13209534464 |      3224984 |     209.94 |   53743.83 |    0.150 |    3105.00 |     0.049



total:
  %-ile |  Read (ms) | Write (ms) | Total (ms)
----------------------------------------------
    min |      0.073 |      0.073 |      0.073
   25th |      0.131 |      0.134 |      0.132
   50th |      0.144 |      0.147 |      0.145
   75th |      0.159 |      0.161 |      0.160
   90th |      0.175 |      0.177 |      0.176
   95th |      0.185 |      0.187 |      0.186
   99th |      0.217 |      0.219 |      0.218
3-nines |      0.484 |      0.415 |      0.445
4-nines |      2.094 |      1.648 |      1.932
5-nines |      4.432 |      4.533 |      4.439
6-nines |     16.680 |      7.479 |     16.680
7-nines |     32.088 |     32.118 |     32.118
8-nines |     32.088 |     32.118 |     32.118
9-nines |     32.088 |     32.118 |     32.118
    max |     32.088 |     32.118 |     32.118

C:\WORK\DISKSPD>

Wie du sehen kannst, bekomme ich bei DCTCP TO DCTCP einen um ca. 10-15% höheren Durchsatz mit einer etwa um ~10% besseren/geringeren Latenz hin.
Das ist meiner Ansicht nach schon ein sehr deutlicher Unterschied, der eher gegen CUBIC spricht.

Beste Grüsse aus BaWü
Alex

@MysticFoxDE
Copy link
Owner

MysticFoxDE commented Feb 28, 2023

Moin @rscheff,

"Dir ist aber schon klar, dass diese L4S Präsentation genau meinen Punkt unterstreicht, oder? ... "

ich fange langsam an dich etwas besser zu verstehen, muss jedoch auch zugeben, dass ich an vielen Stellen noch zu viele Bahnhöfe sehe. Das liegt jedoch daran, dass du in diesem Thema noch viel tiefer in der Materie steckst als ich.

Zudem muss ich an dieser Stelle ehrlich gestehen, dass mir die Fairness des Datenverkehrs im Internet relativ am Hintern vorbei geht, wenn dadurch die Performance des lokalen Datenverkehrs (Intranet) zu sehr untergraben wird. 😔

Diese Diskussion wäre meiner Ansicht nach auch nicht notwendig, wenn diese Microsoftians das TCP-Profil Autohandling bei den Clients nicht künstlich herausoperiert/kastriert hätten. Dann würde der Client, genau so wie der Server es auch heute auch schon tut, anhand der RTT automatisch entweder das Datacenter-Profil wählen oder das Internet-Profil. Und beim Internet-Profil kann von mir aus weiterhin CUBIC verwendet werden und beim Datacenter-Profil kann ich ja dann nach Gusto einstellen was ich in dem entsprechenden Intranet für richtig halte.

Sprich, CUBIC pauschal durch DCTCP zu ersetzen war eigentlich nie mein Plan, jedoch kann ich bei W10 und W11 nur entweder oder wählen, und genau diesen Murks prangere ich vorrangig mitunter ja auch an.

"'* Disclaimer: Ich bin einer der Autoren dieses Teilaspekts in L4S: AccECN"

😬 ... das ist jetzt aber echt ein harter 🦴, hier muss ich mich erstmal anständig durchbeissen.

Beste Grüsse aus BaWü

Alex

@rscheff
Copy link
Author

rscheff commented Feb 28, 2023

[global]
size=100m
directory=L:
thread
iodepth=4
direct=1
group_reporting
ioengine=windowsaio
ramp_time=15
runtime=300
time_based
write_lat_log=4krandom

[mixed]
rw=randrw
blocksize=4k
stonewall

TCP 10.65.51.30:53682 10.65.58.55:3260 ESTABLISHED Internet

C:\Users\srichard>netsh int tcp show supplemental template=internet
TCP Supplemental Parameters

Minimum RTO (msec) : 300
Initial Congestion Window (MSS) : 10
Congestion Control Provider : cubic
Enable Congestion Window Restart : disabled
Delayed ACK timeout (msec) : 40
Delayed ACK frequency : 2
Enable RACK : enabled
Enable Tail Loss Probe : enabled

C:\Program Files\fio>fio rndtest
mixed: (g=0): rw=randrw, bs=(R) 4096B-4096B, (W) 4096B-4096B, (T) 4096B-4096B, ioengine=windowsaio, iodepth=4
fio-3.20-dirty
Starting 1 thread
mixed: Laying out IO file (1 file / 100MiB)
Jobs: 1 (f=1): [f(1)][100.0%][eta 00m:00s]
mixed: (groupid=0, jobs=1): err= 0: pid=9800: Tue Feb 28 13:04:08 2023
read: IOPS=3284, BW=12.8MiB/s (13.5MB/s)(3849MiB/300001msec)
slat (usec): min=8, max=5067, avg=25.33, stdev=19.09
clat (usec): min=5, max=38990, avg=578.63, stdev=512.31
lat (usec): min=332, max=39048, avg=603.96, stdev=512.42
clat percentiles (usec):
| 1.00th=[ 388], 5.00th=[ 433], 10.00th=[ 453], 20.00th=[ 478],
| 30.00th=[ 498], 40.00th=[ 519], 50.00th=[ 537], 60.00th=[ 562],
| 70.00th=[ 586], 80.00th=[ 619], 90.00th=[ 668], 95.00th=[ 725],
| 99.00th=[ 922], 99.50th=[ 1188], 99.90th=[10683], 99.95th=[12649],
| 99.99th=[15270]
bw ( KiB/s): min= 7821, max=14361, per=100.00%, avg=13151.96, stdev=623.83, samples=583
iops : min= 1955, max= 3590, avg=3287.66, stdev=155.96, samples=583
write: IOPS=3280, BW=12.8MiB/s (13.4MB/s)(3844MiB/300001msec); 0 zone resets
slat (usec): min=12, max=5575, avg=41.72, stdev=23.45
clat (usec): min=2, max=41352, avg=552.43, stdev=127.27
lat (usec): min=403, max=41832, avg=594.14, stdev=130.33
clat percentiles (usec):
| 1.00th=[ 412], 5.00th=[ 441], 10.00th=[ 457], 20.00th=[ 486],
| 30.00th=[ 506], 40.00th=[ 523], 50.00th=[ 545], 60.00th=[ 562],
| 70.00th=[ 586], 80.00th=[ 611], 90.00th=[ 660], 95.00th=[ 693],
| 99.00th=[ 775], 99.50th=[ 824], 99.90th=[ 1188], 99.95th=[ 1565],
| 99.99th=[ 3916]
bw ( KiB/s): min= 8077, max=14089, per=100.00%, avg=13133.81, stdev=651.71, samples=583
iops : min= 2019, max= 3522, avg=3283.12, stdev=162.92, samples=583
lat (usec) : 4=0.01%, 10=0.01%, 20=0.01%, 50=0.01%, 100=0.01%
lat (usec) : 250=0.01%, 500=29.17%, 750=68.18%, 1000=2.18%
lat (msec) : 2=0.27%, 4=0.05%, 10=0.09%, 20=0.06%, 50=0.01%
cpu : usr=2.67%, sys=19.33%, ctx=0, majf=0, minf=0
IO depths : 1=0.2%, 2=17.0%, 4=82.8%, 8=0.0%, 16=0.0%, 32=0.0%, >=64=0.0%
submit : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
complete : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
issued rwts: total=985370,984039,0,0 short=0,0,0,0 dropped=0,0,0,0
latency : target=0, window=0, percentile=100.00%, depth=4

Run status group 0 (all jobs):
READ: bw=12.8MiB/s (13.5MB/s), 12.8MiB/s-12.8MiB/s (13.5MB/s-13.5MB/s), io=3849MiB (4036MB), run=300001-300001msec
WRITE: bw=12.8MiB/s (13.4MB/s), 12.8MiB/s-12.8MiB/s (13.4MB/s-13.4MB/s), io=3844MiB (4031MB), run=300001-300001msec

C:\Users\srichard>netsh int tcp show supplemental template=internet
TCP Supplemental Parameters

Minimum RTO (msec) : 300
Initial Congestion Window (MSS) : 10
Congestion Control Provider : dctcp
Enable Congestion Window Restart : disabled
Delayed ACK timeout (msec) : 40
Delayed ACK frequency : 2
Enable RACK : enabled
Enable Tail Loss Probe : enabled

C:\Users\srichard>netstat -anyp tcp | find /i "3260"
TCP 10.65.51.30:53682 10.65.58.55:3260 TIME_WAIT Not Applicable
TCP 10.65.51.30:62817 10.65.58.55:3260 ESTABLISHED Internet

C:\Program Files\fio>fio rndtest
mixed: (g=0): rw=randrw, bs=(R) 4096B-4096B, (W) 4096B-4096B, (T) 4096B-4096B, ioengine=windowsaio, iodepth=4
fio-3.20-dirty
Starting 1 thread
Jobs: 1 (f=1): [f(1)][100.0%][eta 00m:00s]
mixed: (groupid=0, jobs=1): err= 0: pid=6956: Tue Feb 28 13:17:00 2023
read: IOPS=3340, BW=13.0MiB/s (13.7MB/s)(3915MiB/300001msec)
slat (usec): min=8, max=779, avg=24.48, stdev=11.21
clat (usec): min=5, max=24805, avg=568.80, stdev=497.24
lat (usec): min=326, max=24824, avg=593.28, stdev=496.88
clat percentiles (usec):
| 1.00th=[ 379], 5.00th=[ 424], 10.00th=[ 449], 20.00th=[ 474],
| 30.00th=[ 494], 40.00th=[ 510], 50.00th=[ 529], 60.00th=[ 553],
| 70.00th=[ 578], 80.00th=[ 611], 90.00th=[ 660], 95.00th=[ 709],
| 99.00th=[ 881], 99.50th=[ 1057], 99.90th=[10421], 99.95th=[12780],
| 99.99th=[15401]
bw ( KiB/s): min=11168, max=14508, per=100.00%, avg=13375.20, stdev=439.82, samples=584
iops : min= 2792, max= 3627, avg=3343.48, stdev=109.97, samples=584
write: IOPS=3337, BW=13.0MiB/s (13.7MB/s)(3911MiB/300001msec); 0 zone resets
slat (usec): min=12, max=825, avg=40.56, stdev=14.32
clat (usec): min=16, max=10713, avg=544.78, stdev=80.90
lat (usec): min=398, max=10749, avg=585.34, stdev=80.82
clat percentiles (usec):
| 1.00th=[ 408], 5.00th=[ 437], 10.00th=[ 453], 20.00th=[ 482],
| 30.00th=[ 502], 40.00th=[ 519], 50.00th=[ 537], 60.00th=[ 553],
| 70.00th=[ 578], 80.00th=[ 603], 90.00th=[ 644], 95.00th=[ 685],
| 99.00th=[ 758], 99.50th=[ 791], 99.90th=[ 914], 99.95th=[ 1037],
| 99.99th=[ 1467]
bw ( KiB/s): min=11505, max=14400, per=100.00%, avg=13363.68, stdev=437.45, samples=584
iops : min= 2876, max= 3600, avg=3340.55, stdev=109.40, samples=584
lat (usec) : 10=0.01%, 20=0.01%, 250=0.01%, 500=31.89%, 750=66.01%
lat (usec) : 1000=1.79%
lat (msec) : 2=0.16%, 4=0.03%, 10=0.08%, 20=0.05%, 50=0.01%
cpu : usr=2.67%, sys=19.67%, ctx=0, majf=0, minf=0
IO depths : 1=0.2%, 2=17.1%, 4=82.7%, 8=0.0%, 16=0.0%, 32=0.0%, >=64=0.0%
submit : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
complete : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
issued rwts: total=1002206,1001322,0,0 short=0,0,0,0 dropped=0,0,0,0
latency : target=0, window=0, percentile=100.00%, depth=4

Run status group 0 (all jobs):
READ: bw=13.0MiB/s (13.7MB/s), 13.0MiB/s-13.0MiB/s (13.7MB/s-13.7MB/s), io=3915MiB (4105MB), run=300001-300001msec
WRITE: bw=13.0MiB/s (13.7MB/s), 13.0MiB/s-13.0MiB/s (13.7MB/s-13.7MB/s), io=3911MiB (4101MB), run=300001-300001msec

Read IOs:
Cubic: lat (usec): min=332, max=39048, avg=603.96, stdev=512.42
DCTCP: lat (usec): min=326, max=24824, avg=593.28, stdev=496.88
Write IOs (this could be influenced by DCTCP):
Cubic: lat (usec): min=403, max=41832, avg=594.14, stdev=130.33
DCTCP: lat (usec): min=398, max=10749, avg=585.34, stdev=80.82

IMHO not a significant difference outside of statistically really relevant bounds (10 usec faster average IO completion time by DCTCP vs. Cubic, at around 600 usec IO completion time (less than 2%).

@rscheff
Copy link
Author

rscheff commented Feb 28, 2023

Frage: Wurde nur der congestionprovider parameter geändert, oder das komplette script durchlaufen lassen?

Die Parameter von DiskSpd sind 4 parallele Threads, mit jeweils IO Tiefe von 4 (also 16 outstanding IOs), -si macht effektiv sequential IO (warum dann eine 20G testdatei; wenn man nur die Netzperformance mit möglichst geringen Filesystem Einflüssen messen will, sollte man die Daten im Filesystem idealerweise im Hot Cache haben - also dramatisch geringere Filegröße wäre angesagt, vielleicht nur 1 oder 10 MB (manche tools jammern, wenn die größe zu klein wird).
-Su macht kein lokales Caching für reads, aber -Sw scheint zu fehlen um blocking,synchonous writes zu machen (sonst misst man eventuell nur wie lange der syscall dauert innerhalb des lokalen filesystems; wegen der mischung von rd und wr und der IO depth sind dann aber trotzdem nicht beliebig viele writes möglich)

Die Idee von DCTCP ist, wenn es korrekt (also mit den notwendigen Modifikationen von dazwischenliegenden Switches) umgesetzt wird, die Netzwerklatenz um 80-95% zu senken. Klarerweise bleibt die (dominate) Latenz des Servers (reduzierbar indem man möglichst kleine Files nutzt die im L2/L3 cache bleiben) davon unbeeinträchtigt.

Und manche Versionen von DCTCP nutzen das einfachere NewReno - in dem Test oben ist es unwahrscheinlich, dass Queuing im Switch überhaupt auftritt (angenommen 10G Link speed).

Die 10% Verbesserungen wären hingegen konsitstent mit den anderen Parametern des Skrips, schnellere Delayed ACKs, etc.

Ich denke nicht, dass die minimal schnellere Verarbeitung von (potentiell) NewReno +DCTCP vs. Cubic im Stack alleine einen 10% Unterschied ausmachen kann.

Ein "netstat -nsp tcp" vor und nach dem test, auf beiden seiten, wäre interessant - ob es überhaupt retransmissions gab (ich bin mir nicht sicher, ob/wie windows die ECN statistiken hergibt).

Sprich, CUBIC pauschal durch DCTCP zu ersetzen war eigentlich nie mein Plan, jedoch kann ich bei W10 und W11 nur entweder oder wählen, und genau diesen Murks prangere ich vorrangig mitunter ja auch an.

Gut, darin sind wir uns ja einig. Ich habe auch nix dagegen, wenn sich jemand selbst in den Fuß schiesst, und intern DCTCP parallel mit (externem) TCP Traffic nutzt, ohne wirklich zu wissen, ob das so eine schlaue Idee ist.

Wobei der Threshold von 6ms teilweise heutzutage schon bei FTTH zum nächstgelegenen NetFlix Server zustandekommt (quer über ein Provider Netzwerk). (NF nutzt aber Cubic mit RACK, und kein ECN bisher - mangels der TCP ECN aktivierung arbeitet W11 dann also wie oben erklärt, entweder mit NewReno oder Cubic alleine).

Wenn man DCTCP intern machen will, sollte man seine Firewall so aufsetzen, dass Traffic ins Internet ohne ECN läuft - also entweder CE-markierte Packete droppen, oder in TCP die beiden Bits und auf 0 setzen. Dann ist sichergestellt, dass externe Sessions immer ohne ECN (und ohne DCTCP) laufen, und es keine komplikationen mit anderem (Internet) Traffic gibt.

@MysticFoxDE
Copy link
Owner

MysticFoxDE commented Feb 28, 2023

Moin @rscheff,

wenn ich mir deine Ergebnisse, für die ich übrigens sehr dankbar bin, ansehe, dann stellen sich mir die folgenden Fragen.

Warum sind die Ergebnisse von deinen Tests, stellenweise so signifikant anders als meine?
Was ist genau der Grund dafür?

Du verwendest W10 22H2 und testest wahrscheinlich gegen eine NetApp.
Und ich teste W11 22H2 gegen W11 22H2.

Haben die Microsoftianer vielleicht die Implementierung von CUBIC zwischen W10 und W11 verändert?

Gruss Alex

@rscheff
Copy link
Author

rscheff commented Feb 28, 2023

  1. ich habe ausschliesslich den congestionprovider geändert - alle anderen Parameter sind unverändert gegenüber dem Default des internet profils. Damit keine (komplett nachvollziehbaren) Verbesserungen zB wegen reduzierter Delayed ACKs (die ohne Loss, also Congestion Response, den Hauptteil von vermeidbaren Verzögerungen verursachen sollten, falls das volle Skript in deinen Tests verwendet wurde.

  2. Ich habe versucht, Einflüsse des Server OS/Filesystems zu minimieren (kleine, komplett gecachte Datei - durch random IO wird die auch im Speicher gepinnt; sequential IO triggert oft prefetching, aber wird gleich nachdem der Block angefragt wurde, zum Recycling freigegeben)

  3. Meine Box ist nur mit 1Gbps im 1. Hop angebunden - Schreiboperationen, wo lokales ändern des Parameters einen Einfluss haben könnte, werden effektiv durch diese Linkgeschwindigkeit gebremst (und ein IO Burst mit 1Gbps / 100 MB/sec ist keine ernsthafte Herausforderung für einen SMB Server. Bei den anderen Links danach sind 40G und 25G.

Und ja, Cubic ist sicherlich leicht modifiziert worden (siehe RFC8312 und RFC8312bis), abgesehen davon, dass W11 vermutlich eine anfängliche Form von HyStart++ macht, was während SlowStart durchaus helfen kann, Packetverluste zu vermeiden.

Mein Hauptargument ist jedoch, dass ein Ausrollen von DCTCP, wenn das unilateral passiert, und man TCP ECN nicht an der Grenze zum Internet dann erst recht wieder verhindert, kann das dazu führen das der DCTCP Traffic einen überproportionalen Anteil der Bandbreite einer Überlasteten Queue an sich zieht - und ISPs gegebenenfalls Gegenmaßnahmen einleiten (wie das deaktivieren bzw überschreiben von IP ECN und TCP ECN bits - wodurch dann das Ausrollen von L4S wieder einige Jahre nach hinten verschoben werden wird. Also ein klassischer Fall von Tragedy of the Commons wodurch dass Internet durch einige wenige Selbstsüchtige nicht für alle besser werden kann (L4S

TCP ist zwar über 40 Jahre alt, aber es werden immer noch neue Tricks implementiert, die teilweise sehr subtil sind und nur in bestimmten Umgebungen klar zutage treten.

@MysticFoxDE
Copy link
Owner

Moin @rscheff,

eines im Vorfeld, damit du besser nachvollziehen kannst, warum ich mich mit diesem TCP Murks überhaupt beschäftige. Ursprünglich komme ich eher aus der Storage Ecke und habe bereits 2010 das erste AllFlash bei einem unserer Kunden implementiert.
Mittlerweile haben wir bei einigen Kunden deren AllFlash-SAN’s bereits durch neuere und schnellere Geräte ersetzt, doch der erhoffte Performancezuwachs, ist meistens ausgeblieben.
Und so habe ich mich auf die Suche gemacht, woran das liegen könnte und haben dann irgendwann mittendrin gemerkt, dass es so gut wie nichts bringt, wenn ich die Latenz eines IO’s, durch ein neues SAN’s von z.B. 1ms auf 0,1ms gedrückt wird, wenn danach das Windows hergeht, und beim Transport dieses IO’s über das Netzwerk, eine zusätzliche Latenz von 40ms und mehr, draufpackt. 😔

„Frage: Wurde nur der congestionprovider parameter geändert, oder das komplette script durchlaufen lassen?“

Ich habe zuerst alles durchlaufen lassen, bis auf die Umstellung von CUBIC auf DCTCP, dann habe ich den CUBIC Test gemacht und dann nur noch auf DCTCP umgestellt und erneut getestet.

„Die Parameter von DiskSpd sind 4 parallele Threads, mit jeweils IO Tiefe von 4 (also 16 outstanding IOs)“

Jup, ich wollte damit eine Last mit ein paar parallelen Threads/Worker, mit je etwas Dampf dahinter, simulieren.

„-si macht effektiv sequential IO“

Ob sequential oder random macht in dem Fall ja nicht wirklich was aus, weil wir momentan ja nur über TCP-Performance reden.

„warum dann eine 20G testdatei;“

Damit diese in den SLC-Cache der in den Workstations verbauten Samsungs 980 PRO reinpasst. 😁
Du hast aber schon recht, für den reinen TCP-Test hätte ich die Testdatei auch kleiner wählen können. Na ja, macht der Gewohnheit, bei Storagetests muss ich genau auf das Gegenteil achten, damit ich nicht nur „all hit“, sprich nicht nur gegen den Cache teste. 🙃

„wenn man nur die Netzperformance mit möglichst geringen Filesystem Einflüssen messen will, sollte man die Daten im Filesystem idealerweise im Hot Cache haben - also dramatisch geringere Filegröße wäre angesagt, vielleicht nur 1 oder 10 MB (manche tools jammern, wenn die größe zu klein wird).“

Das eure NetApp’s mit dem Cache gut umgehen können, will ich nicht anzweifeln, im Gegenteil, ich weis genau wie NetApp die Plazierung bei SPC1 & SPC2 hinbekommen hat.
Aber glaub mir, den "Block-Data-Cache" vom Windows möchtest du nicht wirklich benutzen.

„-Su macht kein lokales Caching für reads,“

Jup, damit wollte ich bewusst das Windows eigenen Caching umgehen, weil dieses schlichtweg eine Katastrophe ist. Ich sag nur Sequentialisierung + LazyWrites … 🤢🤮

„aber -Sw scheint zu fehlen um blocking,synchonous writes zu machen (sonst misst man eventuell nur wie lange der syscall dauert innerhalb des lokalen filesystems; wegen der mischung von rd und wr und der IO depth sind dann aber trotzdem nicht beliebig viele writes möglich)“

Wenn ich mit „-Sw“, sprich „write-through“ teste, dann umgeht der IO wenn ich das richtig verstehe den Drive-Cache und landet direkt auf dem MLC der Samsung, was performancetechnisch doch wieder suboptimal wäre.

„Die Idee von DCTCP ist, wenn es korrekt (also mit den notwendigen Modifikationen von dazwischenliegenden Switches) umgesetzt wird, die Netzwerklatenz um 80-95% zu senken. Klarerweise bleibt die (dominate) Latenz des Servers (reduzierbar indem man möglichst kleine Files nutzt die im L2/L3 cache bleiben) davon unbeeinträchtigt.“

Na ja, ich bin von L2/L3 Caches nicht wirklich zu sehr angetan, weil der vor allem beim Lesen ja erst ab dem zweiten IO richtig zündelt. Ich fange eher bei einem mit Optane-SSD’s bestücktem SAN an zu sabbern. Sprich, IO‘s mit geringer Latenz egal wie und wohin man greift.🤪

„Und manche Versionen von DCTCP nutzen das einfachere NewReno - in dem Test oben ist es unwahrscheinlich, dass Queuing im Switch überhaupt auftritt (angenommen 10G Link speed).“

Nix Queuing im Switch, die Workstations waren während des Tests direkt mit einem Patchkabel miteinander verbunden.
By the Way, ich habe schon mehrfach bemerkt, dass die CPU-Belastung der Core-Switche unserer Kunden, nach der Umstellung derer Systeme von CUBIC auf DCTCP, deutlich zurückgegangen ist.

„Die 10% Verbesserungen wären hingegen konsitstent mit den anderen Parametern des Skrips, schnellere Delayed ACKs, etc.“

Wie ich oben schon geschrieben habe, waren bei dem CUBIC Test Delayed-ACK’s & Co., bereits auch schon deaktiviert.

„Ich denke nicht, dass die minimal schnellere Verarbeitung von (potentiell) NewReno +DCTCP vs. Cubic im Stack alleine einen 10% Unterschied ausmachen kann.“

Genau danach sieht es momentan aber aus.

„Ein "netstat -nsp tcp" vor und nach dem test, auf beiden seiten, wäre interessant - ob es überhaupt retransmissions gab (ich bin mir nicht sicher, ob/wie windows die ECN statistiken hergibt).“

Guter Hinweis, danke, werde ich beim nächsten Test auf jeden Fall prüfen.

„Gut, darin sind wir uns ja einig. Ich habe auch nix dagegen, wenn sich jemand selbst in den Fuß schiesst, und intern DCTCP parallel mit (externem) TCP Traffic nutzt, ohne wirklich zu wissen, ob das so eine schlaue Idee ist.“

Na ja, das bisherige Feedback ist eher ganz weit von einem Knieschuss entfernt.
Und das irrwitzige dabei ist auch noch, dass die Meisten, neben einer drastisch gestiegenen Performance bei lokalen Anwendungen, mitunter sofort auch eine Verbesserung der Performance beim Surfen im Internet feststellen.

„Wobei der Threshold von 6ms teilweise heutzutage schon bei FTTH zum nächstgelegenen NetFlix Server zustandekommt (quer über ein Provider Netzwerk). (NF nutzt aber Cubic mit RACK, und kein ECN bisher - mangels der TCP ECN aktivierung arbeitet W11 dann also wie oben erklärt, entweder mit NewReno oder Cubic alleine).“

Und auch hier gab es in diversen Foren schon das Feedback, das nach den ausführen des Skripts, also auch Umstellung auf DCTCP, Streaming-Anwendungen ebenfalls viel besser laufen würden.

„Wenn man DCTCP intern machen will, sollte man seine Firewall so aufsetzen, dass Traffic ins Internet ohne ECN läuft - also entweder CE-markierte Packete droppen, oder in TCP die beiden Bits und auf 0 setzen. Dann ist sichergestellt, dass externe Sessions immer ohne ECN (und ohne DCTCP) laufen, und es keine komplikationen mit anderem (Internet) Traffic gibt.“

Ich habe die Optimierungen schon in diversen Umgebungen vorgenommen und bisher sind mir noch keine Probleme bei den entsprechenden SGW’s bekannt.

Beste Grüsse aus BaWü
Alex

@MysticFoxDE
Copy link
Owner

Moin @rscheff,

„ich habe ausschliesslich den congestionprovider geändert - alle anderen Parameter sind unverändert gegenüber dem Default des internet profils. Damit keine (komplett nachvollziehbaren) Verbesserungen zB wegen reduzierter Delayed ACKs (die ohne Loss, also Congestion Response, den Hauptteil von vermeidbaren Verzögerungen verursachen sollten, falls das volle Skript in deinen Tests verwendet wurde.“

Bei meinem Test war wie zuvor schon geschrieben, auch bei dem CUBIC Durchlauf alles bis auf den Congestion-Provider & ECN, bereits schon optimiert.
Sprich, die Unterschiede im Ergebnis kommen bei mir nur durch die Umstellung von CUBIC auf DCTCP und der Aktivierung von ECN.

„Ich habe versucht, Einflüsse des Server OS/Filesystems zu minimieren (kleine, komplett gecachte Datei - durch random IO wird die auch im Speicher gepinnt; sequential IO triggert oft prefetching, aber wird gleich nachdem der Block angefragt wurde, zum Recycling freigegeben)“

Na ja, da es hier aktuell ja nur um TCP-Performance geht, wären AllCache Zugriffe so gesehen eigentlich nicht wirklich verkehrt, weil man durch diese die geringste Verfälschung seitens des Storages hätte.

Warum kann eigentlich kein einziges reines TCP-Performance Messtool wie z.B. iperf oder ntttcp & Co., denselben Workload simulieren, sprich, blockweise abwechselnd senden/empfangen.

„Und ja, Cubic ist sicherlich leicht modifiziert worden (siehe RFC8312 und RFC8312bis), abgesehen davon, dass W11 vermutlich eine anfängliche Form von HyStart++ macht, was während SlowStart durchaus helfen kann, Packetverluste zu vermeiden.“

Danke für diesen Hinweis, das muss ich mir nun etwas genauer anschauen.

„Mein Hauptargument ist jedoch, dass ein Ausrollen von DCTCP, wenn das unilateral passiert, und man TCP ECN nicht an der Grenze zum Internet dann erst recht wieder verhindert, kann das dazu führen das der DCTCP Traffic einen überproportionalen Anteil der Bandbreite einer Überlasteten Queue an sich zieht - und ISPs gegebenenfalls Gegenmaßnahmen einleiten (wie das deaktivieren bzw überschreiben von IP ECN und TCP ECN bits - wodurch dann das Ausrollen von L4S wieder einige Jahre nach hinten verschoben werden wird. Also ein klassischer Fall von Tragedy of the Commons wodurch dass Internet durch einige wenige Selbstsüchtige nicht für alle besser werden kann (L4S

Richard, wie ich schon geschrieben habe ist es überhaupt nicht mein Bestreben, den Fluss des Datenverkehrs des Internets zu „sabotieren“!
Ich kann es jedoch auch nicht hinnehmen, dass wegen Features, deren Entwickler nur Glubschis für den Internetdatenverkehr hatten, der für unserer Kunden viel wichtigere Intranetdatenverkehr, zum Teil sehr extrem leidet. 😔

„TCP ist zwar über 40 Jahre alt, aber es werden immer noch neue Tricks implementiert, die teilweise sehr subtil sind und nur in bestimmten Umgebungen klar zutage treten.“

Und genau hier liegt eines der Kernprobleme, so wie du es selber schreibst … „die teilweise sehr subtil sind und nur in bestimmten Umgebungen klar zutage treten“ passen manche TCP-Features nur für bestimmte Szenarien.
Warum zur Höhle, werden dann solch spezielle Features, wie z.B. RSC, dann in aktuellen Betriebssystemen per default, sprich, in jeglichen Umgebungen pauschal aktiviert?

Beste Grüsse aus BaWü
Alex

@AloisKraus
Copy link

Hm die Performance scheint da sehr zu fluktuieren. Mein Vorschlag wäre das mal mit ETW zu messen und dann mit Tools wie WPA (Windows Performance Analyzer) zu untersuchen woher die Schwankungen kommen. Man kann das auch automatisieren z.B. mit https://github.com/Siemens-Healthineers/ETWAnalyzer um CPU/Disk/File ... demnächst auch TCP Retransmissions wo die TCP Templates auch eine Rolle spielen.

@MysticFoxDE
Copy link
Owner

MysticFoxDE commented Mar 22, 2023

Hi Alois,

Hm die Performance scheint da sehr zu fluktuieren

ja, das tut sie und dass stellenweise nicht gerade wenig. 😔

Mein Vorschlag wäre das mal mit ETW zu messen und dann mit Tools wie WPA (Windows Performance Analyzer) zu untersuchen woher die Schwankungen kommen.

Das ist ein guter Vorschlag und ich würde mich auch sehr freuen, wenn mal die grösseren in der IT-Branche, wie z.B. Lenovo, Dell, IBM, HPE & Co., die vor allem etwas mehr Kapazitäten wie wir haben, diesen mal selbst umsetzen würden.
Verstehe mich jetzt bitte nicht falsch, ich möchte mich vor dieser Aufgabe nicht drücken, aber mein Unternehmen ist sehr klein und diese zum Teil sehr aufwändigen Analysen, nagen schon seit längerem, extremst an unseren etwas eingeschränkten Ressourcen.

Zudem habe ich erst vor ein paar Wochen mehrere Traces mit einer klaren Fragestellung, direkt an Dan, Matt, Keith, Daniel & Co. (Hauptentwickler des TCP-Stacks bei MS) gesendet und das einzige was ich zurück bekommen habe, war die Frage, weshalb ich den RSS ausgeschaltet habe.

Diese Frage habe ich dann auch sehr ausführlich beantwortet.
Kurzfassung: Weil ich durch RSS das Messergebnis nicht unnötig verwischen lassen möchte und auch auf dessen, mitunter nicht geringen Overhead, gerne verzichten kann. Und weil ich bei einer 10G NIC und einer CPU deren Kerne allesamt über 4GHz dauerhaft halten können, schlichtweg kein RSS benötige und das ganz ohne Jumboframes und vor allem den Latenzfresser wie Interrupt Moderation, RSC & Co.

Seit dem habe ich aus Redmond nichts mehr gehört.

Auch auf die Frage, warum denn ein Windows 11 22H2 ohne aktiven Phischingschutz, beim Empfangen von Daten über das Netzwerk, die doppelte CPU-Ressourcen benötigt, wie beim Senden derselben, habe ich bis heute auch keine Antwort bekommen.

Übrigens, wenn der Phischingschutz bei Windows 11 aktiv ist, dann steig die CPU-Belastung beim Senden der Daten nochmals um 200% und beim Empfangen um 300% und das nur betreffend der TCP Verarbeitung!!! 🤢🤮

Beste Grüsse aus BaWü
Alex

@AloisKraus
Copy link

Da kommen viele verschiedene Beobachtungen zusammen. Firewall Regeln sind ein Thema was ich mit ETWAnalyzer schon oft gesehen habe. Die kosten vor allem in grossen AD Domains einiges und können unter Windows 10 die Bandbreite auf 20 MBit/s drücken weil der Kernel nur noch mit Firewall Regeln unterwegs ist. Ist aber eine ganz andere Ecke.

Symptom ist immer das gleiche: Netzwerk ist langsam.

Um da weiter zu kommen sollte man nicht das eine Symptom mit den vielen Root Causes dafür in einen Topf werfen. Ohne Root Cause Analyse kommt man pro Szenario sonst nicht weit.

Ich halte übrigens das generelle enablen des DataCenter Profiles für nicht zielführend.

  1. Wird das Datacenter Profile beim initialen TCP Handshake je nach der Latenz ohnehin enabled (das ist was Auto macht).
  2. Wenn der Rechner nicht nur im RZ sitzt und mit seinesgleichen Pakete tauscht und Traffic von "aussen" oder VPN reinkommt (Home Office?) hat man oft eine Latenz > 20ms. Das bedeutet aber das damit über das DataCenter Profile die MinRTO von 20ms zuschlägt und der Netzwerkverkehr sich verdoppelt, da alles 2x geschickt wird. Der Client wird übrigens mit 300ms RTO sich verbinden, da der üblicherweise das Internet Profile benutzt.

Was mir fehlt ist eine Diskussion welche der vielen Settings in welchen Szenarien was bringen bzw. wann man es besser lassen sollte. Die Beobachtung mit Remote Desktop Latenzen und DelayedAckFrequency ist interessant aber auch da würde ich das nicht für ein Netzwerk Interface für alle Adressen enablen.

@MysticFoxDE
Copy link
Owner

MysticFoxDE commented Mar 22, 2023

Hi Alois,

"Die kosten vor allem in grossen AD Domains einiges und können unter Windows 10 die Bandbreite auf 20 MBit/s drücken weil der Kernel nur noch mit Firewall Regeln unterwegs ist. Ist aber eine ganz andere Ecke."

ja, vor allem dann, wenn von dem immer wieder neue Regeln erstellt werden, obwohl es dieselben im Regelwerk bereits gibt. 🙃

Deswegen ist eines der ersten Dinge die wir auf einer Neuinstallation ausführen, das folgende.
Set-NetFirewallProfile -Profile Domain, Public, Private -Enabled False 😁

Unter anderem auch deswegen, weil wir im Bereich Security, bewusst nicht auf die Produkte von Microsoft setzen.

Ich halte übrigens das generelle enablen des DataCenter Profiles für nicht zielführend.
Wird das Datacenter Profile beim initialen TCP Handshake je nach der Latenz ohnehin enabled (das ist was Auto macht).

Nein, genau das macht Windows 10/11 eben nicht mehr. 😔😭
Deshalb habe ich ja auch hauptsächlich die folgenden Beiträge geschrieben ...

https://administrator.de/tutorial/wie-man-das-windows-10-und-11-tcp-handling-wieder-desuboptimieren-kann-5529700198.html
https://community.spiceworks.com/topic/post/10299845

aus denen schlussendlich auch das "W10ANDW11-NETWORK-TCP-DESUBOPTIMIZATION.ps1" entstanden ist.

Was mir fehlt ist eine Diskussion welche der vielen Settings in welchen Szenarien was bringen bzw. wann man es besser lassen sollte. Die Beobachtung mit Remote Desktop Latenzen und DelayedAckFrequency ist interessant aber auch da würde ich das nicht für ein Netzwerk Interface für alle Adressen enablen.

Sieh dir diesbezüglich bitte die ganzen positiven Kommentare in den Foren an, wo das Skript schon durchgekaut worden ist.
In den allermeisten Fällen spüren die User danach eine sehr deutliche Performanceverbesserung bei allem möglichen.

Siehe z.B. ...
https://community.gigperformer.com/t/maybe-help-for-the-few-dante-users/13511

Beste Grüsse aus BaWü
Alex

@rscheff
Copy link
Author

rscheff commented Mar 22, 2023

„ich habe ausschliesslich den congestionprovider geändert - alle anderen Parameter sind unverändert gegenüber dem Default des internet profils. Damit keine (komplett nachvollziehbaren) Verbesserungen zB wegen reduzierter Delayed ACKs (die ohne Loss, also Congestion Response, den Hauptteil von vermeidbaren Verzögerungen verursachen sollten, falls das volle Skript in deinen Tests verwendet wurde.“

Bei meinem Test war wie zuvor schon geschrieben, auch bei dem CUBIC Durchlauf alles bis auf den Congestion-Provider & ECN, bereits schon optimiert. Sprich, die Unterschiede im Ergebnis kommen bei mir nur durch die Umstellung von CUBIC auf DCTCP und der Aktivierung von ECN.

Nochmal: ECN zu aktivieren kann - insbesondere bei einem Back-to-Back Test zwischen zwei servern - prinzipiell keinerlei Einfluss haben, weil keine aktive Queue zwischen den beiden Servern ist. Es wird schlichtweg nie ein "ECN CE" markiertes Packet geben, statt eines verlorenen Packets (das zB wegen Queue overflow in einer der RSS Queues - um so mehr, wenn RSS deaktiviert ist - stattfinden kann.

Warum kann eigentlich kein einziges reines TCP-Performance Messtool wie z.B. iperf oder ntttcp & Co., denselben Workload simulieren, sprich, blockweise abwechselnd senden/empfangen.

Unzulässige verallgemeinerung. Wie bereits beschrieben, uperf kann zB derartige Burst-typischen "Stop-and-Go" Lastsituationen simulieren, ohne da mit dem kompletten Storage Stack auffahren zu müssen.

Genau um dieses Verhalten, dass zB auch bei S3 Storage oder Web Traffic ebenfalls vorhanden sein kann, rein auf der Netzwerkebene zu testen: https://uperf.org/ (Niemand scheint aber Windows Binaries vorgebaut zu haben).

„Mein Hauptargument ist jedoch, dass ein Ausrollen von DCTCP, wenn das unilateral passiert, und man TCP ECN nicht an der Grenze zum Internet dann erst recht wieder verhindert, kann das dazu führen das der DCTCP Traffic einen überproportionalen Anteil der Bandbreite einer Überlasteten Queue an sich zieht - und ISPs gegebenenfalls Gegenmaßnahmen einleiten (wie das deaktivieren bzw überschreiben von IP ECN und TCP ECN bits - wodurch dann das Ausrollen von L4S wieder einige Jahre nach hinten verschoben werden wird. Also ein klassischer Fall von Tragedy of the Commons wodurch dass Internet durch einige wenige Selbstsüchtige nicht für alle besser werden kann (L4S

Richard, wie ich schon geschrieben habe ist es überhaupt nicht mein Bestreben, den Fluss des Datenverkehrs des Internets zu „sabotieren“! Ich kann es jedoch auch nicht hinnehmen, dass wegen Features, deren Entwickler nur Glubschis für den Internetdatenverkehr hatten, der für unserer Kunden viel wichtigere Intranetdatenverkehr, zum Teil sehr extrem leidet. 😔

Warum die beobachteten, massiven unterschiede zwischen Cubic und DCTCP im Stack auftreten, insbesondere wenn kein ECN im Spiel ist (sein kann, wegen back-to-back), ist eine hervorragende Beobachtung. Allerdings liegt es wohl nicht am eigentlichen TCP Congestion Control Verfahren - wohl viel mehr daran, wie dies implementiert ist, und wo die relevanten Parameter (tcpcb) liegen. Ich weiß von einem OS, wo regelmäßig L1 cache analysen gemacht werden, damit zeitlich rasch miteinander zugegriffene Variablen von inpcb und tcpcb möglichst optimal auf die Cachelines (64 byte memory) zu liegen kommen - also ein Cache nachladen alle "heissen" Variablen gleich in den L1 lädt.

Da DCTCP intern, wie mehrfach geschrieben, vermutlich weiterhin ein recht einfaches NewReno CC nutzt, während Cubic durchaus einiges an zusätzlichen Variablen benötigt, würde mich nicht wundern, wenn Cubic aufgrund von häufiger auftretenden L1 Cache misses dann langsamer ist...

„TCP ist zwar über 40 Jahre alt, aber es werden immer noch neue Tricks implementiert, die teilweise sehr subtil sind und nur in bestimmten Umgebungen klar zutage treten.“

Und genau hier liegt eines der Kernprobleme, so wie du es selber schreibst … „die teilweise sehr subtil sind und nur in bestimmten Umgebungen klar zutage treten“ passen manche TCP-Features nur für bestimmte Szenarien. Warum zur Höhle[sic], werden dann solch spezielle Features, wie z.B. RSC, dann in aktuellen Betriebssystemen per default, sprich, in jeglichen Umgebungen pauschal aktiviert?

RSC im speziellen dient unter anderem dazu, den IRQ und PCI Arbitration Overhead zu minimieren. Dass damit einige Mikrosekunden Latenz dazu kommen, ist oft nicht relevant. Letztlich eine Abwägung zwischen minimaler Latenz (höherer CPU / Bus Last), und höherer Summenbandbreite.

Traditioniell waren viele Leute bislang immer nur auf das Thema Bandbreite fixiert - und das Thema Latenz wurde eher sekundär behandelt.

Aber inzwischen ist meist sogar schon das Internet Bandbreitenmäßig schnell genug, und Latenzeffekte treten nun als Faktor deutlich hervor.

@AloisKraus
Copy link

Stimmt Windows 10/11 Client OS hat keine einzige Verbindung DataCenter enabled. Allerdings sollte das nicht so viel Einfluss haben, da wenn der Server ein Server OS hat, dann wird sehr wohl das DataCenter Template genommen. D.h. wenn der Server hautpsächlich schickt und die Clients nicht viel upstream traffic verursachen sollte das ok sein und wir im Effekt DataCenter Performance bezüglich Retransmissions sehen.

Für Clients das DataCenter Template für alle Verbidndungen zu nehmen ist wie ich schon sagte aus System Sicht nicht gut, da damit ab einem Ping > 20ms die Clients den Traffic doppelt schicken. Das kann nicht im Sinne einer optimialen Netzwerkauslastung sein.

Der Erfahrungsbericht
https://community.gigperformer.com/t/maybe-help-for-the-few-dante-users/13511
ist im Bezug auf eine Audio Software, die von dem lokalen Netz (vermutlich dem 20ms RTO) profitiert hat. Die Applikation hat sich vorher nicht sauber beendet. Ob die bessere Performance jetzt durch das andere Timing Fehler in der Applikation ausgebügelt hat, oder wirklich das Netzwerk an sich optimiert wurde kann ich nicht beurteilen.

@MysticFoxDE
Copy link
Owner

MysticFoxDE commented Mar 23, 2023

Moin @rscheff,

Nochmal: ECN zu aktivieren kann - insbesondere bei einem Back-to-Back Test zwischen zwei servern - prinzipiell keinerlei Einfluss haben, weil keine aktive Queue zwischen den beiden Servern ist. Es wird schlichtweg nie ein "ECN CE" markiertes Packet geben, statt eines verlorenen Packets (das zB wegen Queue overflow in einer der RSS Queues - um so mehr, wenn RSS deaktiviert ist - stattfinden kann.

Richard, dass das in der Theorie so sein sollte glaube ich dir gerne.
In der Microsoftians-Welt sieht das Ganze wie meine Tests beweisen, jedoch etwas anders aus.
Wenn du nun sagst, nein, dass darf so nicht sein, OK ... gut ... wie und was können wir dagegen tun?
Denn am Ende des Tages laufen eure NetApps meistens auch gegen einen Windows Client.
Sprich, wir sitzen eigentlich im selben Boot. 😉

Bei meinen letzten Tests waren übrigens nur zwei W11 Workstations eingebunden und kein Server.

Genau um dieses Verhalten, dass zB auch bei S3 Storage oder Web Traffic ebenfalls vorhanden sein kann, rein auf der Netzwerkebene zu testen: https://uperf.org/

🤔 ... interessant, danke für die Info.

Da DCTCP intern, wie mehrfach geschrieben, vermutlich weiterhin ein recht einfaches NewReno CC nutzt, während Cubic durchaus einiges an zusätzlichen Variablen benötigt, würde mich nicht wundern, wenn Cubic aufgrund von häufiger auftretenden L1 Cache misses dann langsamer ist...

So, jetzt geht es glaube ich langsam in die richtige Richtung.
Wenn Cubic komplexer ist als DCTCP, dann hat es auch einen höheren Overhead und dann passen meine Beobachtungen auch wieder +- zu der Theorie.

Ich habe ferner zwischendurch den folgenden interessanten Bericht zu unserer Diskussion gefunden ...
https://ieeexplore.ieee.org/document/9493352/metrics#metrics

"Our results show that DTCP improves substantially the fairness properties of TCP, but it requires more buffer space for large number of flows; it also requires the intermediate switches to be Explicit Congestion Notification (ECN)-aware. CUBIC achieves very low queue occupancies, but it demonstrates low fairness when a large and a small set of flows compete at the output port of a bottleneck switch (TCP Outcast issue)."

Komme jetzt auf die Schnelle, vor allem nicht ohne zu blechen, nicht an den Rest heran. 😭
Na ja, mal schauen, habe heute Abend 3 Stunden im Zug totzuschlagen. 🤪

"RSC im speziellen dient unter anderem dazu, den IRQ und PCI Arbitration Overhead zu minimieren. Dass damit einige Mikrosekunden Latenz dazu kommen, ist oft nicht relevant. Letztlich eine Abwägung zwischen minimaler Latenz (höherer CPU / Bus Last), und höherer Summenbandbreite."

Richard, ich weiss mittlerweile sehr genau wie RSC funktioniert und dass es die Eingehenden Pakete auf bis zu 64K aufstocken kann, bis ein IRQ zur Übergabe ausgelöst wird. Und genau hier liegt das Problem, den die Daten aus dem ersten Ethernet Paket, werden im suboptimalsten Fall erst mit den Daten des ~42 Ethernet-Pakets von der Anwendungsschicht verarbeitet und oder die Daten des ersten Ethernet Pakets werden von RSC unnötig aufgehalten, weil dieses noch auf ein eventuelles weiters Ethernet Paket wartet, dass es dann zusammenfassen kann. 🤢

Und jetzt denk mal bitte ganz genau darüber nach wie Interrupt Moderation funktioniert und erkläre mir dann bitte, wie das mit RSC und IM überhaupt in einen Topf rein passen soll.

Traditioniell waren viele Leute bislang immer nur auf das Thema Bandbreite fixiert - und das Thema Latenz wurde eher sekundär behandelt.

Ja das merke ich, vor allem Produktseitig. 😔
Nimm mir das jetzt bitte nicht übel, aber genau aus diesem Grund setzen wir bei unseren Kunden auch auf reine Blocklevel-SAN's und nicht auf SAN's die Blocklevel auf einem Filelevel "emulieren".
Ja, OK, ihr könnt das um Welten besser als QNAP & Co.

"Aber inzwischen ist meist sogar schon das Internet Bandbreitenmäßig schnell genug, und Latenzeffekte treten nun als Faktor deutlich hervor."

Na ja, eines der interessantesten Feedbacks was ich auf mein Skript erhalten habe war +- folgend.
"Alex, ich habe zwar nur einen 6 MBit/s Anschluss, aber selbst bei diesem merke ich eine deutliche Verbesserung, danke."

Beste Grüsse aus BaWü
Alex

@MysticFoxDE
Copy link
Owner

Moin @AloisKraus,

Allerdings sollte das nicht so viel Einfluss haben, da wenn der Server ein Server OS hat, dann wird sehr wohl das DataCenter Template genommen.

ja, aber nur Serverseitig und nicht Clientseitig.

D.h. wenn der Server hautpsächlich schickt und die Clients nicht viel upstream traffic verursachen sollte das ok sein und wir im Effekt DataCenter Performance bezüglich Retransmissions sehen.

Jetzt hast du glaube ich einen kleinen Denkfehler, den die Quittierung der Pakete vom Server seitens des Clients erfolgt gemäss dem angewendeten TCP-Profil des Clients und nicht gemäss dem des Servers. 😉

Für Clients das DataCenter Template für alle Verbidndungen zu nehmen ist wie ich schon sagte aus System Sicht nicht gut, da damit ab einem Ping > 20ms die Clients den Traffic doppelt schicken. Das kann nicht im Sinne einer optimialen Netzwerkauslastung sein.

Das ist so, zumindest was Windows 10/11 angeht nicht korrekt, denn sowohl beim Datacenter-Profil, als auch beim Internet-Profil, steht die "InitialRtoMs" auf 1000ms.
Sprich, was das angeht, gibt es zwischen dem Internet-Profil und dem Datacenter-Profil, überhaupt keine Verhaltensunterschiede. 😉

Beste Grüsse aus BaWü
Alex

@AloisKraus
Copy link

AloisKraus commented Mar 23, 2023

@MysticFoxDE: Sorry das sehe ich jetzt erst. Aber irgendwann muss nach InitialRto die MinRto greifen.
Sonst würden die 20ms ja keinen Sinn machen. Greift die InitialRto nur für den TCP Handshake und wird dann die echte MinRto genommen? Dann würde das auch Sinn machen was ich in den ETW Retransmission Daten sehe.

PS> Get-NetTCPSetting


SettingName                     : Automatic
...

SettingName                     : Datacenter
MinRto(ms)                      : 20
InitialCongestionWindow(MSS)    : 10
CongestionProvider              : CUBIC
CwndRestart                     : False
DelayedAckTimeout(ms)           : 10
DelayedAckFrequency             : 2
MemoryPressureProtection        : Enabled
AutoTuningLevelLocal            : Normal
AutoTuningLevelGroupPolicy      : NotConfigured
AutoTuningLevelEffective        : Local
EcnCapability                   : Disabled
Timestamps                      : Disabled
InitialRto(ms)                  : 1000
ScalingHeuristics               : Disabled
DynamicPortRangeStartPort       : 49152
DynamicPortRangeNumberOfPorts   : 16358
AutomaticUseCustom              : Disabled
NonSackRttResiliency            : Disabled
ForceWS                         : Enabled
MaxSynRetransmissions           : 4
AutoReusePortRangeStartPort     : 0
AutoReusePortRangeNumberOfPorts : 0

zudem ist es genau das was ich mit Wireshark sehe:

  • Einen Haufen retransmits mit 20ms vom Server zum Client.

Das ist auch was ich mit dem ETW Provider sehe:

image

Das sollten alle Settings sein die da eine Rolle spielen.

@MysticFoxDE
Copy link
Owner

MysticFoxDE commented Mar 28, 2023

Moin @AloisKraus,

sorry für die späte Antwort, was die letzten Tage viel unterwegs und die nächsten sieht es leider auch nicht besser aus.

Aber irgendwann muss nach InitialRto die MinRto greifen.

Die MinRto greift so weit ich das bisher verstanden habe nur bei der Initialisierung der TCP-Session.
Und zwar wird bei der Initialisierung der TCP-Session, sprich beim TCP-Handshake die RTO zwischen den beiden Endpunkten ermittelt und anhand dieser RTO, weist der TCP-Stack in Windows dieser Session das entsprechende TCP-Profil zu.
Beim Server 2019/2022 wird daher bei einer RTO von < 10ms per default das Datacenter Profil gewählt und bei einer RTO <300ms, das Internet TCP-Profil. Was bei einer RTO >300ms geschieht weiss ich ehrlich gesagt nicht wirklich.
Und bei Windows 10/11 wählt der TCP-Stack leider eben immer stur das Internetprofil. 😔

Die InitialRto ist so gesehen nur der Timeout für eine erneute Übermittlung.
Sprich, wenn das vorherige TCP-Paket innerhalb dieser Zeit nicht quittiert wurde, dann wird es eben erneut gesendet und zwar gemäss der "MaxSynRetransmissions" bis zu 2 weitere Mal und erst wenn auch der dritte Versuch nicht gefruchtet hat, wird/sollte die Session nach 3000ms dann automatisch gekillt/neuaufgebaut werden.

@rscheff
Bitte korrigieren, falls ich groben Unfug erzähle, danke. 🤪

zudem ist es genau das was ich mit Wireshark sehe:
Einen Haufen retransmits mit 20ms vom Server zum Client.

🤔, Drops alle 20ms, das ist schräg.

Hast du auf dieser Verbindung rein zufällig Flow Control aktiv und oder läuft die über ein LAG?

Tritt dieses Problem bei dir generell auf, oder erst nach Ausführung vom meinem Skript?

Ist da irgendwo ein Hyper-V oder VMware noch dazwischen?

Beste Grüsse aus BaWü
Alex

@rscheff
Copy link
Author

rscheff commented Mar 28, 2023

Naja, der Teil mit der Auswahl zw. Datacenter und Internet Profil stimmt - da gibts ein hardcoded Limit - je nach Version waren das 6 oder 10ms.

InitialRTO ist der Retransmission Timeout Wert wenn eine neue Session zu einem Server aufgebaut wird (und es im HostCache - falls vorhanden - kein besserer Wert von einer vorherigen Session vorhanden ist).

MinRTO ist der minimale Wert, den der dynamisch aus der RTT berechnete RTO Wert einer Session minimal haben darf (also auch im Datacenter kommt eine retransmission wegen eines Timeouts erst frühestens nach MinRTO Millisekunden. Ein RTO ist im Vergleich zu einer Fast Retransmission, eine Zäsur in der Evolution der TCP Session - daher will man das nicht unnötig und möglicherweise zu früh machen. Nach einem RTO müssen viele dynamische Zustandsvariablen von TCP erst wieder neu aufgebaut und angepasst werden. Daher machen viele Stacks auch ein Rollback, falls ein RTO nicht notwendig gewesen wäre (mit verschiedenen Mechanismen um das zu detektieren).

Andererseits, die meisten Stacks haben nur sehr limitierte Möglichkeiten, sich von nochmals verlorene Fast Retransmissions zu erholen (Linux Lost Retransmission Detection, TCP RACK) - beziehungsweise nur unter bestimmten Umständen (Tail Loss Probe, Rescue Retransmission). D.h. eine Retransmission aufgrund des RTO Timers ist die Ultimate Methode, wie TCP dann doch noch versucht, Daten zwischen den beiden Hosts ausgetauscht zu bekommen.

Und da natürlich eine einzelne Retransmission wegen RTO auch wieder verloren gehen kann, wird hier - mit jeweils verdoppeltem Intervall - das Packet weiter versucht zu senden.

Und da muß man noch Unterscheiden zwischen Retransmissions während des 3WHS (wo noch nicht viel passiert ist, und der Client schneller aufgibt, und der erfolglose Versuch an die Applikation gemeldet wird), und während der Datenübertragung - wo es potentiell viel mehr Folgeprobleme geben kann. Viele Stacks verdoppeln das RTO Intervall auf bis zu 60 sekunden, und versuchen es dann für bis zu 15 oder 30 Minuten lang - wenn die Applikation nicht vorher in ein Timeout von sich aus läuft.

Lost Retransmission Detection selbst ist ein RFC Standard, sondern ein "Emerging Property" von der Art und Weise, wie ein Packetorientierter Stack (Linux) Buch über einzelne gesendete Packete führt. Und modernere Varianten von TCP (RACK - Recent ACKnowledgment) können ebenfalls "beliebig häufig" ein wiederholt verlorenes Packet erneut im Rahmen einer Fast Retransmission senden.

Aber klassische Stacks (Cubic, NewReno, Compound, DCTCP) eben nicht - für Transaktionale Sessions, die eben lokal sehr häufig sind, sehen einen direkten Latenzeinfluss basierend auf dem Wert von MinRTO - und in solchen schnellen Netzen sind potentiell unnötig wiederholt gesendete Packete, um die Latenz niedrig zu halten, viel weniger ein Thema als in einem 1980/1990iger Netzwerk.

Es gibt vermutlich mehrere tausend Papers, die alle gemeinsam haben, am RTO Wert herumzuschrauben, um Latenz im Datacenter zu minimieren.

Und wie auch ich anfangs gesagt habe - das Tuning an den ganzen Timern das das Skript macht, sind alles Dinge die im Rahmen eines "eigenen" Rechenzentrums nicht unvernünftig sind.

@MysticFoxDE
Copy link
Owner

MysticFoxDE commented Apr 6, 2023

Moin @rscheff,
als erstes einen herzlichen Dank für deine sehr ausführliche Antwort.

Naja, der Teil mit der Auswahl zw. Datacenter und Internet Profil stimmt - da gibts ein hardcoded Limit - je nach Version waren das 6 oder 10ms.

OK, kann es dann sein, dass dieses „hardcoded Limit“ im NetTransportFilter (Get-NetTransportFilter) hinterlegt ist?
Bei den Servern, ist per Default nämlich das „Automatic“ Profil hinterlegt und bei den Clients stur das „Internet“ Profil, welches sich auf diesen auch nicht auf „Automatic“ umstellen lässt. (🤢🤮 @microsoft)

InitialRTO ist der Retransmission Timeout Wert wenn eine neue Session zu einem Server aufgebaut wird (und es im HostCache - falls vorhanden - kein besserer Wert von einer vorherigen Session vorhanden ist).

Hast du nicht etwas Zeit übrig, um die Dokus von MS mal zu überarbeiten?
Deine Erklärungen verstehe ich auf jeden Fall um Welten besser als die von MS selbst. 👍👍👍
Das gilt übrigens insbesondere für den nächsten Punkt.

MinRTO ist der minimale Wert, den der dynamisch aus der RTT berechnete RTO Wert einer Session minimal haben darf (also auch im Datacenter kommt eine retransmission wegen eines Timeouts erst frühestens nach MinRTO Millisekunden. Ein RTO ist im Vergleich zu einer Fast Retransmission, eine Zäsur in der Evolution der TCP Session - daher will man das nicht unnötig und möglicherweise zu früh machen. Nach einem RTO müssen viele dynamische Zustandsvariablen von TCP erst wieder neu aufgebaut und angepasst werden. Daher machen viele Stacks auch ein Rollback, falls ein RTO nicht notwendig gewesen wäre (mit verschiedenen Mechanismen um das zu detektieren).
Andererseits, die meisten Stacks haben nur sehr limitierte Möglichkeiten, sich von nochmals verlorene Fast Retransmissions zu erholen (Linux Lost Retransmission Detection, TCP RACK) - beziehungsweise nur unter bestimmten Umständen (Tail Loss Probe, Rescue Retransmission). D.h. eine Retransmission aufgrund des RTO Timers ist die Ultimate Methode, wie TCP dann doch noch versucht, Daten zwischen den beiden Hosts ausgetauscht zu bekommen.
Und da natürlich eine einzelne Retransmission wegen RTO auch wieder verloren gehen kann, wird hier - mit jeweils verdoppeltem Intervall - das Packet weiter versucht zu senden.
Und da muß man noch Unterscheiden zwischen Retransmissions während des 3WHS (wo noch nicht viel passiert ist, und der Client schneller aufgibt, und der erfolglose Versuch an die Applikation gemeldet wird), und während der Datenübertragung - wo es potentiell viel mehr Folgeprobleme geben kann. Viele Stacks verdoppeln das RTO Intervall auf bis zu 60 sekunden, und versuchen es dann für bis zu 15 oder 30 Minuten lang - wenn die Applikation nicht vorher in ein Timeout von sich aus läuft.

😯 … OK, jetzt habe ich das mit der MinRTO glaube ich auch gerafft, danke.
Dann sollte ich diese in meinem Optimierungsskript beim „DatacenterCustom“ Profil auf jeden Fall auf ~150ms stellen, da dieses Profil nach dem Ausführen meines Skripts für sämtliche Verbindungen, sprich auch die Richtung Internet/WAN ja auch genutzt wird.

Und wie auch ich anfangs gesagt habe - das Tuning an den ganzen Timern das das Skript macht, sind alles Dinge die im Rahmen eines "eigenen" Rechenzentrums nicht unvernünftig sind.

Ich wollte ja auch primär nur den Datenverehr innerhalb des eigenen Intranets verbessern und nicht pauschal das Verhalten von sämtlichem Datenverkehr beeinflussen. Jedoch ist leider das erstere bei Windows 10 und 11, aktuell ohne das letztere nicht möglich.
Daher bleibt momentan nicht viel übrig, als ein Mittelding für beide Welten (Intranet/Internet) zu finden und nein zufrieden bin ich mit diesem Zustand auch nicht wirklich.

Beste Grüsse aus BaWü
Alex

P.S. Anreas, das ist die fachlichste Unterhaltung die ich jemals mit jemandem zu diesem Thema gehabt habe, daher nochmals herzlichsten Dank für deine Mühen und vor allem der Geduld mit mir.
Mir ist durchaus bewusst, dass ich manchmal auch etwas "schwierig/kompliziert" sein kann.
Aber so sind wir, die alten IT-Hasen ... ähm und natürlich auch die IT-Füchse eben. 🤪

@MysticFoxDE
Copy link
Owner

Moin @rscheff,

und das ist jetzt mal wieder der beste Beweis für die hinterhältige Kastration/Bevormundung durch Microsoft. 😠

MINRTO-PS

MINRTO-CMD

Sprich, so ohne Weiteres lässt sich die MinRto bei Windows 10/11, weder beim DatacenterCustom, noch bei den anderen Profilen ändern. 😭
Na ja, halb so wild, zum Glück weiss ich, wie man die MinRto auch über die Registry ändern kann. 😎

Beste Grüsse aus BaWü
Alex

@AloisKraus
Copy link

@MysticFoxDE: Dann würde ich das Advertising wann man dein Skript nehmen sollte ändern. Es ist ok das für GBit+ lokale Netzwerke zu machen.

Wenn man aber per Google Suche nach: "dieses Script macht dein Internet schneller" vorbei kommt könnte das gegenteilige Effekte haben. Was Du da machst ist das absolute fine tuning für in-house RZ Infrastruktur wo viele verschiedene Probleme addressiert werden.
Nicht alles sollte über Konfiguration des TCP Stacks gemacht werden.
Z.B. die Remote Desktop Probleme sind interessant, aber da RDP auch UDP als Transport Protokol supported kann man das auch ohne Rekonfiguration am TCP Stack lösen.

@MysticFoxDE
Copy link
Owner

MysticFoxDE commented Apr 12, 2023

Moin @AloisKraus,

"Dann würde ich das Advertising wann man dein Skript nehmen sollte ändern. Es ist ok das für GBit+ lokale Netzwerke zu machen."

ich habe das Skript ja auch Ursprünglich für die Beschleunigung des lokalen Datenverkehrs erstellt, dass es auch den Datenverkehr in die Richtung des WAN's/Internets zum Teil massiv verbessert, ist erst im Nachgang rausgekommen und zwar durch das Feedback der entsprechenden Enduser. 😁

Was ich übrigens sehr spannend finde ist die Tatsache, dass bei deinem Datacenter Profil die MinRto per Default auf 20ms steht und bei meinem Datacenter Profil per Default auf 60ms.

MINRTO

Was ist das jetzt wieder für ein MS-Murks?🤔

Ich habe Windows 11 Enterprise 22H2.
Von welchem OS kommt die Info aus dem folgenden Post?
#9 (comment)

Wenn man aber per Google Suche nach: "dieses Script macht dein Internet schneller" vorbei kommt könnte das gegenteilige Effekte haben. Was Du da machst ist das absolute fine tuning für in-house RZ Infrastruktur wo viele verschiedene Probleme addressiert werden.

Das mit "dieses Script macht dein Internet schneller" kommt aber ganz sicher nicht von mir. 😉

Nicht alles sollte über Konfiguration des TCP Stacks gemacht werden.
Z.B. die Remote Desktop Probleme sind interessant, aber da RDP auch UDP als Transport Protokol supported kann man das auch ohne Rekonfiguration am TCP Stack lösen.

Ja, RDP kann auch über UDP laufen und mach es übrigens auch standardmäßig so.
Ist aber in vielen Fällen ein riesiger Mist und daher stellen wir das bei allen RDS-Umgebungen auch gleich wieder auf TCP um.

Beste Grüsse aus BaWü
Alex

@rscheff
Copy link
Author

rscheff commented Apr 12, 2023

Der Delayed ACK timer ist meistens in der Größenordnung von 40 ms; MinRTO kleiner als DelayedACK zu setzen ist kontraproduktiv (zu viele spurious retransmission timeouts). Wenn man beides gleichzeitig justieren kann (zb delayedACK auf 1ms, dann spricht auch nichts dagegen, MinRTO entsprechend zu verringern.

Wenn man aber die andere Seite nicht kontrolliert, sollte man MinRTO über dem zu erwarteten RTT + DelayedACK delay belassen, um nicht exzessiv viele spurious RTOs einzufangen.

@MysticFoxDE
Copy link
Owner

MysticFoxDE commented Apr 12, 2023

Moin @rscheff,

Der Delayed ACK timer ist meistens in der Größenordnung von 40 ms.

Ja, im Internetprofil von Windows 10&11 welches wie schon mehrfach angesprochen per default bei jeder TCP Verbindung benutzt wird ist das auch genau so und daher wir auch jeder ACK, sprich auch die des LAN Datenverkehrs, dessen RTO oft unter 1ms liegt, um bis zu 40ms absolut unnötig verzögert. 🤢
Das ist insbesondere bei kleinen Transaktionen ein absoluter Performancekiller.

MinRTO kleiner als DelayedACK zu setzen ist kontraproduktiv (zu viele spurious retransmission timeouts).

😁, ja das kann ich gut nachvollziehen.
Sprich, man würde dadurch im schlimmsten Fall unnötig mehrfach schiessen, obwohl man schon beim ersten Mal getroffen hat. 🤪

Wenn man beides gleichzeitig justieren kann (zb delayedACK auf 1ms, dann spricht auch nichts dagegen, MinRTO entsprechend zu verringern.

Na ja, eigentlich bin ich überhaupt kein Freund von delayedACK, weil es in der Welt wo ich mich hauptsächlich bewege, einfach nur als Latenzgenerator fungiert. 😔
Schau dir einfach mal auf einem Windows-Client im Ressourcenmonitor bei Netzwerk die Latenzen einer über das Netzwerk gestarteten Anwendung mal genauer an und dann siehst du gleich was ich meine. 😉

Sehe ich das korrekt, dass wenn ich kein delayedACK verwende, die MinRTO dann auch etwas grösser ausfallen kann, da dadurch lediglich im Falle eine Fehlers (was im Besten Fall sehr selten passiert) die erneute Übertragung etwas länger hinausgezögert wird?

Wenn man aber die andere Seite nicht kontrolliert, sollte man MinRTO über dem zu erwarteten RTT + DelayedACK delay belassen, um nicht exzessiv viele spurious RTOs einzufangen.

Na ja, ich kann die MinRTO bei einem Windows-Client aktuell überhaupt nicht nachträglich verändern. 🤮🤮🤮
Der Trick mit der Registry klappt leider (noch) nicht so wie ich es gewünscht hatte. 😭
Na ja, muss nur mal rausfiesseln wo der Server 2019/2022 die Einstellung ablegt und das dann dasselbe auf den Client, der Kerneltechnisch ja eh >99% dasselbe ist, übertragen. 😁

Beste Grüsse aus BaWü
Alex

@rscheff
Copy link
Author

rscheff commented Apr 12, 2023

Es ist und bleibt ein multidimensionales Optimierungsproblem - und die Antwort in einem Fall ist vermutlich nicht die Antwort in einem anderen Fall - oder je mehr man für eine bestimmte Umgebung optimiert, desto schlechter wird es unter anderen Umgebungsbedingungen.

Es gibt dutzende Papers dazu, wie man durch ausschalten von DelayedAck die Latenz insbesondere von RPC Traffic optimieren kann. Allerdings kostet ein ACK sowohl CPU beim Senden, wie auch Bandbreite beim Übertragen; Es gibt nach wie vor Strecken im Internet, wo der ACK overhead (64 vs. 1518 Bytes, oder 4,2%) ohne Delayed ACK, oder 2,1% mit klassischen Delayed ACKs (jedes 2. Packet) ein Problem darstellt - und Mechanismen wie Ack Thinning oder Ack Bunching zum Einsatz kommen (WiFi ARQ). Am anderen Ende des Spektrums, wenn man GB/sec Datenströme hat, braucht es vielleicht nur 1 ACK alle tausend Packete, um alles am Laufen zu halten... (Minimal sollte man nicht weniger als rund 2-3 ACKs pro RTT haben).

Wenn das Netz ideal lossless ist, kann man MinRTO beliebig groß setzen (FC Protokolle haben equivalente timer zwischen 3 und 15 sec). Aber solange man congestion / error losses nicht ausschliessen kann - weiß man vorher nicht, wann ein RTO notwendig ist.

Der RTO wird auch dynamisch, abhängig von RTT und Jitter berechnet - MinRTO gibt nur das untere Limit an, unter das dieser dynamisch berechnete Wert nicht weiter sinken sollte (zB wegen Delayed ACKs, wenn der RPC IO mit einem Volley an Packeten dann am "falschen" (ungeraden) Packet endet).

Parallel gibts auch Weiterentwicklungen wie RACK, die unter solchen Bedingungen dann proaktiv "ungerade" Packete rasch (1,5x RTT, << RTO) nochmal senden, und damit dann ein ACK triggern (quasi ein DupAck eines noch nicht gesendeten Acks).

In dem Bereich gibts weiterhin viele Ideen, und nur wenige sind in der Fläche und auf den meisten OS vorhanden (und klar gibts dann auch immer Implementationsdetails und Bugs; das DCTCP zB deutlich latenzärmer unterwegs ist als Cubic, in einem sonst Fehlerfreien Netz ohne Congestion, ist unerwartet und wohl ausschliesslich auf die Implementierung (Wieviele Cachelines bleiben wie heiß, während der Abarbeitung jedes Packets) zurückzuführen - DCTCP mit NewReno CC ist wohl weniger CPU intensiv als Cubic, und braucht auch weniger Zustandsdaten...

@AloisKraus
Copy link

Die 40ms kommen von Windows 10 und Server 2019. Bei Server 2022 ist MinRTO 60ms. Ja die schrauben da ständig daran rum. Wahrscheinlich gab es doch zu viele Beschwerden aus realen Netzwerken, dass das Datacenter Profil das Netzwerk mit Retransmissions zugemüllt hat.
Um da mehr zu erfahren müsstest Du einen Call bei MS aufmachen.

@MysticFoxDE
Copy link
Owner

MysticFoxDE commented Apr 12, 2023

Moin @AloisKraus,

"Die 40ms kommen von Windows 10 und Server 2019. Bei Server 2022 ist MinRTO 60ms"

da passen jetzt aber zwei Dinge nicht zusammen, zum Einen ist in deinem Screenshot eine MinRTO von 20ms abgebildet.

MINRTO-ALOIS

Und zum Anderen haben alle unseren 2019er Server auch eine MinRTO von 60ms im Datacenter Profil hinterlegt.

MINRTO-2019

???

Ja die schrauben da ständig daran rum.

Ja, und leider sehr oft nicht zu unserem Vorteil. 😔

Wahrscheinlich gab es doch zu viele Beschwerden aus realen Netzwerken, dass das Datacenter Profil das Netzwerk mit Retransmissions zugemüllt hat.

Das Datacenter Profil wird wie ich schon mehrfach geschrieben habe normalerweise nur auf den Servern verwendet und das nur bei Verbindungen, deren RTT niedrig genug ist. Und eine MinRTO von 20ms ist für ein Intranet, dessen RTT meist unter 1ms liegen sollte, nun auch kein Beinbruch.

Jedoch ist eine MinRTO von 20ms definitiv zu klein, um pauschal das Datacenter oder DatacenterCustom Profil für sämtlichen Datenverkehr zu verwenden. 😬
Na ja, entweder bekomme ich es hin die MinRTO des Datacenter, respektive DatacenterCustom Profils auf 100ms oder 150ms anzuheben, dann kann man dieses weiterhin "pauschal" für Intranet/Internet verwenden oder ich muss eine Prüfung ins Skript einbauen und bei einem zu geringen MinRTO Wert des vorhandenen Datacenter Profils, den Wechsel zu diesem überspringen.

Ist eigentlich nicht wirklich wild, den die Dinge die ich im DatacenterCostom Profil durch mein Skript anpasse, kann ich auch genau so gut direkt im Internet Profil ändern. Sprich, es gibt auf jeden Fall auch noch einen Plan B. 😁
Dann spring mir Richard glaube ich aber vollends ins Genick, wenn ich DCTCP und ECN direkt auf dem Internet Profil aktiviere. 🤪

Um da mehr zu erfahren müsstest Du einen Call bei MS aufmachen.

Nein, mit Call's bei MS bin ich für eine Weile erstmal wieder durch, ich brache meine Nerven auch noch für andere, vor allem sinnvollere Dinge.

Beste Grüsse aus BaWü
Alex

@MysticFoxDE
Copy link
Owner

Moin @rscheff,

ähm ... Richard ... du darfs mir jetzt bitte nicht böse sein, aber ich habe gerade das machen müssen, was ich in meinem letzten Post schon vorsichtshalber angekündigt habe.
Ich habe das Skript jetzt so umgebaut, dass es nicht mehr auf DatacenterCustom schwenkt, sondern habe im per default verwendeten Internet Profil, von CUBIC auf DCTCP geswitcht und ECN aktiviert.
Der Hintergrund ist, dass bei Windows 10 & 11 die MinRto in den TCP Profilen nicht mehr von Hand angepasst werden kann,
weil diese Microsoftianer das so wie es aussieht hart reincodiert haben. 🤢🤮
Die MinRto des Datacenter und auch DatacenterCustom Profils ist aber insbesondere bei einigen Windows 10 Versionen mit 20ms zu gering um diese Pauschal für alle Verbindungen zu verwenden.
Daher blieb mit im Sinnen einer bestmöglichen Lösung für beide Welten (Intranet/Internet) auch nichts anderes übrig. 😔

Beste Grüsse aus BaWü
Alex

@MysticFoxDE
Copy link
Owner

Moin @AloisKraus,

probiere mal die V2.01 aus, damit sollte dein Problem behoben sein. 😉

Beste Grüsse aus BaWü
Alex

@AloisKraus
Copy link

@MysticFoxDE: Danke! Das ist alles sehr interessant, aber ich bevorzuge es dann etwas zu ändern wenn ich ein Problem habe. Solange ich meine 100 MBit/s auslasten kann und RDP sauber funktioniert ist das erst mal ok. Wenn ich ein Problem habe, dann messe ich erst mal mit ETW um zu sehen woher das kommt. Bisher hatte ich in dieser Ecke noch keine Probleme. Aber die Diskussion hier hat mir sehr geholfen das Thema besser zu verstehen und die Doku zu verbessern:

https://github.com/Siemens-Healthineers/ETWAnalyzer/blob/main/ETWAnalyzer/Documentation/DumpTCPCommand.md

Feedback ist immer willkommen. Netzwerk Monitoring in verteilten System wird immer wichtiger. Das Applikationsverhalten auf CPU/Disk/File/DNS und jetzt auch TCP zusammenzubringen hilft sehr.

@MysticFoxDE
Copy link
Owner

Moin Alois,

Das Applikationsverhalten auf CPU/Disk/File/DNS und jetzt auch TCP zusammenzubringen hilft sehr.

und ist auch extrem wichtig und zwar zusammen (CPU/RAM/STORAGE/TCP/ETHERNET/SMB & Co.KG) und nicht einzeln für sich betrachtet.

Denn sehr oft hat man bei Netzwerkübertragungen keinen Durchsatz oder zu schlechte Latenzen, weil die CPU des Clients und oder des Servers, z.B. durch unnütze Features zu sehr ausgelastet sind.
Oder das Dateisystem liefert keine anständige Leistung, weil es über ein Software-RAID realisiert wurde.
Oder, oder, oder ... TCP ist hierbei leider nur einer der möglichen Stolpersteine, aber ein sehr wesentlicher. 😔

Beste Grüsse aus BaWü
Alex

@MysticFoxDE
Copy link
Owner

MysticFoxDE commented Apr 24, 2023

Moin @rscheff,

Richard, hast du vielleicht eine Idee, warum ich mit iperf3 nicht mehr wie 30 aktive TCP Sessions aufbauen kann, über die auch Daten gesendet werden können?

Details siehe hier ...
#17 (comment)

Ich sehe hier einen möglichen Zusammenhang zu einigen anderen Problemen.

Gibt es bei Windows eventuell eine Schutzfunktion, die die aktiven Sessions einer EXE einschränkt?

Herzlichen Dank im Voraus.

Beste Grüsse aus BaWü
Alex

P.S. Ich habe übrigens diverse IPerf3 Versionen versucht und bei allen geschieht dasselbe.

@rscheff
Copy link
Author

rscheff commented Apr 24, 2023 via email

@MysticFoxDE
Copy link
Owner

Moin @rscheff,

Ich würde erst mal den Source Code von iperf3 prüfen

😬 ... dafür fehlen mir sowohl die Kenntnisse als auch die Ressourcen.

oder ggf die Windows APIs durchforschen, welche Merkwürdigkeiten dort bei Threading und Socket API versteckt sind.

das hört sich schon eher machbar an.

Ich nutze Windows nicht wirklich für professionelle Anwendungen.

Und ich muss es nutzen, weil es auch unsere Kunden benutzen (müssen).

Ich habe bei dieser Anfrage eher darauf gehofft dass du eventuell mit alla "Ja, das könnte an der oder der TCP Schutzfunktion liegen." um die Ecke kommen würdest.

Beste Grüsse aus BaWü
Alex

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants