Java - Panduan Micropengukuran Untuk Pemula

Halo semua, para penyihir Java masa depan! ? Hari ini, kita akan melakukan perjalanan yang menyegarkan ke dunia micropengukuran Java. Jangan khawatir jika Anda belum pernah menulis satu baris kode sebelumnya - kita akan mulai dari awal dan bergerak maju bersama. Jadi, ambil secangkir kopi (atau teh, jika itu yang Anda sukai), dan mari kita melompat masuk!

Java - Microbenchmark

Apa Itu Micropengukuran?

Sebelum kita masuk ke detil tentang micropengukuran Java, mari kita mengerti apa itu micropengukuran.

Bayangkan Anda adalah seorang chef yang mencoba untuk menyempurnakan sebuah resep. Anda tidak hanya akan mencoba makan makanan akhir untuk melihat apakah itu enak, kan? Anda akan mencoba masing-masing bahan, menguji waktu penggorengan yang berbeda, dan mencoba teknik yang berbeda. Itulah yang sama dengan micropengukuran dalam pemrograman - itu adalah cara untuk mengukur performa dari bagian kecil, terpisah dari kode Anda.

Mengapa Pengukuran Java Penting?

Sekarang, Anda mungkin bertanya-tanya, "Mengapa saya harus peduli tentang pengukuran?" Baiklah, izinkan saya untuk memberikan cerita kecil.

Pada saat saya masih menjadi pengembang júnior, saya pernah menulis sebuah program yang sempurna... di komputer saya. Tetapi ketika kita mendeploy ke server perusahaan, itu lebih lambat dari seekor kura-kura yang membawa rakitan berat! Itu saat saya mengetahui pentingnya pengukuran. Hal ini membantu kita:

  1. Mengidentifikasi titik kaku performa
  2. Membandingkan implementasi yang berbeda
  3. Memastikan kode kita berjalan efisien di sistem yang berbeda

Teknik Pengukuran Java

Mari kita lihat beberapa teknik pengukuran Java yang umum:

1. Pengukuran Manual

Cara paling sederhana untuk mengukur adalah pengukuran manual. Berikut adalah contoh dasar:

public class ContohPengukuranManual {
public static void main(String[] args) {
long waktuMulai = System.nanoTime();

// Kode Anda di sini
for (int i = 0; i < 1000000; i++) {
Math.sqrt(i);
}

long waktuAkhir = System.nanoTime();
long durasi = (waktuAkhir - waktuMulai);
System.out.println("Waktu eksekusi: " + durasi + " nanosekon");
}
}

Dalam contoh ini, kita menggunakan System.nanoTime() untuk mengukur berapa lama waktu yang dibutuhkan untuk menghitung akar kuadrat dari angka 0 sampai 999,999.

2. Menggunakan JMH (Java Microbenchmark Harness)

Meskipun pengukuran manual sederhana, itu tidak selalu akurat. Itulah saat JMH masuk ke acara. JMH adalah perangkat Java untuk membangun, menjalankan, dan menganalisis nano/mikro/milli/makro pengukuran.

Untuk menggunakan JMH, Anda perlu menambahkannya ke proyek Anda. Jika Anda menggunakan Maven, tambahkan dependensi berikut ke pom.xml Anda:

<dependencies>
<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-core</artifactId>
<version>1.35</version>
</dependency>
<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-generator-annprocess</artifactId>
<version>1.35</version>
</dependency>
</dependencies>

Sekarang, mari kita tulis pengukuran JMH sederhana:

import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;

import java.util.concurrent.TimeUnit;

@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@State(Scope.Thread)
@Fork(value = 2, jvmArgs = {"-Xms2G", "-Xmx2G"})
@Warmup(iterations = 3)
@Measurement(iterations = 3)
public class ContohJMH {

@Benchmark
public void pengukuranMathSqrt() {
Math.sqrt(143);
}

public static void main(String[] args) throws RunnerException {
Options opt = new OptionsBuilder()
.include(ContohJMH.class.getSimpleName())
.forks(1)
.build();

new Runner(opt).run();
}
}

Pengukuran ini mengukur waktu rata-rata yang dibutuhkan untuk menghitung akar kuadrat dari 143. Mari kitaurai anotasi:

  • @BenchmarkMode: Menentukan apa yang akan diukur (waktu rata-rata dalam kasus ini)
  • @OutputTimeUnit: Menentukan unit hasil
  • @State: Definisikan lingkup di mana "state" objek akan dibagi
  • @Fork: Berapa kali menggandakan satu pengukuran
  • @Warmup dan @Measurement: Definisikan berapa banyak iterasi penghangat dan pengukuran yang akan dilakukan

Algoritma Koleksi Java

Sementara kita berbicara tentang pengukuran, mari kita sekilas ke Algoritma Koleksi Java. Ini adalah alat yang sangat berguna yang dapat memiliki dampak besar pada performa program Anda.

Berikut adalah tabel beberapa algoritma umum:

Algoritma Deskripsi Kasus Penggunaan
Collections.sort() Mengurutkan sebuah daftar Ketika Anda perlu memesan elemen
Collections.binarySearch() Mencari sebuah daftar yang terurut Mencari elemen di daftar besar, terurut
Collections.reverse() Membalik urutan daftar Ketika Anda perlu membalikkan urutan elemen
Collections.shuffle() Mengacak secara acak urutan daftar Mengacak urutan elemen
Collections.fill() Mengganti semua elemen dengan elemen yang ditentukan Menginisialisasi daftar dengan nilai tertentu

Mari kita ukur performa pengurutan daftar menggunakan Collections.sort():

import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import java.util.concurrent.TimeUnit;

@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.MICROSECONDS)
@State(Scope.Thread)
@Fork(value = 2, jvmArgs = {"-Xms2G", "-Xmx2G"})
@Warmup(iterations = 3)
@Measurement(iterations = 3)
public class PengukuranPengurutan {

@Param({"100", "1000", "10000"})
private int ukuranDaftar;

private List<Integer> daftar;

@Setup
public void setup() {
daftar = new ArrayList<>(ukuranDaftar);
Random acak = new Random();
for (int i = 0; i < ukuranDaftar; i++) {
daftar.add(acak.nextInt());
}
}

@Benchmark
public void pengukuranCollectionsSort() {
Collections.sort(daftar);
}

public static void main(String[] args) throws RunnerException {
Options opt = new OptionsBuilder()
.include(PengukuranPengurutan.class.getSimpleName())
.forks(1)
.build();

new Runner(opt).run();
}
}

Pengukuran ini mengukur berapa lama waktu yang dibutuhkan untuk mengurutkan daftar dengan ukuran yang berbeda (100, 1000, dan 10000 elemen). Menjalankan ini akan memberikan gambaran bagus tentang bagaimana waktu pengurutan meningkat dengan ukuran daftar.

Kesimpulan

Dan itu saja, teman-teman! Kita baru saja menyentuh permukaan micropengukuran Java. Ingat, pengukuran tidak hanya tentang menulis kode cepat - itu tentang memahami karakteristik performa kode Anda dan membuat keputusan yang informasi.

Sebagai Anda terus menjalankan perjalanan Java Anda, tetaplah menggunakan pengukuran sebagai alat di rak Anda. Itu seperti kompas yang dapat membantu Anda menavigasi di atas laut yang kadang-kadang gelombang software performa.

Selamat coding, dan semoga pengukuran Anda selalu memberikan wawasan! ??‍??‍?

Credits: Image by storyset