You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@ignite.apache.org by "Vladislav Pyatkov (Jira)" <ji...@apache.org> on 2024/11/15 10:31:00 UTC

[jira] [Commented] (IGNITE-23316) Hybrid Clock#update can be optimized in case where return value is not needed

    [ https://issues.apache.org/jira/browse/IGNITE-23316?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17898569#comment-17898569 ] 

Vladislav Pyatkov commented on IGNITE-23316:
--------------------------------------------

Benchmark                    (clockOptimisationEnable)  (clusterSize)  (fsync)   Mode  Cnt       Score       Error  Units
SelectBenchmark.kvGet16                          false              1    false  thrpt   20  342720.705 ± 28020.727  ops/s
SelectBenchmark.kvGet16                           true              1    false  thrpt   20  355052.054 ± 36981.952  ops/s
SelectBenchmark.kvGet2                           false              1    false  thrpt   20  115337.877 ± 21416.119  ops/s
SelectBenchmark.kvGet2                            true              1    false  thrpt   20  209501.631 ± 11199.247  ops/s
SelectBenchmark.kvGet32                          false              1    false  thrpt   20  371942.472 ± 33987.155  ops/s
SelectBenchmark.kvGet32                           true              1    false  thrpt   20  446417.599 ± 44151.695  ops/s
SelectBenchmark.kvGet8                           false              1    false  thrpt   20  247639.011 ± 22236.092  ops/s
SelectBenchmark.kvGet8                            true              1    false  thrpt   20  278507.407 ± 31575.227  ops/s

SelectBenchmark.kvThinGet16                      false              1    false  thrpt   20   28274.544 ±  2899.646  ops/s
SelectBenchmark.kvThinGet16                       true              1    false  thrpt   20   28349.755 ±  1359.339  ops/s
SelectBenchmark.kvThinGet2                       false              1    false  thrpt   20    2462.185 ±   214.741  ops/s
SelectBenchmark.kvThinGet2                        true              1    false  thrpt   20    2410.425 ±   132.871  ops/s
SelectBenchmark.kvThinGet32                      false              1    false  thrpt   20   39411.906 ±  1484.513  ops/s
SelectBenchmark.kvThinGet32                       true              1    false  thrpt   20   43292.651 ±  2848.292  ops/s
SelectBenchmark.kvThinGet8                       false              1    false  thrpt   20   17177.921 ±   649.470  ops/s
SelectBenchmark.kvThinGet8                        true              1    false  thrpt   20   14915.538 ±   991.048  ops/s

> Hybrid Clock#update can be optimized in case where return value is not needed
> -----------------------------------------------------------------------------
>
>                 Key: IGNITE-23316
>                 URL: https://issues.apache.org/jira/browse/IGNITE-23316
>             Project: Ignite
>          Issue Type: Improvement
>            Reporter: Vladislav Pyatkov
>            Assignee: Vladislav Pyatkov
>            Priority: Major
>              Labels: ignite-3
>          Time Spent: 10m
>  Remaining Estimate: 0h
>
> h3. Motivation
> Thread-safe update is an expensive operation, and we ought to avoid it in cases where it is not needed. The stack below shows the usage update operation where the result value in not used:
> {code}
> if (response instanceof TimestampAware) {
>     clock.update(((TimestampAware) response).timestamp());
> }
> {code}
> {noformat}
> hybridClock:update-:java.lang.Exception: 
> 	at org.apache.ignite.internal.util.IgniteUtils.dumpStack(IgniteUtils.java:682)
> 	at org.apache.ignite.internal.hlc.HybridClockImpl.update(HybridClockImpl.java:119)
> 	at org.apache.ignite.internal.replicator.ReplicaService.lambda$sendToReplica$7(ReplicaService.java:164)
> 	at java.base/java.util.concurrent.CompletableFuture.uniWhenComplete(CompletableFuture.java:859)
> 	at java.base/java.util.concurrent.CompletableFuture.uniWhenCompleteStage(CompletableFuture.java:883)
> 	at java.base/java.util.concurrent.CompletableFuture.whenComplete(CompletableFuture.java:2257)
> 	at org.apache.ignite.internal.replicator.ReplicaService.sendToReplica(ReplicaService.java:144)
> 	at org.apache.ignite.internal.replicator.ReplicaService.invoke(ReplicaService.java:275)
> 	at org.apache.ignite.internal.table.distributed.storage.InternalTableImpl.lambda$evaluateReadOnlyPrimaryNode$19(InternalTableImpl.java:772)
> 	at java.base/java.util.concurrent.CompletableFuture.uniComposeStage(CompletableFuture.java:1106)
> 	at java.base/java.util.concurrent.CompletableFuture.thenCompose(CompletableFuture.java:2241)
> 	at org.apache.ignite.internal.table.distributed.storage.InternalTableImpl.evaluateReadOnlyPrimaryNode(InternalTableImpl.java:763)
> 	at org.apache.ignite.internal.table.distributed.storage.InternalTableImpl.get(InternalTableImpl.java:859)
> 	at org.apache.ignite.internal.table.KeyValueBinaryViewImpl.lambda$getAsync$1(KeyValueBinaryViewImpl.java:120)
> 	at org.apache.ignite.internal.table.AbstractTableView.lambda$withSchemaSync$2(AbstractTableView.java:143)
> 	at java.base/java.util.concurrent.CompletableFuture.uniComposeStage(CompletableFuture.java:1106)
> 	at java.base/java.util.concurrent.CompletableFuture.thenCompose(CompletableFuture.java:2241)
> 	at org.apache.ignite.internal.table.AbstractTableView.withSchemaSync(AbstractTableView.java:143)
> 	at org.apache.ignite.internal.table.AbstractTableView.withSchemaSync(AbstractTableView.java:134)
> 	at org.apache.ignite.internal.table.AbstractTableView.doOperation(AbstractTableView.java:112)
> 	at org.apache.ignite.internal.table.KeyValueBinaryViewImpl.getAsync(KeyValueBinaryViewImpl.java:117)
> 	at org.apache.ignite.internal.table.KeyValueBinaryViewImpl.get(KeyValueBinaryViewImpl.java:104)
> 	at org.apache.ignite.internal.table.KeyValueBinaryViewImpl.get(KeyValueBinaryViewImpl.java:74)
> 	at org.apache.ignite.internal.table.PublicApiThreadingKeyValueView.lambda$get$0(PublicApiThreadingKeyValueView.java:57)
> 	at org.apache.ignite.internal.thread.PublicApiThreading.executeWithRole(PublicApiThreading.java:144)
> 	at org.apache.ignite.internal.thread.PublicApiThreading.execUserSyncOperation(PublicApiThreading.java:102)
> 	at org.apache.ignite.internal.table.PublicApiThreadingViewBase.executeSyncOp(PublicApiThreadingViewBase.java:107)
> 	at org.apache.ignite.internal.table.PublicApiThreadingKeyValueView.get(PublicApiThreadingKeyValueView.java:57)
> 	at org.apache.ignite.internal.restart.RestartProofKeyValueView.lambda$get$0(RestartProofKeyValueView.java:58)
> 	at org.apache.ignite.internal.restart.RestartProofApiObject.lambda$attached$0(RestartProofApiObject.java:46)
> 	at org.apache.ignite.internal.restart.IgniteAttachmentLock.attached(IgniteAttachmentLock.java:59)
> 	at org.apache.ignite.internal.restart.RestartProofApiObject.attached(RestartProofApiObject.java:46)
> 	at org.apache.ignite.internal.restart.RestartProofKeyValueView.get(RestartProofKeyValueView.java:58)
> 	at org.apache.ignite.internal.benchmark.SelectBenchmark.kvGet(SelectBenchmark.java:175)
> 	at org.apache.ignite.internal.benchmark.jmh_generated.SelectBenchmark_kvGet_jmhTest.kvGet_avgt_jmhStub(SelectBenchmark_kvGet_jmhTest.java:238)
> 	at org.apache.ignite.internal.benchmark.jmh_generated.SelectBenchmark_kvGet_jmhTest.kvGet_AverageTime(SelectBenchmark_kvGet_jmhTest.java:177)
> 	at jdk.internal.reflect.GeneratedMethodAccessor17.invoke(Unknown Source)
> 	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
> 	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
> 	at org.openjdk.jmh.runner.BenchmarkHandler$BenchmarkTask.call(BenchmarkHandler.java:527)
> 	at org.openjdk.jmh.runner.BenchmarkHandler$BenchmarkTask.call(BenchmarkHandler.java:504)
> 	at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
> 	at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
> 	at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
> 	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
> 	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
> 	at java.base/java.lang.Thread.run(Thread.java:829)
> {noformat}
> h3. Implementation notes
> My proposal of the fast update operation:
> {code}
>   public void fastUpdate(HybridTimestamp requestTime) {
>         long requestTimeLong = requestTime.longValue();
>         while (true) {
>             long now = currentTime();
>             if (requestTimeLong <= now) {
>                 return;
>             }
>             // Read the latest time after accessing UTC time to reduce contention.
>             long oldLatestTime = this.latestTime;
>             if (requestTimeLong <= oldLatestTime) {
>                 return;
>             }
>             if (LATEST_TIME.compareAndSet(this, oldLatestTime, requestTimeLong)) {
>                 notifyUpdateListeners(requestTimeLong);
>                 return;
>             }
>         }
>     }
> {code}
> h3. Definition of done
> Replace all HybridClock#update's to the fastUpdate where the result value is not used.



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