Benchmark
The source code of the benchmark is here, using H2's in-memory database, it can run directly without any environment preparation.
Report
Operation count per second
- The abscissa represents the count of data objects queried from the database each time.
- The ordinate represents the operation count per second.
- Chart
- Data
Framework | Data count | Ops/s |
---|---|---|
JDBC(ColIndex) | 10 | 564001 |
JDBC(ColIndex) | 20 | 480692 |
JDBC(ColIndex) | 50 | 232401 |
JDBC(ColIndex) | 100 | 134663 |
JDBC(ColIndex) | 200 | 71072 |
JDBC(ColIndex) | 500 | 30751 |
JDBC(ColIndex) | 1000 | 14681 |
JDBC(ColName) | 10 | 340041 |
JDBC(ColName) | 20 | 194774 |
JDBC(ColName) | 50 | 125967 |
JDBC(ColName) | 100 | 55368 |
JDBC(ColName) | 200 | 38823 |
JDBC(ColName) | 500 | 16254 |
JDBC(ColName) | 1000 | 8157 |
Jimmer(Java) | 10 | 234769 |
Jimmer(Java) | 20 | 135347 |
Jimmer(Java) | 50 | 70747 |
Jimmer(Java) | 100 | 35901 |
Jimmer(Java) | 200 | 18585 |
Jimmer(Java) | 500 | 7661 |
Jimmer(Java) | 1000 | 3759 |
Jimmer(Kotlin) | 10 | 231853 |
Jimmer(Kotlin) | 20 | 133594 |
Jimmer(Kotlin) | 50 | 61121 |
Jimmer(Kotlin) | 100 | 27805 |
Jimmer(Kotlin) | 200 | 16830 |
Jimmer(Kotlin) | 500 | 6920 |
Jimmer(Kotlin) | 1000 | 3486 |
MyBatis | 10 | 77973 |
MyBatis | 20 | 43833 |
MyBatis | 50 | 20453 |
MyBatis | 100 | 10489 |
MyBatis | 200 | 5147 |
MyBatis | 500 | 1922 |
MyBatis | 1000 | 1059 |
Exposed | 10 | 96617 |
Exposed | 20 | 69563 |
Exposed | 50 | 34146 |
Exposed | 100 | 19736 |
Exposed | 200 | 10249 |
Exposed | 500 | 4261 |
Exposed | 1000 | 2182 |
JPA(Hibernate) | 10 | 103156 |
JPA(Hibernate) | 20 | 60658 |
JPA(Hibernate) | 50 | 26730 |
JPA(Hibernate) | 100 | 13504 |
JPA(Hibernate) | 200 | 6850 |
JPA(Hibernate) | 500 | 2540 |
JPA(Hibernate) | 1000 | 1437 |
JPA(EclipseLink) | 10 | 63772 |
JPA(EclipseLink) | 20 | 33637 |
JPA(EclipseLink) | 50 | 13525 |
JPA(EclipseLink) | 100 | 6815 |
JPA(EclipseLink) | 200 | 3232 |
JPA(EclipseLink) | 500 | 1361 |
JPA(EclipseLink) | 1000 | 666 |
JOOQ | 10 | 57410 |
JOOQ | 20 | 35126 |
JOOQ | 50 | 14441 |
JOOQ | 100 | 9955 |
JOOQ | 200 | 3738 |
JOOQ | 500 | 1689 |
JOOQ | 1000 | 994 |
Nutz | 10 | 82881 |
Nutz | 20 | 48008 |
Nutz | 50 | 17310 |
Nutz | 100 | 8570 |
Nutz | 200 | 5124 |
Nutz | 500 | 1892 |
Nutz | 1000 | 964 |
ObjectiveSQL | 10 | 59701 |
ObjectiveSQL | 20 | 29487 |
ObjectiveSQL | 50 | 12662 |
ObjectiveSQL | 100 | 6795 |
ObjectiveSQL | 200 | 3419 |
ObjectiveSQL | 500 | 1356 |
ObjectiveSQL | 1000 | 599 |
Spring Data JDBC | 10 | 20612 |
Spring Data JDBC | 20 | 10123 |
Spring Data JDBC | 50 | 4029 |
Spring Data JDBC | 100 | 1984 |
Spring Data JDBC | 200 | 1079 |
Spring Data JDBC | 500 | 412 |
Spring Data JDBC | 1000 | 227 |
Ktorm | 10 | 17717 |
Ktorm | 20 | 10214 |
Ktorm | 50 | 4182 |
Ktorm | 100 | 2041 |
Ktorm | 200 | 1067 |
Ktorm | 500 | 356 |
Ktorm | 1000 | 181 |
Time cost per operation
- The abscissa represents the count of data objects queried from the database each time.
- The ordinate represents the time cost per operation(μs).
- Chart
- Data
Framework | Data count | Time(μs) |
---|---|---|
JDBC(ColIndex) | 10 | 2 |
JDBC(ColIndex) | 20 | 2 |
JDBC(ColIndex) | 50 | 4 |
JDBC(ColIndex) | 100 | 7 |
JDBC(ColIndex) | 200 | 14 |
JDBC(ColIndex) | 500 | 33 |
JDBC(ColIndex) | 1000 | 68 |
JDBC(ColName) | 10 | 3 |
JDBC(ColName) | 20 | 5 |
JDBC(ColName) | 50 | 8 |
JDBC(ColName) | 100 | 18 |
JDBC(ColName) | 200 | 26 |
JDBC(ColName) | 500 | 62 |
JDBC(ColName) | 1000 | 123 |
Jimmer(Java) | 10 | 4 |
Jimmer(Java) | 20 | 7 |
Jimmer(Java) | 50 | 14 |
Jimmer(Java) | 100 | 28 |
Jimmer(Java) | 200 | 54 |
Jimmer(Java) | 500 | 131 |
Jimmer(Java) | 1000 | 266 |
Jimmer(Kotlin) | 10 | 4 |
Jimmer(Kotlin) | 20 | 7 |
Jimmer(Kotlin) | 50 | 16 |
Jimmer(Kotlin) | 100 | 36 |
Jimmer(Kotlin) | 200 | 59 |
Jimmer(Kotlin) | 500 | 145 |
Jimmer(Kotlin) | 1000 | 287 |
MyBatis | 10 | 13 |
MyBatis | 20 | 23 |
MyBatis | 50 | 49 |
MyBatis | 100 | 95 |
MyBatis | 200 | 194 |
MyBatis | 500 | 520 |
MyBatis | 1000 | 944 |
Exposed | 10 | 10 |
Exposed | 20 | 14 |
Exposed | 50 | 29 |
Exposed | 100 | 51 |
Exposed | 200 | 98 |
Exposed | 500 | 235 |
Exposed | 1000 | 458 |
JPA(Hibernate) | 10 | 10 |
JPA(Hibernate) | 20 | 16 |
JPA(Hibernate) | 50 | 37 |
JPA(Hibernate) | 100 | 74 |
JPA(Hibernate) | 200 | 146 |
JPA(Hibernate) | 500 | 394 |
JPA(Hibernate) | 1000 | 696 |
JPA(EclipseLink) | 10 | 16 |
JPA(EclipseLink) | 20 | 30 |
JPA(EclipseLink) | 50 | 74 |
JPA(EclipseLink) | 100 | 147 |
JPA(EclipseLink) | 200 | 309 |
JPA(EclipseLink) | 500 | 735 |
JPA(EclipseLink) | 1000 | 1501 |
JOOQ | 10 | 17 |
JOOQ | 20 | 28 |
JOOQ | 50 | 69 |
JOOQ | 100 | 100 |
JOOQ | 200 | 268 |
JOOQ | 500 | 592 |
JOOQ | 1000 | 1006 |
Nutz | 10 | 12 |
Nutz | 20 | 21 |
Nutz | 50 | 58 |
Nutz | 100 | 117 |
Nutz | 200 | 195 |
Nutz | 500 | 529 |
Nutz | 1000 | 1038 |
ObjectiveSQL | 10 | 17 |
ObjectiveSQL | 20 | 34 |
ObjectiveSQL | 50 | 79 |
ObjectiveSQL | 100 | 147 |
ObjectiveSQL | 200 | 292 |
ObjectiveSQL | 500 | 738 |
ObjectiveSQL | 1000 | 1671 |
Spring Data JDBC | 10 | 49 |
Spring Data JDBC | 20 | 99 |
Spring Data JDBC | 50 | 248 |
Spring Data JDBC | 100 | 504 |
Spring Data JDBC | 200 | 927 |
Spring Data JDBC | 500 | 2429 |
Spring Data JDBC | 1000 | 4413 |
Ktorm | 10 | 56 |
Ktorm | 20 | 98 |
Ktorm | 50 | 239 |
Ktorm | 100 | 490 |
Ktorm | 200 | 937 |
Ktorm | 500 | 2809 |
Ktorm | 1000 | 5539 |
This benchmark does not include JPA(OpenJPA)
as Spring has removed support for OpenJPA.
Implementation principle
Disable caching for all frameworks
All frameworks close the log
All frameworks open and close connections/sessions each time without sharing; rely on the connection pool to ensure performance.
Use Spring's connection management. Due to different framework APIs, the implementation methods are slightly different.
- Some use
getConnection
andreleaseConnection
of DataSourceUtils - Some use TransactionAwareDataSourceProxy
but the end result is the same
- Some use
Don't use transactions
Exposed
is special, its API enforces transactions, provide fake implementation for it.Use the embedded H2 database to compress database consumption as much as possible, highlighting the performance of ORM itself, that is, the performance of mapping.
Value
A common point of view is that the performance of ORM itself is not important. In actual projects, the database is not embedded memory database, so the time consumption of the ORM itself is negligible compared to the time consumption of the database.
Rebuttal: After the release of Java 19, virtual threads are supported. ORM can complete the mapping as soon as possible, allowing the JVM to schedule more virtual threads.