Java salah satu teknologi paling populer untuk pengembangan aplikasi. Puluhan ribu aplikasi perusahaan dihasilkan dari Java dan jutaan orang menggunakannya setiap hari. Java telah berkembang selama beberapa dekade dan ada begitu banyak kerangka kerja web, middleware, teknologi akses data, dan protokol yang dibangun di atas Java. Dibandingkan dengan C, C++, dan bahasa lain di mana manajemen memori sebagian besar dilakukan secara manual oleh programmer, Java mengatur dan mengelola memori (pembebasan dan reklamasi) sendiri, secara otomatis.
Meskipun demikian, masalah kinerja juga dapat terjadi pada aplikasi berbasis Java dan ketika masalah terjadi, hal itu dapat berdampak pada bisnis. Di blog ini, kita akan melihat beberapa masalah populer yang dihadapi pengembang dan administrator Java dan merekomendasikan beberapa praktik terbaik untuk mengatasi dan mencegahnya.
#1 Kesalahan Memori yang Habis di JVM
Java.lang.OutOfMemoryError yang ditakuti adalah indikasi bahwa aplikasi mencoba menambahkan lebih banyak data ke memori, tetapi tidak ada ruang tambahan untuk itu. Kesalahan kehabisan memori mengakibatkan kegagalan yang tidak dapat dipulihkan oleh aplikasi dan karena hal tersebut, kesalahan kehabisan memori harus dihindari dengan cara apapun.
Ada banyak alasan mengapa kesalahan kehabisan memori dapat terjadi:
Memori yang kurang disediakan: Pertama, memori tumpukan yang dikonfigurasi di JVM mungkin tidak cukup untuk aplikasi. Aplikasi mungkin mencoba memasukkan lebih banyak data ke dalam heap, tetapi tidak ada lagi ruang untuk itu. Pertimbangkan kasus aplikasi yang mencoba membaca dan menyimpan file 256 MB dalam memori. JVM perlu dikonfigurasi dengan ukuran tumpukan minimal 256 MB agar ini berfungsi. Menentukan memori heap yang memadai untuk JVM merupakan hal yang penting, sama pentingnya untuk memastikan bahwa ruang memori lain yang digunakan oleh JVM juga memiliki memori yang cukup. Misalnya, Oracle JVM memiliki beberapa ruang memori:
Masing-masing ruang memori ini memiliki batas penggunaan ruang yang dapat diatur secara individual. Ketika salah satu dari ruang memori ini digunakan sepenuhnya, kesalahan aplikasi akan terjadi.
Lonjakan incoming traffic: Kedua, lonjakan beban aplikasi dapat memicu pengecualian kehabisan memori. Pertimbangkan kluster server dengan beban seimbang dimana masing-masing JVM dikonfigurasi untuk menangani beban normalnya. Ketika salah satu node turun, node lain perlu menangani beban kerja tambahan. Ketika memori yang dikonfigurasi dalam JVM tidak cukup untuk menangani beban kerja yang meningkat, pengecualian kehabisan memori akan terjadi.
Kesalahan pemrograman: Ketiga, kebocoran memori dalam aplikasi dapat disebabkan oleh kesalahan pemrograman. ‘The Java garbage collector’ dirancang untuk mendapatkan kembali memori yang dikonsumsi oleh objek yang tidak digunakan, tetapi jika sebuah program terus menambahkan memori ke heap (misalnya, tabel hash yang terus bertambah), kesalahan kehabisan memori tidak dapat dihindari.
Tips Pemecahan Masalah yang Bermanfaat:
#2 Pengumpulan Sampah Berlebihan
Pengumpulan sampah (Garbage Collection, GC) adalah proses yang sangat berguna dalam JVM yang membebaskan ruang untuk menambahkan data baru di memori. Selain bermanfaat, hal itu juga dapat berubah menjadi hal yang tidak diinginkan jika terlalu sering terjadi. Saat pengumpulan sampah berjalan, ia dapat memonopoli CPU, pemrosesan JVM dapat mungkin dapat terjeda dan hal ini dapat mencekik kinerja aplikasi. Oracle JVM mendukung algoritma pengumpulan sampah yang berbeda: kolektor serial, kolektor paralel, kolektor tanda konkuren (The Concurrent Mark Sweep, CMS) dan kolektor sampah-pertama (Garbage-first collector, G1GC). Pilihan pengumpul sampah dapat berdampak pada kinerja.
Mengonfigurasi memori JVM Anda menjadi terlalu besar juga dapat merusak kinerja. Dalam kasus seperti itu, pengumpulan sampah bisa memakan waktu yang sangat lama untuk diselesaikan, mempengaruhi kinerja.
Tips Pemecahan Masalah yang Bermanfaat:
#3 Caching Data yang Tidak Benar
Sementara caching adalah proses penting untuk membaca lebih cepat data dalam memori (sebagai lawan membuat panggilan database di seluruh jaringan), itu adalah kontra-intuitif untuk mengalokasikan memori yang berlebihan untuk caching. Konfigurasi memori yang kurang optimal untuk caching akan menyebabkan lebih banyak jeda GC dan selanjutnya mempengaruhi pemrosesan aplikasi.
Kesalahan konfigurasi dalam caching juga akan menyebabkan masalah. Objek yang di-cache bersifat stateful, tidak seperti kumpulan yang memiliki objek stateless. Saat caching tidak disetel dengan benar, objek yang baru saja digunakan dapat salah dihapus dari cache, untuk memberi ruang bagi objek baru, yang mengakibatkan skenario "cache miss" saat objek tersebut dipanggil. Selain konfigurasi memori, konfigurasi cache hit dan cache miss juga penting untuk diatur dengan benar.
Tips Pemecahan Masalah yang Bermanfaat:
#4 Kebuntuan dan Kemacetan Thread
Aplikasi Java, khususnya aplikasi berbasis web seringkali bersifat multi-threaded. Multi-threading membantu dengan skalabilitas, tetapi pada saat yang sama, ketika beberapa utas perlu mengakses sumber daya JVM bersama (seringkali memori), penguncian digunakan untuk memastikan bahwa akses ke sumber daya bersama disediakan secara eksklusif untuk setiap thread. Ketika satu thread mengunci sumber daya, thread lainnya menunggu kunci dilepaskan. Bahasa pemrograman Java memudahkan pengembang untuk mengimplementasikan sinkronisasi antar thread. Kata kunci yang disinkronkan dapat digunakan untuk membuat blok kode yang disinkronkan. Metode juga dapat disinkronkan.
Karena sangat mudah untuk membuat blok yang disinkronkan, seringkali pengembang membuat blok yang disinkronkan tanpa memahami implikasi kinerja dari blok kode tersebut. Ketika ratusan thread disinkronkan pada kunci yang sama, pemrosesan permintaan aplikasi Java sangat terpengaruh dan pengguna akan mengalami kelambatan yang berlebihan. Ketika situasi seperti itu terjadi dalam produksi dan ada ratusan thread yang berjalan di JVM, sangat sulit untuk menentukan kunci mana yang menyebabkan kelambatan dan blok kode mana yang menjadi penyebabnya.
Masalah lain dengan penguncian utas adalah kebuntuan. Sebagai contoh, thread A yang memiliki object lock menunggu eksekusi dari thread B, sedangkan thread B memiliki lock sendiri dan menunggu eksekusi dari thread A. Sekarang, kedua thread tersebut mengalami ‘deadlock’ dan tidak akan pernah mengeksekusi sehingga menyebabkan aplikasi hang atau crash.
Terlalu banyak sinkronisasi juga mengurangi kinerja. Dengan menyinkronkan thread secara berlebihan, seseorang dapat menghadapi masalah kemacetan thread, di mana banyak utas menggunakan kunci yang sama, dan menunggu hingga kunci dilepaskan.
Tips Pemecahan Masalah yang Bermanfaat:
#5 Kehilangan Koneksi Database
Sebagian besar aplikasi Java menggunakan server database untuk penyimpanan data yang persisten. Koneksi ke server database digunakan untuk menyimpan dan mengambil data. Karena membangun koneksi database untuk setiap permintaan mahal, kumpulan koneksi sering digunakan. Kumpulan koneksi memiliki pengaturan awal untuk jumlah koneksi yang akan dibuat sebelumnya saat aplikasi dimulai. Ketika koneksi tambahan diperlukan, kumpulan berkembang secara dinamis dengan tunduk pada batas maksimum yang ditentukan.
Jika jumlah koneksi yang digunakan mencapai batas maksimum, permintaan yang lebih baru harus menunggu hingga pemrosesan permintaan basis data yang ada selesai. Penting bagi pengembang dan DBA untuk memiliki perkiraan yang adil dari beban kerja aplikasi dan mengatur konfigurasi yang sesuai. Pada saat yang sama, modul aplikasi atau halaman web tertentu mungkin memiliki kebocoran koneksi – yaitu, koneksi diperoleh dari kumpulan, tetapi tidak dilepaskan kembali ke kumpulan. Kebocoran koneksi seperti itu pada akhirnya akan mengakibatkan kesalahan aplikasi dilaporkan kepada pengguna. Penggunaan kumpulan koneksi yang tinggi juga dapat terjadi pada saat server database memperlambat pemrosesannya. Oleh karena itu, penting untuk membedakan masalah kinerja yang merupakan akibat dari kebocoran koneksi database dibandingkan dengan yang merupakan akibat dari kemacetan server database.
Tips Pemecahan Masalah yang Bermanfaat:
#6 Panggilan Basis Data Lambat
Database merupakan bagian integral dari arsitektur aplikasi. Kinerja aplikasi sangat tergantung pada seberapa cepat database merespon dan mengeksekusi query. Menurut survei pemantauan kinerja DZone, masalah basis data menempati urutan kedua sebagai penyebab paling mungkin dari masalah kinerja aplikasi. Bukan hanya itu, pengembang aplikasi melainkan juga akan disalahkan atas masalah aplikasi padahal sebenarnya masalah query basis data yang harus ditangani oleh DBA. Ada banyak alasan bagaimana query database yang lambat dapat mempengaruhi pemrosesan transaksi aplikasi:
Query lambat: Saat mengembangkan aplikasi, pengembang berfokus untuk mendapatkan fungsionalitas yang tepat daripada kinerja. Sementara query database mereka mungkin mengembalikan hasil yang benar, query ini mungkin tidak dirancang secara optimal. Agar dapat dirancang secara optimal, query harus menghindari pemindaian tabel penuh di tingkat basis data. Itu harus menggunakan indeks basis data, sehingga hasilnya dikembalikan secepat mungkin. Mendapatkan query untuk dirancang secara optimal seringkali membutuhkan keterlibatan administrator basis data. DBA dapat menganalisis rencana penjelasan query dan memberikan rekomendasi tentang cara menyetelnya untuk kinerja yang optimal. Ini dapat mencakup mendesain ulang query, menggunakan indeks yang ada, rekomendasi untuk indeks baru, penambahan petunjuk, dll.
Indeks yang tidak digunakan: Meskipun merupakan praktik yang baik untuk memiliki indeks pada setiap kunci asing dalam sebuah tabel, Anda juga harus mengingat jenis query apa yang sedang dieksekusi. Indeks mungkin tidak diperlukan saat Anda tidak menggunakan kolom tertentu untuk query Anda. Indeks yang tidak digunakan akan menempati ruang pada disk dan database perlu memperbarui indeks setiap kali ada penyisipan/penghapusan catatan. Ini akan memperlambat pemrosesan query.
Sumber daya basis data tidak mencukupi: Ketika basis data kehabisan sumber daya server, seperti CPU, memori, dan disk, hal itu akan berdampak buruk pada eksekusi query.
Tips Pemecahan Masalah yang Bermanfaat:
#7 Masalah Tingkat Kode Java
Survei pemantauan kinerja DZone yang dirujuk sebelumnya menyebutkan masalah tingkat kode sebagai penyebab utama masalah kinerja aplikasi. Sebagian besar masalah tingkat kode disebabkan oleh bug dalam konstruksi kode, seperti menunggu lama, iterasi yang buruk, algoritma kode yang tidak efisien, pilihan struktur data yang buruk, dll. Misalnya, iterasi melalui Vektor dengan ratusan ribu catatan akan menjadi tidak efisien . HashMap mungkin merupakan struktur data yang lebih efisien untuk tugas ini. Dalam kebanyakan kasus, masalah tingkat kode bermanifestasi sebagai loop yang mengambil siklus CPU di JVM.
Kemudian, mungkin ada bug kinerja dalam kerangka kerja pihak ketiga yang digunakan dalam pengembangan aplikasi. Idealnya, semua masalah tingkat kode harus ditangkap oleh tim QA dan diperbaiki oleh tim pengembangan sebelum peluncuran produksi, tetapi hal ini tidak selalu terjadi.
Tips Pemecahan Masalah yang Bermanfaat:
#8 Hambatan Server Aplikasi Java
Server aplikasi adalah komponen penting dari arsitektur aplikasi Java. Server aplikasi Java yang populer adalah Oracle WebLogic, IBM WebSphere, JBoss, WildFly, Tomcat, dll. Kemacetan di server aplikasi akan berdampak langsung pada transaksi bisnis dan mempengaruhi kinerja aplikasi dan pengalaman pengguna akhir. Masalah dalam eksekusi servlet, caching kacang, antrian, konektivitas JDBC, dll akan mempengaruhi kinerja.
Pengembalian transaksi adalah masalah lain yang harus dihadapi. Pengembalian aplikasi biasanya merupakan hasil dari logika bisnis yang telah dirancang sebelumnya. Tetapi rollback non-aplikasi adalah masalah serius dan perlu segera ditangani. Aplikasi akan mengeluarkan pengecualian dan transaksi akan mundur kembali, tidak mengizinkan pengguna akhir menggunakan aplikasi untuk memproses permintaan mereka. Ada tiga jenis rollback non-aplikasi:
Tips Pemecahan Masalah yang Bermanfaat:
#9 Masalah Kinerja Server
Semua aplikasi dan middleware pendukung dan back end dijalankan di server perusahaan. Ini dapat berupa sistem operasi server di kotak fisik, mesin virtual, atau bahkan di cloud. Masalah pada perangkat keras atau sumber daya server akan mempengaruhi kinerja aplikasi yang berjalan di dalamnya. CPU, memori, dan disk yang tidak mencukupi, kesalahan sistem operasi, kesalahan perangkat keras server, proses CPU tinggi, proses zombie, layanan yang rusak, dan lain-lain adalah beberapa masalah umum yang dihadapi administrator. Terutama ketika server di virtualisasi, lebih sulit untuk menentukan masalah. Masalah perebutan sumber daya di server host tervirtualisasi dapat mempengaruhi semua guest virtual machines dan aplikasi yang berjalan di dalamnya. Hal yang sama dengan kontainer dan beban kerja aplikasi berbasis cloud.
Tips Pemecahan Masalah yang Bermanfaat:
#10 Masalah Latensi Jaringan dan Konektivitas
Penyumbatan bandwidth di jaringan, latensi tinggi dan packet loss, kesalahan konfigurasi di router, kegagalan DNS, dan lain-lain dapat mempengaruhi kinerja aplikasi. Biasanya ada banyak tudingan antara tim aplikasi dan tim jaringan tentang di mana akar penyebab masalah aplikasi dan siapa yang perlu menyelesaikannya. Ketika itu sebenarnya masalah jaringan, tim aplikasi bisa mengejar a red herring di sisi server.
Tips Pemecahan Masalah yang Bermanfaat:
Penting bagi pengembang untuk membuat kode secara efisien dan penguji untuk menangkap dan melaporkan masalah – sudah pasti! Tim TI juga harus bertindak secara proaktif dengan memiliki ukuran manajemen kinerja yang diperlukan. Pemantauan tidak boleh menjadi renungan bagi organisasi yang mengembangkan, menghosting, mengimplementasikan, dan menggunakan aplikasi berbasis Java. Pemantauan terus-menerus terhadap pengalaman pengguna, transaksi aplikasi, kode aplikasi, dan infrastruktur pendukung sangat penting untuk mendeteksi dan menyelesaikan masalah sebelum berdampak pada bisnis.
Translated article from:
Mohan, V. (2018). Top 10 Java Performance Problems and How to Solve Them. eG Innovations. https://www.eginnovations.com/blog/top-10-java-performance-problems/?utm_content=204588344&utm_medium=social&utm_source=linkedin&hss_channel=lcp-41614. (Diakses pada 22 April 2022)
Jangan ragu untuk terhubung dan dapatkan update terbaru seputar event, voting, dan informasi menarik lainnya dari KREEN!