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

batch insert event and event_tag performance. #710

Closed
Roiocam opened this issue Nov 22, 2022 · 5 comments
Closed

batch insert event and event_tag performance. #710

Roiocam opened this issue Nov 22, 2022 · 5 comments
Milestone

Comments

@Roiocam
Copy link
Contributor

Roiocam commented Nov 22, 2022

Recently I am doing load testing on my application. it does not really have a good performance, and even can not reach the bottleneck of the database.

I have some questions on the insert model:

on akka.persistence.jdbc.journal.dao.DefaultJournalDao, it uses multi insert action ++=

db.run(queries.writeJournalRows(xs).transactionally).map(_ => ())(ExecutionContexts.parasitic)

And then I took some time to find the source that executes SQL. The multi-insert action implement is MultiInsertAction on slick.jdbc.JdbcActionComponent

And it basically just uses java.sql.Statement#executeBatch. as far as I know it wouldn't optimize too much on the multi-insert on this method. (Most of the JDBC drivers would not).

They just for-each loop every param and fill them to statement and then for-each loop executes it, it will take huge network IO (the bottleneck).

MySQL document points out how to optimize this. https://dev.mysql.com/doc/refman/8.0/en/insert-optimization.html

General, most database support insert values list, it is just one network i/o.

I believe it is a performance issue, and break down the server when the network was degraded. (Expressed as a lot of EventSourcedBehavior complain circuit breakers fail fast).

In the end, In the process of writing down this issue (collecting information), I found the same issue already exists, but on scala slick.

slick/slick#2398 and slick/slick#1272

@Roiocam
Copy link
Contributor Author

Roiocam commented Apr 12, 2023

Skepticism is pointless. After a thorough investigation, it was found that akka-persistence-jdbc/slick does not even use Driver's executeBatch, and the Oldest node was unexpectedly has longer IO time (they are all running in Kubernetes, as Pods of a certain Deployment).

normal/leader

Screenshot 2023-04-12 at 10 03 11

degradation/oldest

Screenshot 2023-04-12 at 10 04 17

reduce active pods to single

active pods

Screenshot 2023-04-12 at 10 12 58

inactive pods

Screenshot 2023-04-12 at 10 13 41

@Roiocam
Copy link
Contributor Author

Roiocam commented Apr 12, 2023

Conclusion

After investigation, I found that once the event of persistence Actor is tagged, the delay of persistence to the database will increase very seriously. For some nodes, it may be 10x time.

the reason why DAO degraded because when event has tag, it's will return to foreach insert, not batch insert.

image

Slick not support insertAndReturn using batch.

image

image

what happen on my case

According to the source code, batches insert event with tag will definitely cause performance degradation.

In my case, it happened randomly, and I verified this problem under cluster and stand-alone respectively.

Generally speaking, if the traffic given to akka-persistence-jdbc is lower than its instantaneous process capacity, then the batch will start, and akka-persistence-jdbc will also start to downgrade.

In my application, due to sharding (my guess), some traffic may be delayed to reach other nodes, which causes the node to receive both HTTP load balancing traffic and traffic from the cluster sharding, resulting in traffic peaks, and resulting in the downgrade of akka-persistence-jdbc.

image

@Roiocam Roiocam changed the title batch insert event/ multi insert event performance. batch insert event and event_tag performance. Apr 12, 2023
@Roiocam
Copy link
Contributor Author

Roiocam commented Apr 12, 2023

i think this was related on #592

@octonato
Copy link
Member

@Roiocam, thanks for reporting this.

I'm curious to see the results of the same load test after adding the PK/FK as described in #592.

@Roiocam
Copy link
Contributor Author

Roiocam commented Apr 13, 2023

@Roiocam, thanks for reporting this.

I'm curious to see the results of the same load test after adding the PK/FK as described in #592.

yep, i'm working on it.

I fork this repository and change the source code base on #592, packaged it and uploaded it to our Maven repository (I am not familiar with scala, sbt publish stuck me most of the time, and finally solved it through maven deploy-file)

I am using same load test for this, but has more case:

  • CASE 1
    • hardware: 4c8g (2 of node with profiler)
    • persit actor num: 1000
    • throughput: 750
  • CASE 2
    • hardware: 4c8g (2 of node with profiler)
    • persit actor num: 1000
    • concurrency: 750
  • CASE 3
    • hardware: 4c8g (4 of node, and 2 of them with profiler)
    • persit actor num: 1000
    • throughput: 4000
  • CASE 4
    • hardware: 4c8g (4 of node, no profiler)
    • persit actor num: 4000
    • throughput: 4000

In case 3, the profiler CPU hotspot report tells us that #592 can solve this problem!

Screenshot 2023-04-13 at 15 33 19

And my application monitor prove the same conclusion.

Screenshot 2023-04-13 at 16 02 52

