出典ます。https://urlify.cn/NfmaYb
JSON-libの紹介
JSON-libには、一般的に、以前のJavaのJSONライブラリで使用され、最終版は、それぞれ、2.4で、サポートJDK 1.3および1.5、2010年12月14日最後に更新を提供します。多くのメンテナンスなしの年が、「JavaのJSON」に関連するキーワード発見のための検索のためだったようですが、検索エンジンでの導入と、このライブラリを使用することで人々がいます。プロジェクトの公式ウェブサイトはhttp://json-lib.sourceforge.net/です。
結論文
JSON-libのJSON文字列を介して各オブジェクトを解析するとき、それは大きなデータJSONに遭遇したときに完全なコピーは、サブストリングをインターセプトコンテンツのでJDK7上に、ストリングサブストリング操作の最後に現在の位置を解決しますそしてより多くのオブジェクトを含むことはCPUとメモリ消費、大量の、でも全GC深刻な問題が生じ、文字配列のコピー操作の多くになります。
分析
ある日は、オンラインの本番サーバのフルGCを発見し、多くの問題があり、調査は農産物のフルGCの量が、外JSONの解析に加えて、このインターフェースは、その後疑いインタフェースで、キャッシュに解析されたデータを格納するときに、古いインタフェースが上昇するましたリクエストパラメータのサイズは、ログを押すと通常のリクエストJSONデータよりもはるかに大きいことが、唯一の約1MBました。この問題を単純化するために、次のパフォーマンス・テスト・コードを記述します。
package net.mayswind;
import net.sf.json.JSONObject;
import org.apache.commons.io.FileUtils;
import java.io.File;
publicclass JsonLibBenchmark {
public static void main(String[] args) throws Exception {
String data = FileUtils.readFileToString(new File("Z:\\data.json"));
benchmark(data, 5);
}
private static void benchmark(String data, int count) {
long startTime = System.currentTimeMillis();
for (int i = 0; i < count; i++) {
JSONObject root = JSONObject.fromObject(data);
}
long elapsedTime = System.currentTimeMillis() - startTime;
System.out.println(String.format("count=%d, elapsed time=%d ms, avg cost=%f ms", count, elapsedTime, (double) elapsedTime / count));
}
}
上記のコードの後に、以下に示すように、平均分解能は、完了するまでに約7秒を必要とするたびに実行されます。
34018同じ内容の試験JSONファイルは、「...」全体のデータは、JSON3万JSONオブジェクト複数、以下に示すように実際の試験データを含む、省略されています。
{
"data":
[
{
"foo": 0123456789,
"bar": 1234567890
},
{
"foo": 0123456789,
"bar": 1234567890
},
...
]
}
以下に示す記録実行のJavaのミッションコントロールを使用して、多数がchar []アレイを割り当てることがわかります。
JSONObject._fromJSONTokener方法は、以下の主要な要素に示す前記関連アイテムは、見て。私たちは、それが「ヌル」の始まりであるかどうか、コードの試合で最初にそれを見ることができます。
private static JSONObject _fromJSONTokener(JSONTokener tokener, JsonConfig jsonConfig) {
try {
if (tokener.matches("null.*")) {
fireObjectStartEvent(jsonConfig);
fireObjectEndEvent(jsonConfig);
returnnew JSONObject(true);
} elseif (tokener.nextClean() != '{') {
throw tokener.syntaxError("A JSONObject text must begin with '{'");
} else {
fireObjectStartEvent(jsonConfig);
Collection exclusions = jsonConfig.getMergedExcludes();
PropertyFilter jsonPropertyFilter = jsonConfig.getJsonPropertyFilter();
JSONObject jsonObject = new JSONObject();
...
而 matches 方法更是直接用 substring 截取当前位置到末尾的字符串,然后进行正则匹配。
public boolean matches(String pattern) {
String str = this.mySource.substring(this.myIndex);
return RegexpUtils.getMatcher(pattern).matches(str);
}
字符串 substring 会传入字符数组、起始位置和截取长度创建一个新的 String 对象。
public String substring(int beginIndex) {
if (beginIndex < 0) {
thrownew StringIndexOutOfBoundsException(beginIndex);
}
int subLen = value.length - beginIndex;
if (subLen < 0) {
thrownew StringIndexOutOfBoundsException(subLen);
}
return (beginIndex == 0) ? this : new String(value, beginIndex, subLen);
}
在 JDK7 及以上,调用该构造方法时在最后一行会复制一遍截取后的数据,这也是导致整个问题的关键所在了。
public String(char value[], int offset, int count) {
if (offset < 0) {
thrownew StringIndexOutOfBoundsException(offset);
}
if (count <= 0) {
if (count < 0) {
thrownew StringIndexOutOfBoundsException(count);
}
if (offset <= value.length) {
this.value = "".value;
return;
}
}
// Note: offset or count might be near -1>>>1.
if (offset > value.length - count) {
thrownew StringIndexOutOfBoundsException(offset + count);
}
this.value = Arrays.copyOfRange(value, offset, offset+count);
}
你们公司还有用这个嘛,留言曝光一下。
猜你喜欢
1、GitHub 标星 3.2w!史上最全技术人员面试手册!FackBoo发起和总结
5、37岁程序员被裁,120天没找到工作,无奈去小公司,结果懵了...