On Wed, 29 Mar 2023 11:28:53 GMT, Aleksey Shipilev <sh...@openjdk.org> wrote:

> Java API has the `Thread.sleep(millis, nanos)` method exposed to users. The 
> documentation for that method clearly says the precision and accuracy are 
> dependent on the underlying system behavior. However, it always rounds up 
> `nanos` to 1ms when doing the actual sleep. This means users cannot do the 
> micro-second precision sleeps, even when the underlying platform allows it. 
> Sub-millisecond sleeps are useful to build interesting primitives, like the 
> rate limiters that run with >1000 RPS.
> 
> When faced with this, some users reach for more awkward APIs like 
> `java.util.concurrent.locks.LockSupport.parkNanos`. The use of that API for 
> sleeps is not in line with its intent, and while it "seems to work", it might 
> have interesting interactions with other uses of `LockSupport`. Additionally, 
> these "sleeps" are no longer visible to monitoring tools as "normal sleeps", 
> e.g. as `Thread.sleep` events. Therefore, it would be prudent to improve 
> current `Thread.sleep(millis, nanos)` for sub-millisecond granularity. 
> 
> Fortunately, the underlying code is almost ready for this, at least on POSIX 
> side. I skipped Windows paths, because its timers are still no good. Note 
> that on both Linux and MacOS timers oversleep by about 50us. I have a few 
> ideas how to improve the accuracy for them, which would be a topic for a 
> separate PR.
> 
> Additional testing:
>   - [x] New regression test
>   - [x] New benchmark
>   - [x] Linux x86_64 `tier1`
>   - [x] Linux AArch64 `tier1`

Motivational improvements on new benchmark below:

m6g.9xlarge (Linux, Xeon, x86_64):


Benchmark                 (sleep)  Mode  Cnt           Score       Error  Units

# ========= no regressions for Thread.sleep(millis)

# Baseline
ThreadSleep.millis             0  avgt    5         463.606 ±     8.256  ns/op
ThreadSleep.millis             1  avgt    5         459.434 ±     0.453  ns/op
ThreadSleep.millis            10  avgt    5         462.828 ±     1.283  ns/op
ThreadSleep.millis           100  avgt    5         459.495 ±     3.244  ns/op
ThreadSleep.millis          1000  avgt    5         457.962 ±     5.769  ns/op
ThreadSleep.millis         10000  avgt    5         457.960 ±     1.195  ns/op
ThreadSleep.millis        100000  avgt    5         459.197 ±     3.054  ns/op
ThreadSleep.millis       1000000  avgt    5     1058342.873 ±   304.169  ns/op
ThreadSleep.millis      10000000  avgt    5    10059945.148 ±  1642.411  ns/op
ThreadSleep.millis     100000000  avgt    5   100062181.340 ±  1863.186  ns/op
ThreadSleep.millis    1000000000  avgt    5  1000070015.600 ± 11379.631  ns/op

# Patched
ThreadSleep.millis             0  avgt    5         461.295 ±     6.700  ns/op
ThreadSleep.millis             1  avgt    5         463.383 ±     3.065  ns/op
ThreadSleep.millis            10  avgt    5         468.109 ±     1.607  ns/op
ThreadSleep.millis           100  avgt    5         467.316 ±     0.270  ns/op
ThreadSleep.millis          1000  avgt    5         461.999 ±     2.341  ns/op
ThreadSleep.millis         10000  avgt    5         465.075 ±     0.324  ns/op
ThreadSleep.millis        100000  avgt    5         462.588 ±     5.321  ns/op
ThreadSleep.millis       1000000  avgt    5     1058285.440 ±   409.376  ns/op
ThreadSleep.millis      10000000  avgt    5    10060437.490 ±   177.754  ns/op
ThreadSleep.millis     100000000  avgt    5   100060665.980 ±  1167.514  ns/op
ThreadSleep.millis    1000000000  avgt    5  1000071917.300 ± 17438.906  ns/op

# ========= Significant improvements for Thread.sleep(millis, nanos)

