[ 
https://issues.apache.org/jira/browse/IGNITE-20869?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Vladislav Pyatkov updated IGNITE-20869:
---------------------------------------
    Description: 
h3. Motivation
[This 
|https://github.com/apache/ignite-3/blob/82c74598b5006ea3e4e86da744a68022dd799c89/modules/network/src/main/java/org/apache/ignite/network/DefaultMessagingService.java#L254-L255]line
 of code cost us near the 3us from the 26us of the whole query (~10%). The 
reason is the orTimeout(...) call.

The simple switch to the simple new CompletableFuture() gives us a 10% boost 
from 26us/s to 23us/s in the 1-node fsync=false run of SelectBenchmark.kvGet.

{code}
responseFuture.orTimeout(timeout, TimeUnit.MILLISECONDS);
{code}
The code spends 3 microseconds or more.

The note above is absolutely correct and appropriate for put operation as well.
Next, I want to notice all the places where `orTimeput` is used in the hot 
path: 
* _LeaseTracker#awaitPrimaryReplica_ Althogh at this place, the future usually 
is completed, we call `orTimout` in any way.
* _DefaultMessagingService#invoke0_ It is not a network timeout (despite the 
fact that it is set in the network layer), but this is an important timeout for 
application code.
* The _IgniteRpcClient#invokeAsync_ Raft retry timeout is set here.
* _TcpClientChannel#serviceAsync_ Thin cluient operation timeout.

h3. Implementation notes
I compared an invocation `orTimeout` and a timeout worker implementation based 
on a dedicated thread with a concurrent queue:
{code}
Thread t = new Thread(() -> {
            TimeoutObject o;

            while (true) {
                o = queue.poll();

                if (o == null) {
                    try {
                        Thread.sleep(200);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }

                    continue;
                }

                if (System.currentTimeMillis() > o.timeout) {
                    o.onTimeout();
                } else {
                    queue.add(o);
                }

            }
        }, "timout-worker");
{code}
!screenshot-1.png|height=250,width=250!

h3. Definition of done
`orTimeout` method is not used in the operation hot (put/get e.t.c) path.

  was:
h3. Motivation
[This 
|https://github.com/apache/ignite-3/blob/82c74598b5006ea3e4e86da744a68022dd799c89/modules/network/src/main/java/org/apache/ignite/network/DefaultMessagingService.java#L254-L255]line
 of code cost us near the 3us from the 26us of the whole query (~10%). The 
reason is the orTimeout(...) call.

The simple switch to the simple new CompletableFuture() gives us a 10% boost 
from 26us/s to 23us/s in the 1-node fsync=false run of SelectBenchmark.kvGet.

{code}
responseFuture.orTimeout(timeout, TimeUnit.MILLISECONDS);
{code}
The code spends 3 microseconds or more.

The note above is absolutely correct and appropriate for put operation as well.
Next, I want to notice all the places where `orTimeput` is used in the hot 
path: 
* _LeaseTracker#awaitPrimaryReplica_ Althogh at this place, the future usually 
is completed, we call `orTimout` in any way.
* _DefaultMessagingService#invoke0_ It is not a network timeout (despite the 
fact that it is set in the network layer), but this is an important timeout for 
application code.
* The _IgniteRpcClient#invokeAsync_ Raft retry timeout is set here.
* _TcpClientChannel#serviceAsync_ Thin cluient operation timeout.

h3. Implementation notes
I compared an invocation `orTimeout` and a timeout worker implementation based 
on a dedicated thread with a concurrent queue:
{code}
Thread t = new Thread(() -> {
            TimeoutObject o;

            while (true) {
                o = queue.poll();

                if (o == null) {
                    try {
                        Thread.sleep(200);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }

                    continue;
                }

                if (System.currentTimeMillis() > o.timeout) {
                    o.onTimeout();
                } else {
                    queue.add(o);
                }

            }
        }, "timout-worker");
{code}
 !screenshot-1.png! 

h3. Definition of done
`orTimeout` method is not used in the operation hot (put/get e.t.c) path.


> CompletableFuture with orTimeout has noticeable performance impact
> ------------------------------------------------------------------
>
>                 Key: IGNITE-20869
>                 URL: https://issues.apache.org/jira/browse/IGNITE-20869
>             Project: Ignite
>          Issue Type: Improvement
>            Reporter: Kirill Gusakov
>            Priority: Major
>              Labels: ignite-3
>         Attachments: screenshot-1.png
>
>
> h3. Motivation
> [This 
> |https://github.com/apache/ignite-3/blob/82c74598b5006ea3e4e86da744a68022dd799c89/modules/network/src/main/java/org/apache/ignite/network/DefaultMessagingService.java#L254-L255]line
>  of code cost us near the 3us from the 26us of the whole query (~10%). The 
> reason is the orTimeout(...) call.
> The simple switch to the simple new CompletableFuture() gives us a 10% boost 
> from 26us/s to 23us/s in the 1-node fsync=false run of SelectBenchmark.kvGet.
> {code}
> responseFuture.orTimeout(timeout, TimeUnit.MILLISECONDS);
> {code}
> The code spends 3 microseconds or more.
> The note above is absolutely correct and appropriate for put operation as 
> well.
> Next, I want to notice all the places where `orTimeput` is used in the hot 
> path: 
> * _LeaseTracker#awaitPrimaryReplica_ Althogh at this place, the future 
> usually is completed, we call `orTimout` in any way.
> * _DefaultMessagingService#invoke0_ It is not a network timeout (despite the 
> fact that it is set in the network layer), but this is an important timeout 
> for application code.
> * The _IgniteRpcClient#invokeAsync_ Raft retry timeout is set here.
> * _TcpClientChannel#serviceAsync_ Thin cluient operation timeout.
> h3. Implementation notes
> I compared an invocation `orTimeout` and a timeout worker implementation 
> based on a dedicated thread with a concurrent queue:
> {code}
> Thread t = new Thread(() -> {
>             TimeoutObject o;
>             while (true) {
>                 o = queue.poll();
>                 if (o == null) {
>                     try {
>                         Thread.sleep(200);
>                     } catch (InterruptedException e) {
>                         throw new RuntimeException(e);
>                     }
>                     continue;
>                 }
>                 if (System.currentTimeMillis() > o.timeout) {
>                     o.onTimeout();
>                 } else {
>                     queue.add(o);
>                 }
>             }
>         }, "timout-worker");
> {code}
> !screenshot-1.png|height=250,width=250!
> h3. Definition of done
> `orTimeout` method is not used in the operation hot (put/get e.t.c) path.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to