Java 反序列化糟糕的性能


我在 hackernews 上看到了这篇文章,觉得看看这里的社区怎么想会很有趣。
HN 帖子:https://news.ycombinator.com/item? id=41616653
博客链接:https://www.marginalia.nu/log/a_110_java_io/
编辑:博客作者添加了一个带有测试源代码的 github 链接,但仅限于 HN,而不是博客本身。说实话不知道为什么:https: //github.com/vlofgren/Serialization1BRCBenchmark/


测试:

  • DuckDB    2.6s    3.0 GB
  • Disk I/O 2 GB    4.0s    2.0 GB
  • Parquet (Snappy) in DuckDB    4.5s    5.5 GB
  • Custom Encoding 2 + mmap    5.1s    2.8 GB
  • Parquet (Zstd) in DuckDB    5.5s    3.0 GB
  • Custom Encoding 2    6.7s    2.8 GB
  • Disk I/O 10 GB    20.0s    10 GB
  • Custom Encoding    56s    9.5GB
  • Protobuf + NIO    91s    12.3 GB
  • Parquet in Java    134s    2.4 GB
  • OIS    260s    14 GB
  • DIS+BIS    300s    10 GB
  • Protobuf + BIS    580s    12.3 GB
  • Stream all 1B rows over JDBC    620s    3.0 GB


观点1:
虽然 Java IO 的当前设计显然无法轻松利用新的硬件速度,但我认为这篇博文通过将专用解决方案与用 Java 编写的通用或专用解决方案的松散示例进行比较而夸大了这个问题。

总之,高级 Java IO 的性能可能存在问题,但这篇博文并没有真正帮助您理解它是什么。

观点2:
很棒的帖子。请将 https://github.com/apache/fury添加到基准测试中。我很好奇它的排名如何...
JDBC 部分也非常令人大开眼界,因为似乎没有人尝试优化这一部分。我希望我们在那里有一些选择……
我刚刚花了半个小时研究 postgresql jdbc 的压缩选项,结果非常糟糕。

观点3:
在我看来,JDBC 部分简直是愚蠢至极。如果您要使用 SQL-DB,请使用 SQL-DB。插入数据,然后从中选择 AVG、MIN、MAX 等任何您想要的值,不要通过 JDBC 获取十亿行并在客户端进行聚合。

观点4:
我曾经在 PostgreSQL 上写过一个事件存储。使用 JDBC 的单线程处理相当大的事件(有效负载 1kB 以上)时的性能约为 100 MB/秒(在 1 Gbit 网络上)。因此 3 GB 需要 30 秒。我认为它每秒处理大约 20000 个事件(每个事件都是一行,带有 Jackson 序列化的有效负载)。
我使用一些 PostgreSQL 特定命令 (使用COPY而不是SELECT) 执行了此操作。这样速度要快得多。

观点5:
我工作中使用的应用程序只是一个带有大量数据库的大型 CRUD 应用程序。除了尝试使用缓存来加速之外,JDBC 实际上没有其他选择。