# Baseline
ThreadSleep.millisNanos           0  avgt    5         462.831 ±     0.251  
ns/op
ThreadSleep.millisNanos           1  avgt    5     1058708.668 ±   960.683  
ns/op
ThreadSleep.millisNanos          10  avgt    5     1058364.414 ±   197.700  
ns/op
ThreadSleep.millisNanos         100  avgt    5     1058451.889 ±   561.979  
ns/op
ThreadSleep.millisNanos        1000  avgt    5     1058372.010 ±    96.867  
ns/op
ThreadSleep.millisNanos       10000  avgt    5     1058354.100 ±   297.148  
ns/op
ThreadSleep.millisNanos      100000  avgt    5     1058485.092 ±  1093.340  
ns/op
ThreadSleep.millisNanos     1000000  avgt    5     1059004.036 ±  1899.950  
ns/op
ThreadSleep.millisNanos    10000000  avgt    5    10059733.302 ±  1725.908  
ns/op
ThreadSleep.millisNanos   100000000  avgt    5   100063327.840 ±  6244.805  
ns/op
ThreadSleep.millisNanos  1000000000  avgt    5  1000074542.300 ± 17898.173  
ns/op

# Patched
ThreadSleep.millisNanos           0  avgt    5         467.968 ±     9.202  
ns/op
ThreadSleep.millisNanos           1  avgt    5         579.448 ±     1.363  
ns/op
ThreadSleep.millisNanos          10  avgt    5         577.656 ±     0.278  
ns/op
ThreadSleep.millisNanos         100  avgt    5       58092.815 ±  2410.401  
ns/op
ThreadSleep.millisNanos        1000  avgt    5       58592.249 ±   189.232  
ns/op
ThreadSleep.millisNanos       10000  avgt    5       67668.688 ±   591.365  
ns/op
ThreadSleep.millisNanos      100000  avgt    5      158143.164 ±  2281.540  
ns/op
ThreadSleep.millisNanos     1000000  avgt    5     1058508.682 ±   155.767  
ns/op
ThreadSleep.millisNanos    10000000  avgt    5    10059979.272 ±  1095.207  
ns/op
ThreadSleep.millisNanos   100000000  avgt    5   100066844.180 ±  4287.440  
ns/op
ThreadSleep.millisNanos  1000000000  avgt    5  1000075313.100 ±  9665.656  
ns/op


m6g.4xlarge (Linux, Graviton, AArch64):


# ========= no regressions for Thread.sleep(millis)

# Baseline
ThreadSleep.millis             0  avgt    5         429.403 ±    24.947  ns/op
ThreadSleep.millis             1  avgt    5         427.533 ±     7.969  ns/op
ThreadSleep.millis            10  avgt    5         438.464 ±    10.277  ns/op
ThreadSleep.millis           100  avgt    5         425.626 ±     3.371  ns/op
ThreadSleep.millis          1000  avgt    5         426.465 ±     4.501  ns/op
ThreadSleep.millis         10000  avgt    5         427.235 ±     6.916  ns/op
ThreadSleep.millis        100000  avgt    5         430.311 ±     4.073  ns/op
ThreadSleep.millis       1000000  avgt    5     1054808.881 ±   469.409  ns/op
ThreadSleep.millis      10000000  avgt    5    10055497.206 ±  2123.591  ns/op
ThreadSleep.millis     100000000  avgt    5   100059355.520 ± 11597.426  ns/op
ThreadSleep.millis    1000000000  avgt    5  1000073145.400 ±  7659.244  ns/op