"Slice Executor" duration metrics in all tests (no more peaks happen on load):

Screenshot 2023-04-13 at 16 54 05

After fixing the batch insertion problem, my application throughput increased from 1000 up to 4000(Kryo serialization is the next bottleneck for now.)

Screenshot 2023-04-13 at 16 47 05

Screenshot 2023-04-13 at 16 49 31

finally, this is my change of #592, i am not familiar with scala, so maybe i missing some blind spot, And one more thing, in my tests, i did't using projection.

On my opinion, foreach insert performance is bad, we should avoid using something like insert and return.

PR show my change: #731

Roiocam pushed a commit to Roiocam/akka-persistence-jdbc that referenced this issue Apr 13, 2023
Roiocam added a commit to Roiocam/akka-persistence-jdbc that referenced this issue Apr 14, 2023
Roiocam added a commit to Roiocam/akka-persistence-jdbc that referenced this issue Aug 23, 2023
Roiocam pushed a commit to Roiocam/akka-persistence-jdbc that referenced this issue Aug 23, 2023
Roiocam added a commit to Roiocam/akka-persistence-jdbc that referenced this issue Aug 23, 2023
Roiocam added a commit to Roiocam/akka-persistence-jdbc that referenced this issue Aug 23, 2023
Roiocam added a commit to Roiocam/akka-persistence-jdbc that referenced this issue Aug 24, 2023
Roiocam added a commit to Roiocam/akka-persistence-jdbc that referenced this issue Aug 29, 2023
Roiocam added a commit to Roiocam/akka-persistence-jdbc that referenced this issue Sep 1, 2023
Roiocam added a commit to Roiocam/akka-persistence-jdbc that referenced this issue Sep 6, 2023
Roiocam added a commit to Roiocam/akka-persistence-jdbc that referenced this issue Sep 6, 2023
Roiocam added a commit to Roiocam/akka-persistence-jdbc that referenced this issue Oct 8, 2023
Roiocam pushed a commit to Roiocam/akka-persistence-jdbc that referenced this issue Oct 8, 2023
Roiocam added a commit to Roiocam/akka-persistence-jdbc that referenced this issue Oct 8, 2023
Roiocam added a commit to Roiocam/akka-persistence-jdbc that referenced this issue Oct 8, 2023
Roiocam added a commit to Roiocam/akka-persistence-jdbc that referenced this issue Oct 8, 2023
Roiocam added a commit to Roiocam/akka-persistence-jdbc that referenced this issue Oct 8, 2023
Roiocam added a commit to Roiocam/akka-persistence-jdbc that referenced this issue Oct 8, 2023
Roiocam added a commit to Roiocam/akka-persistence-jdbc that referenced this issue Oct 8, 2023
Roiocam added a commit to Roiocam/akka-persistence-jdbc that referenced this issue Oct 8, 2023
Roiocam added a commit to Roiocam/akka-persistence-jdbc that referenced this issue Oct 25, 2023
Roiocam pushed a commit to Roiocam/akka-persistence-jdbc that referenced this issue Oct 25, 2023
Roiocam added a commit to Roiocam/akka-persistence-jdbc that referenced this issue Oct 25, 2023
Roiocam added a commit to Roiocam/akka-persistence-jdbc that referenced this issue Oct 25, 2023
Roiocam added a commit to Roiocam/akka-persistence-jdbc that referenced this issue Oct 25, 2023
Roiocam added a commit to Roiocam/akka-persistence-jdbc that referenced this issue Oct 25, 2023
Roiocam added a commit to Roiocam/akka-persistence-jdbc that referenced this issue Oct 25, 2023
Roiocam added a commit to Roiocam/akka-persistence-jdbc that referenced this issue Oct 25, 2023
Roiocam added a commit to Roiocam/akka-persistence-jdbc that referenced this issue Oct 25, 2023
@patriknw patriknw added this to the 5.4.0 milestone Oct 30, 2023
Bugsource pushed a commit to Bugsource/akka-persistence-jdbc that referenced this issue Jan 8, 2024
* Replace event_tag FK to get rid of insert and return akka#710

* support rolling updates akka#710

* remove CRLF akka#710

* optimized migrator akka#710

* fixes oracle test akka#710

* unitTest,SQL for migration akka#710

* fix MigratorSpec akka#710

* chore: typo fix akka#710

* fix: IntegrationTest and clean code akka#710

* fix: compatible legacy tag read akka#673

* chore: mi-ma filter for PR

* fix: optimized migrate step

* fix: dialect for column fill

* fix: update migration sql

* fix: mysql dialect

* fix: dialect syntax

* fix: dialect syntax

* fix: avoid use system table of mysql

* fix: batch insert caused flaky test

* fix: insert less event of large batch

* fix: script fix and strongly express two-step update
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