Java-da String və StringBuilder Performans Müqayisəsi: JMH Benchmark Testi

Java proqramlaşdırmasında string manipulyasiyası geniş istifadə edilir, lakin hansı metodun performans baxımından daha üstün olduğunu bilmək vacibdir. Bu məqalədə String və StringBuilder arasında performans fərqini ölçmək üçün JMH (Java Microbenchmark Harness) istifadə edəcəyik. JMH, Java proqramlarının mikrosəviyyədə performans ölçülməsi üçün nəzərdə tutulmuş kitabxanadır.

19 Noyabr 2024 - 01:14
 0  72
Java-da String və StringBuilder Performans Müqayisəsi: JMH Benchmark Testi
Java Azərbaycan

Niyə String və StringBuilder Müqayisə Edilməlidir?

Java-da String dəyişməz (immutable) bir obyekt olaraq dizayn edilmişdir. Buna görə hər dəfə bir String birləşdirmə etdikdə yeni bir obyekt yaradılır. Əksinə, StringBuilder dəyişkən (mutable) bir obyekt olaraq, string manipulyasiyalarını daha səmərəli şəkildə həyata keçirir. Bunun necə işlədiyini performans testləri ilə araşdıracağıq.

Bu testdə Java-da StringStringBuilder istifadə edərək mətn birləşdirmənin (concatenation) performans fərqini yoxladım.

package com.javaazerbaycan;

import org.openjdk.jmh.annotations.*;
import java.util.concurrent.TimeUnit;

@BenchmarkMode(Mode.Throughput) 
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@State(Scope.Thread)
public class StringVsStringBuilderBenchmark {

    private static final String BASE_STRING = "Java";
    private static final int ITERATIONS = 1000;

    @Benchmark
    public String testStringConcatenation() {
        String result = BASE_STRING;
        for (int i = 0; i < ITERATIONS; i++) {
            result += " Azerbaijan";
        }
        return result;
    }

    @Benchmark
    public String testStringBuilderAppend() {
        StringBuilder builder = new StringBuilder(BASE_STRING);
        for (int i = 0; i < ITERATIONS; i++) {
            builder.append(" Azerbaijan");
        }
        return builder.toString();
    }
}

Testin Məqsədi

StringStringBuilder ilə çoxsaylı əməliyyatlar zamanı hansının daha effektiv olduğunu müəyyən etməkdir. Bunun üçün aşağıdakılar yoxlanılır:

  1. testStringConcatenation Metodu:

    • Bu metodda String obyektindən istifadə edərək mətn birləşdirmə aparılır.
    • Hər bir birləşdirmə zamanı yeni bir String obyekti yaradılır, çünki String immutable-dır (dəyişməzdir). Bu, performans baxımından daha çox yaddaş və CPU sərfi deməkdir.
  2. testStringBuilderAppend Metodu:

    • Bu metodda StringBuilder obyektindən istifadə olunur. StringBuilder mutable-dır (dəyişdirilə bilən).
    • Mətn birləşdirmə əməliyyatları mövcud obyekt daxilində aparılır, bu da daha az yaddaş sərfi və daha sürətli icra ilə nəticələnir.

Testdəki Parametrlər

  • @BenchmarkMode(Mode.Throughput): Saniyə ərzində neçə əməliyyat icra olunduğunu ölçür.
  • @OutputTimeUnit(TimeUnit.MILLISECONDS): Ölçü vahidinin millisaniyə olduğunu göstərir.
  • @State(Scope.Thread): Hər thread üçün ayrıca State təmin edir, bu, testlərin izolyasiya olunmuş şəraitdə icrasını təmin edir.

Necə İşləyir?

  • Hər bir metod 1000 iterasiya ilə eyni("Java") string-ə " Azerbaijan" əlavə edir.
  • JMH (Java Microbenchmark Harness) vasitəsilə hər iki metod icra olunur və onların performansı müqayisə edilir:
    • testStringConcatenation çoxlu obyekt yaradıldığı üçün daha yavaşdır.
    • testStringBuilderAppend daha az resurs istifadə etdiyi üçün daha sürətlidir.

Testdən Nəticə

Benchmark                                                Mode  Cnt    Score   Error   Units
StringVsStringBuilderBenchmark.testStringBuilderAppend  thrpt   25  120.505 ± 2.578  ops/ms
StringVsStringBuilderBenchmark.testStringConcatenation  thrpt   25    2.017 ± 0.064  ops/ms

JMH testinin nəticələrində aşağıdakı sütunlar var və hər biri müəyyən mənanı ifadə edir:

Mode: İşləmə rejimi

Test zamanı hansı performans ölçmə rejimindən istifadə edildiyini göstərir.

Bu testdə Throughput(thrpt) rejimindən istifadə etdik, yəni saniyədə neçə əməliyyatın başa çatdırıldığını ölçdük.

Cnt: Təkrar sayı

Testin neçə dəfə təkrarlandığını göstərir.

Bu, testin dəqiq və sabit nəticə verməsi üçün istifadə edilir. Adətən, yüksək təkrar sayı testin daha sabit nəticələr verməsinə kömək edir.

Score: Performans göstəricisi

Bu sütun testin nəticələrini ədədi dəyərlə ifadə edir.

Throughput rejimində: Saniyədə yerinə yetirilən əməliyyatların orta sayı.

Məsələn: 120.505 ops/ms deməkdir ki, test zamanı hər millisaniyədə orta hesabla 120 əməliyyat başa çatıb.

Error: Xətanın dərəcəsi

Test nəticələrinin dəqiq olmadığını nəzərə alaraq, orta nəticənin nə qədər dəyişə biləcəyini göstərir.

Məsələn:

Score =  120.505 ± 2.578 ops/ms deməkdir ki, faktiki nəticə 120.505 ilə (120.505 ± 2.578) arasında ola bilər.

Yəni, nəticənin etibarlılığına dair bir intervalla təmin edilir.

Units: Ölçü vahidi

Test nəticələrinin hansı vahidlərdə göstərildiyini bildirir.

Bu testdə:

ops/ms: Millisaniyə başına əməliyyatların sayı.

Digər rejimlərdə isə bu vahidlər ns/op (hər əməliyyata nanosanilər) və ya başqa vahidlər ola bilər.

Ümumi İzah

Bu sütunlar JMH testlərinin nəticələrini dəqiq şəkildə ifadə edir:

  • Mode: Testin necə ölçüldüyünü göstərir.
  • Cnt: Təkrarlanan testlərin sayını bildirir.
  • Score: Performans göstəricisidir (yüksək rəqəm daha yaxşıdır).
  • Error: Nəticənin qeyri-dəqiqliyini ifadə edir.
  • Units: Ölçü vahidini göstərir.

Nəticə etibarilə bu test göstərdi ki, StringBuilder string manipulyasiyaları üçün performans baxımından daha effektivdir, xüsusilə dövrlərdə böyük miqdarda əməliyyat aparılarkən. Sadə əməliyyatlar üçün String istifadə etmək rahat olsa da, mürəkkəb və çox iterasiyalı ssenarilər üçün StringBuilder seçilməsi tövsiyə olunur.

Əgər performans optimizasiyası ilə maraqlanırsınızsa, JMH kimi güclü alətlərin istifadəsi sizin işinizə böyük töhfə verəcəkdir.