# Patched
ThreadSleep.millis             0  avgt    5         429.535 ±     2.597  ns/op
ThreadSleep.millis             1  avgt    5         425.209 ±     3.620  ns/op
ThreadSleep.millis            10  avgt    5         432.416 ±     9.350  ns/op
ThreadSleep.millis           100  avgt    5         432.867 ±     3.978  ns/op
ThreadSleep.millis          1000  avgt    5         426.627 ±     1.064  ns/op
ThreadSleep.millis         10000  avgt    5         427.180 ±     4.691  ns/op
ThreadSleep.millis        100000  avgt    5         438.554 ±     4.271  ns/op
ThreadSleep.millis       1000000  avgt    5     1054693.226 ±   323.240  ns/op
ThreadSleep.millis      10000000  avgt    5    10056408.240 ±  1759.211  ns/op
ThreadSleep.millis     100000000  avgt    5   100062449.780 ± 15133.808  ns/op
ThreadSleep.millis    1000000000  avgt    5  1000066918.500 ± 15817.822  ns/op

# ========= Significant improvements for Thread.sleep(millis, nanos)

# Baseline
ThreadSleep.millisNanos           0  avgt    5         439.163 ±     5.559  
ns/op
ThreadSleep.millisNanos           1  avgt    5     1054751.231 ±   431.842  
ns/op
ThreadSleep.millisNanos          10  avgt    5     1054640.725 ±   525.901  
ns/op
ThreadSleep.millisNanos         100  avgt    5     1054807.619 ±  1009.104  
ns/op
ThreadSleep.millisNanos        1000  avgt    5     1054894.829 ±  1946.551  
ns/op
ThreadSleep.millisNanos       10000  avgt    5     1054765.444 ±   701.873  
ns/op
ThreadSleep.millisNanos      100000  avgt    5     1054707.758 ±   619.054  
ns/op
ThreadSleep.millisNanos     1000000  avgt    5     1054802.230 ±  1294.035  
ns/op
ThreadSleep.millisNanos    10000000  avgt    5    10055265.430 ±  1184.281  
ns/op
ThreadSleep.millisNanos   100000000  avgt    5   100057484.300 ±  7960.939  
ns/op
ThreadSleep.millisNanos  1000000000  avgt    5  1000062244.700 ± 20244.067  
ns/op

# Patched
ThreadSleep.millisNanos           0  avgt    5         426.482 ±    10.284  
ns/op
ThreadSleep.millisNanos           1  avgt    5         565.819 ±     1.098  
ns/op
ThreadSleep.millisNanos          10  avgt    5         564.108 ±     3.493  
ns/op
ThreadSleep.millisNanos         100  avgt    5       53698.839 ±   942.506  
ns/op
ThreadSleep.millisNanos        1000  avgt    5       55205.929 ±   416.951  
ns/op
ThreadSleep.millisNanos       10000  avgt    5       64206.709 ±   382.213  
ns/op
ThreadSleep.millisNanos      100000  avgt    5      154477.045 ±   125.316  
ns/op
ThreadSleep.millisNanos     1000000  avgt    5     1054889.472 ±  2152.765  
ns/op
ThreadSleep.millisNanos    10000000  avgt    5    10055273.582 ±   691.628  
ns/op
ThreadSleep.millisNanos   100000000  avgt    5   100058261.300 ±  5222.946  
ns/op
ThreadSleep.millisNanos  1000000000  avgt    5  1000065434.000 ± 30213.137  
ns/op


MacBook 2021 (MacOS X, M1, AArch64):


# ========= no regressions for Thread.sleep(millis)

# Baseline
Benchmark                 (sleep)  Mode  Cnt           Score          Error  
Units
ThreadSleep.millis             0  avgt    5         555,871 ±      525,544  
ns/op
ThreadSleep.millis             1  avgt    5         405,761 ±      153,981  
ns/op
ThreadSleep.millis            10  avgt    5         403,906 ±      279,245  
ns/op
ThreadSleep.millis           100  avgt    5         402,787 ±      223,658  
ns/op
ThreadSleep.millis          1000  avgt    5         439,250 ±      374,150  
ns/op
ThreadSleep.millis         10000  avgt    5         435,769 ±      352,067  
ns/op
ThreadSleep.millis        100000  avgt    5        1853,664 ±     7254,716  
ns/op
ThreadSleep.millis       1000000  avgt    5     1364788,214 ±    66446,869  
ns/op
ThreadSleep.millis      10000000  avgt    5    11819681,019 ±   473810,685  
ns/op
ThreadSleep.millis     100000000  avgt    5   103536901,660 ±  1423282,032  
ns/op
ThreadSleep.millis    1000000000  avgt    5  1002995262,600 ±  6576388,880  
ns/op

