Parsing large object tree keeps a separate copy of every key in every object
まだ誰も着手していません。
評価
- 難易度
- 5/5
- 見積もり時間
- 1週間以上
- 初心者へのやさしさ
- 45/100
- issue の種類
- 機能追加
- 明瞭さ
- おおむね明確
- 活発さ
- 活発
- 技術スタック
- java
- 領域
- backend, performance
調査の方向性
Start with JSONTokener.nextString, nextSimpleValue, and nextValue, then trace how JSONObject parses and stores keys; the issue explains the repeated-string memory cost and the existing subclass workaround. Compare the opt-in configuration, default behavior, and key-map size cap options, then add unit tests for key sharing and ensure values are not shared. Done means the chosen API behaves as documented and default parsing remains unchanged.
索引モデルが issue の本文から書いたものです。
説明
What we were doing
We run a web application that takes bulk inserts as JSON. A request body has an array of row objects that all use the same keys, for example {"rows": [{"name": "a", "count": 1, ...}, {"name": "b", "count": 2, ...}, ...]}. We parse it with new JSONObject(new JSONTokener(reader)). A request can have thousands of rows with dozens of keys each.
Result
JSONTokener.nextString creates a new String for every key it reads. A key that appears in 10,000 rows is stored 10,000 times. A heap dump from one of our production servers with 41 bulk-insert requests in progress showed 1.88 GB of parsed JSON, about 108 bytes per cell. Approximately half of that was repeated copies of the same String keys.
Expected result
Each distinct key should be stored once per parse. Since your README includes "low memory footprint" as a project goal, we're hoping you'd entertain a change.
Current workaround
We subclass JSONTokener and override nextString to return one shared instance per distinct key: KeySharingJSONTokener.java. This depends on internal details: keys are read through nextSimpleValue → nextString, but quoted values go through the same nextString. To keep values out of the shared map, we also override nextValue and handle quoted values there. A future change to these internals could quietly stop keys from being shared, or start sharing values.
Proposal
Add an opt-in option, JSONParserConfiguration.withShareKeys(boolean), that is off by default. When it's on, JSONObject swaps each parsed key for an earlier identical key from the same parse. The map of seen keys is held only for the length of one parse, and it is capped so input with a huge number of unique keys can't make it grow without limit. With the default configuration, no input would parse differently.
Alternatively, if you like this approach (I don't see much downside) it could be enabled by default.
If you'd rather not add a configuration option, a documented protected method on JSONTokener that is called only for keys would also make our subclass more reliable.
We're happy to send a PR, with unit tests and Java 6-compatible code, for whichever approach you prefer. Our code linked above is Apache 2.0 but we are happy to submit a contribution here as public domain.
- 主要言語
- Java
- スター
- 4.7k
- フォーク
- 2.6k
- 平均マージ
- 4日 11時間
- マージ済み PR(30日)
- 7
環境構築
- Dockerfile・Docker Compose ファイルなし
- プルリクエストのテンプレートなし
- コントリビューションガイドを読む
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
stleary/JSON-java のほかの issue
-
JSONObject.toString does not use an Enum's `toString()` but its `name()`再び着手できるかも @XIAYM-gh が 45 日前に担当しましたが、オープン中のプルリクエストはありません。 オープンFix before the next release
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
-
Awaiting further input from submitter No changes at this time
難易度 3/5 1〜2日 初心者へのやさしさ 45/100
-
難易度 3/5 1〜2日 初心者へのやさしさ 72/100
-
Active discussion
難易度 5/5 1週間以上 初心者へのやさしさ 35/100
-
JSONObject.toString() throws StackOverflowError (not JSONException) on self-referential cycles再び着手できるかも このイシューのプルリクエストはマージされずにクローズされました。 オープンActive discussion
難易度 4/5 3〜5日 初心者へのやさしさ 56/100
stleary/JSON-java の issue をすべて見る
似ている issue
-
[Bug] Lock owned by another client (e.g. Text app) cannot be unlocked from the app対応中かも @falkloewert が今日担当しました。 オープン
難易度 2/5 1〜3時間 初心者へのやさしさ 72/100
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 74/100
oracle/graalvm-reachability-metadata#11026 ·
メンテナーはふだん 1 日以内に返信
-
bug
難易度 1/5 1時間未満 初心者へのやさしさ 88/100
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 67/100
CodeForPhilly/benefit-decision-toolkit#565 ·
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 76/100
checkstyle/checkstyle#22050 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信