Infrastruktur dan pembukaan
Saya memiliki Aplikasi PlayFramework (2.3.8) yang dihosting pada instans AWS EC2. Saya memiliki serangkaian objek kompleks, yang harus dikembalikan sebagai string JSON melalui API web. Saya memerlukan salinan array yang dalam, dengan semua objek anak dimuat penuh hingga lapisan terakhir. Array memiliki ukuran 30-100 entri, setiap entri memiliki sekitar 1-10 entri, setiap entri memiliki hingga 100 properti, pada akhirnya tidak ada BLOB atau sejenisnya yang terlibat, semuanya bermuara pada string/ganda/ int/bool. Saya tidak yakin seberapa penting struktur data yang sebenarnya, beri tahu saya jika Anda memerlukan detail lebih lanjut. Ukuran file .json yang dihasilkan sekitar 1 MB.
Kinerja deserialisasi array ini sangat buruk, untuk ~1 MB di mesin lokal saya diperlukan waktu 3-5 menit; pada EC2 dibutuhkan sekitar 20-30 detik.
Masalah awal: kinerja buruk saat menggunakan play.libs json
Array objek saya dimuat dan disimpan sebagai JsonNode. JsonNode ini kemudian diteruskan ke ObjectMapper, yang akhirnya menulisnya dengan PrettyPrinted:
List<myObject> myObjects = myObjectService.getInstance().getAllObjects(); // simplified example
JsonNode myJsonNode = Json.toJson(myObjects); // this line of code takes a huge amount of time!
ObjectMapper om = new ObjectMapper();
return om.writerWithDefaultPrettyPrinter().writeValueAsString(myJsonNode); // this runs in <10 ms
Jadi saya menetapkan pelakunya adalah deserialisasi Json.toJson. Sejauh yang saya tahu, ini adalah perpustakaan Jackson yang digunakan oleh PlayFramework.
Meskipun saya telah membaca tentang beberapa masalah kinerja deserialisasi JSON, saya tidak yakin apakah kita harus membicarakan beberapa ratus milidetik hingga detik, dan bukan menit. Bagaimanapun, saya mencoba mengimplementasikan beberapa perpustakaan JSON lainnya (GSON, argonaut, flexjson), yang tidak berjalan mulus.
GSON
Saya "hanya" mencoba mengganti perpustakaan play-json dengan perpustakaan GSON, seperti yang saya lakukan pada bagian kecil proyek lainnya. Ini berfungsi dengan baik di sana, tetapi meskipun saya TIDAK memiliki referensi melingkar, itu melemparkan StackOverflowErrors ke wajah saya, bahkan jika saya mencoba melakukan deserialisasi objek kecil yang dibuat secara manual. Baik di mesin dev saya maupun di instans EC2.
FlexJson
List<myObject> myObjects = myObjectService.getInstance().getAllObjects(); // simplified example
JSONSerializer serializer = new JSONSerializer().prettyPrint(true);
return serializer.deepSerialize(myObjects); // returns a prettyPrinted String
Sejauh ini berfungsi cukup baik, hanya membutuhkan sekitar 20% waktu dibandingkan dengan metode JSON.toJson di atas. Namun, hal ini mungkin terjadi karena ia tidak benar-benar menyalin objek secara mendalam. Itu menyalinnya secara mendalam pada lapisan pertama, namun karena model saya memiliki beberapa properti yang lebih kompleks (dengan anak, cucu, dan cucu...), dan cukup banyak, saya tidak yakin bagaimana melanjutkannya di sini.
Berikut adalah contoh output dari salah satu objek bersarang saya (ini adalah salah satu properti dari objek "atas"):
"class": "com.avaje.ebean.common.BeanList",
"empty": false,
"filterMany": null,
"finishedFetch": true,
"loaderIndex": 0,
"modifyAdditions": null,
"modifyListenMode": "NONE",
"modifyRemovals": null,
"populated": true,
"propertyName": "elements",
"readOnly": false,
"reference": false
Apakah Anda punya saran solusi lain, atau petunjuk apa yang mungkin rusak? Saya juga memikirkan bahwa mungkin entitas hanya dimuat SEPENUHNYA setelah saya memanggil .toJson()? Tetap saja itu tidak akan memakan waktu sebanyak itu.
Terima kasih sebelumnya!
.toJson()
. Seperti yang saya lihat, Anda menggunakan Ebean. Coba aktifkan logging untuk pernyataan sql untuk melihat apakah grafik objek sedang dimuat sebelum atau selama panggilantoJson
. - person marcospereira   schedule 09.11.2016toJson
(jika proses ini lebih cepat dari sebelumnya maka jelas ada sesuatu selain penguraian/pembuatan json yang membuatnya lebih lambat) - person Salem   schedule 10.11.2016