# Patched
ThreadSleep.millis             0  avgt    5         662,597 ±     459,888  ns/op
ThreadSleep.millis             1  avgt    5         433,561 ±     214,850  ns/op
ThreadSleep.millis            10  avgt    5         388,614 ±      65,199  ns/op
ThreadSleep.millis           100  avgt    5         436,823 ±     636,901  ns/op
ThreadSleep.millis          1000  avgt    5         337,046 ±     129,440  ns/op
ThreadSleep.millis         10000  avgt    5         366,557 ±     510,494  ns/op
ThreadSleep.millis        100000  avgt    5         278,339 ±     102,443  ns/op
ThreadSleep.millis       1000000  avgt    5     1520092,133 ±   26217,972  ns/op
ThreadSleep.millis      10000000  avgt    5    13116509,001 ±  855508,621  ns/op
ThreadSleep.millis     100000000  avgt    5   107010708,340 ± 1667080,292  ns/op
ThreadSleep.millis    1000000000  avgt    5  1005412095,700 ± 6141267,753  ns/op

# ========= Significant improvements for Thread.sleep(millis, nanos)

# Baseline
ThreadSleep.millisNanos           0  avgt    5         245,942 ±       44,338  
ns/op
ThreadSleep.millisNanos           1  avgt    5     1313354,886 ±    71820,989  
ns/op
ThreadSleep.millisNanos          10  avgt    5     1310358,568 ±    42731,583  
ns/op
ThreadSleep.millisNanos         100  avgt    5     1335221,078 ±   122031,471  
ns/op
ThreadSleep.millisNanos        1000  avgt    5     1313977,625 ±    30683,810  
ns/op
ThreadSleep.millisNanos       10000  avgt    5     1553321,472 ±    75181,324  
ns/op
ThreadSleep.millisNanos      100000  avgt    5     1553317,573 ±   132998,558  
ns/op
ThreadSleep.millisNanos     1000000  avgt    5     1544944,015 ±    41587,129  
ns/op
ThreadSleep.millisNanos    10000000  avgt    5    13228565,376 ±   902384,381  
ns/op
ThreadSleep.millisNanos   100000000  avgt    5   106866740,840 ±  2518606,524  
ns/op
ThreadSleep.millisNanos  1000000000  avgt    5  1006669020,800 ± 10961093,568  
ns/op

# Patched
ThreadSleep.millisNanos           0  avgt    5         394,716 ±     310,886  
ns/op
ThreadSleep.millisNanos           1  avgt    5        9945,543 ±     905,136  
ns/op
ThreadSleep.millisNanos          10  avgt    5        9863,605 ±     557,909  
ns/op
ThreadSleep.millisNanos         100  avgt    5        2454,862 ±     323,279  
ns/op
ThreadSleep.millisNanos        1000  avgt    5        3834,507 ±    2427,033  
ns/op
ThreadSleep.millisNanos       10000  avgt    5       16667,415 ±     508,814  
ns/op
ThreadSleep.millisNanos      100000  avgt    5      154202,589 ±     258,406  
ns/op
ThreadSleep.millisNanos     1000000  avgt    5     1557886,136 ±  192080,832  
ns/op
ThreadSleep.millisNanos    10000000  avgt    5    13077385,237 ±  887650,194  
ns/op
ThreadSleep.millisNanos   100000000  avgt    5   106225257,480 ± 3288589,410  
ns/op
ThreadSleep.millisNanos  1000000000  avgt    5  1006589558,200 ± 3677828,811  
ns/op

-------------

PR Comment: https://git.openjdk.org/jdk/pull/13225#issuecomment-1488989224

Reply via email to