CodeGym /Kurslar /JAVA 25 SELF /Serializasiyanın kompressiyası və profillənməsi

Serializasiyanın kompressiyası və profillənməsi

JAVA 25 SELF
Səviyyə, Dərs
Mövcuddur

1. Giriş: serializasiyanı niyə optimallaşdırmaq lazımdır?

Müasir tətbiqlərdə serializasiya hər yerdə rast gəlinir — şəbəkə protokollarından paylanmış keşlərə və xidmətlər arasında məlumat mübadiləsinə qədər.

Burada serializasiyanın sürəti və ölçüsü kritikdir. Serializasiya yavaşdırsa, tətbiq məlumatları saxlayarkən və ya yükləyərkən “yavaşımağa” başlayır, şəbəkə və ya disk isə boşuna gözləyir. Obyektlər çox böyük alındıqda, onlar diskdə çox yer tutur, şəbəkə ilə daha uzun müddət ötürülür və yaddaşa, eləcə də buraxma qabiliyyətinə əlavə yük yaradır.

Tipik vəzifələrə böyük obyekt qrafını fayla və ya keşa yazmaq, obyektləri şəbəkə ilə minimal gecikmə ilə ötürmək və çoxsaxlı sistemdə verilənləri tez serializasiya/deserializasiya etmək daxildir.

Nəticə sadədir: serializasiyanın optimallaşdırılması “premium funksionallıq” deyil, məhsuldar və miqyaslana bilən tətbiqlər üçün zəruri praktikadır.

2. Serializasiya edilmiş məlumatların ölçüsünün optimallaşdırılması

Lazımsız məlumatların istisnası: transient açar sözü

Susmaya görə, transient kimi işarələnənlər istisna olmaqla obyektin bütün sahələri serializə olunur. Sahəni saxlamağa ehtiyac yoxdursa (məsələn, keş, müvəqqəti məlumatlar, servislərə istinadlar), onu transient kimi işarələyin:

public class User implements Serializable {
    private String name;
    private transient String sessionToken; // serializasiya olunmayacaq
}

Üstünlüklər:

  • Serializə olunmuş obyektin ölçüsü daha kiçik olur.
  • Faylda və ya şəbəkədə artıq/təhlükəli məlumatlar yoxdur.

Əl ilə serializasiya: Externalizable interfeysi

Nəyin və necə serializə olunmasına tam nəzarət lazımdırsa, Externalizable interfeysini reallaşdırın və serializasiyanı açıq şəkildə təsvir edin (writeExternal/readExternal metodları):

public class Person implements Externalizable {
    private String name;
    private int age;
    private transient String secret;

    @Override
    public void writeExternal(ObjectOutput out) throws IOException {
        out.writeUTF(name);
        out.writeInt(age);
        // secret-i serializasiya etmirik
    }

    @Override
    public void readExternal(ObjectInput in) throws IOException {
        name = in.readUTF();
        age = in.readInt();
    }
}

Üstünlüklər:

  • Yalnız lazım olan sahələr serializə olunur.
  • Uyğunluğu itirmədən serializasiya formatını dəyişmək mümkündür.

Kompressiya: serializə olunmuş məlumatların sıxılması

Serializə olunmuş obyektlər çox vaxt çox yer tutur, xüsusilə təkrarlanan sətrlər və böyük kolleksiyalar olduqda. Ölçünü kompressiya ilə azaltmaq olar.

GZIPOutputStream ilə nümunə:

try (ObjectOutputStream out = new ObjectOutputStream(
         new GZIPOutputStream(new FileOutputStream("data.gz")))) {
    out.writeObject(bigObject);
}

ZipOutputStream ilə nümunə:

try (ZipOutputStream zip = new ZipOutputStream(new FileOutputStream("data.zip"))) {
    zip.putNextEntry(new ZipEntry("object"));
    ObjectOutputStream out = new ObjectOutputStream(zip);
    out.writeObject(bigObject);
    out.flush();
    zip.closeEntry();
}

Üstünlüklər:

  • Faylın ölçüsü dəfələrlə azala bilər (xüsusilə böyük obyekt qrafları üçün).
  • Şəbəkə üzərindən ötürülən trafik azalır.

Mənfi cəhətlər:

  • Sıxma/açma əlavə vaxt (CPU) tələb edir.

3. Serializasiyanın sürətinin optimallaşdırılması

Buferləşdirmə: BufferedOutputStream və BufferedInputStream niyə lazımdır

Problem:
Buferləşdirmə olmadan hər bir write() və ya read() çağırışı diskə və ya şəbəkəyə sistem müraciətinə səbəb olur — bu isə çox yavaşdır!

Həll:
Buferləşdirilmiş axınlardan istifadə edin:

try (ObjectOutputStream out = new ObjectOutputStream(
         new BufferedOutputStream(new FileOutputStream("data.bin")))) {
    out.writeObject(bigObject);
}
try (ObjectInputStream in = new ObjectInputStream(
         new BufferedInputStream(new FileInputStream("data.bin")))) {
    Object obj = in.readObject();
}

Üstünlüklər:

  • Böyük obyektlərin yazılmasını/oxunmasını əhəmiyyətli dərəcədə sürətləndirir.
  • Diskə/şəbəkəyə müraciətlərin sayını azaldır.

Bu necə işləyir?
Bufer məlumatı yaddaşda toplayır və onları bayt‑bayt yox, porsiyalarla yazır.

Sürətli kopyalama: FileChannel.transferTo

Böyük serializə olunmuş faylı tez kopyalamaq lazımdırsa, NIO və transferTo metodundan istifadə edin:

try (FileChannel src = new FileInputStream("data.bin").getChannel();
     FileChannel dest = new FileOutputStream("copy.bin").getChannel()) {
    src.transferTo(0, src.size(), dest);
}

Üstünlüklər:

  • Kopyalama OS səviyyəsində baş verir, Java-da artıq buferləşdirməni keçərək — böyük fayllar üçün çox sürətlidir.

4. Serializasiyanın profillənməsi

Sadə vaxt ölçümü: System.nanoTime()

Serializasiyanın məhsuldarlığını tez qiymətləndirmək üçün System.nanoTime()-dan istifadə etmək olar:

long start = System.nanoTime();
try (ObjectOutputStream out = new ObjectOutputStream(
         new BufferedOutputStream(new FileOutputStream("data.bin")))) {
    out.writeObject(bigObject);
}
long end = System.nanoTime();
System.out.println("Serializasiya vaxtı: " + (end - start) / 1_000_000 + " ms");

Üstünlüklər:

  • Sadə və sürətlidir.
  • Müxtəlif variantları müqayisə etmək olar (buferlə, buffersiz, kompressiya ilə və s.).

Mənfi cəhətlər:

  • Nəticələr GC və fon prosesləri səbəbindən dəyişkən ola bilər.
  • Çox kiçik fərqlərin dəqiq müqayisəsi üçün uyğun deyil.

Dəqiq profilləmə: JMH (Java Microbenchmark Harness)

Daha dəqiq ölçüm üçün mikrobencmarklar üçün xüsusi kitabxana olan JMH-dan istifadə edin.

Sadə bençmark nümunəsi:

@Benchmark
public void serializeWithBuffer() throws Exception {
    try (ObjectOutputStream out = new ObjectOutputStream(
             new BufferedOutputStream(new FileOutputStream("data.bin")))) {
        out.writeObject(bigObject);
    }
}

Üstünlüklər:

  • JVM isinməsini, GC təsirini, OS səs‑küyünü nəzərə alır.
  • Etibarlı və təkrarlana bilən nəticələr verir.

Mənfi cəhətlər:

  • Quraşdırma və JMH metodologiyasını anlamaq tələb olunur.
  • “Gözlə” müqayisə üçün artıqdır.

5. Təcrübə: serializasiya vaxtı və ölçüsünün müqayisəsi

Gəlin mini‑eksperiment aparaq: böyük obyekt qrafını (məsələn, iç‑içə kolleksiyaları olan 100_000 obyektlik siyahı) müxtəlif üsullarla serializasiya edək və zamanla fayl ölçüsünü müqayisə edək.

Buferləşdirmə və kompressiya olmadan serializasiya

long start = System.nanoTime();
try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("data1.bin"))) {
    out.writeObject(bigList);
}
long end = System.nanoTime();
System.out.println("Bufer olmadan: " + (end - start) / 1_000_000 + " ms, ölçü: " +
    new File("data1.bin").length() + " bayt");

Buferləşdirmə ilə serializasiya

long start = System.nanoTime();
try (ObjectOutputStream out = new ObjectOutputStream(
         new BufferedOutputStream(new FileOutputStream("data2.bin")))) {
    out.writeObject(bigList);
}
long end = System.nanoTime();
System.out.println("Buferlə: " + (end - start) / 1_000_000 + " ms, ölçü: " +
    new File("data2.bin").length() + " bayt");

Kompressiya ilə serializasiya (GZIP)

long start = System.nanoTime();
try (ObjectOutputStream out = new ObjectOutputStream(
         new GZIPOutputStream(new FileOutputStream("data3.gz")))) {
    out.writeObject(bigList);
}
long end = System.nanoTime();
System.out.println("Kompressiya ilə: " + (end - start) / 1_000_000 + " ms, ölçü: " +
    new File("data3.gz").length() + " bayt");

Nəticələrin analizi

Sınamalar zamanı buferləşdirmə və kompressiyanın təsiri aydın görünür. Sıxılmış fayllar adətən 2–10 dəfə kiçilir (dəqiq əmsal məlumatların strukturundan asılıdır). Buferlə serializasiya nəzərəçarpacaq dərəcədə sürətlənir, kompressiya isə prosesi bir qədər yavaşıdır, lakin yerə qənaət çox vaxt buna dəyir.

Nəticə: böyük həcmli məlumatlar üçün mütləq buferləşdirmədən istifadə edin, ölçü kritikdirsə — kompressiyanı qoşun.

6. Serializasiyanın optimallaşdırılmasında tipik səhvlər

Səhv №1: Buferləşdirmədən istifadə etməmək — böyük obyektlərin serializasiyası dəfələrlə yavaşlayır.

Səhv №2: Lazımsız və ya həssas məlumatları (məsələn, parollar, müvəqqəti tokenlər) serializasiya etmək — belə sahələr üçün həmişə transient istifadə edin.

Səhv №3: Kompressiyanın həmişə serializasiyanı sürətləndirəcəyini düşünmək — əslində kompressiya ölçünü azaldır, amma prosesi bir qədər yavaşıda bilər (xüsusilə zəif CPU-larda).

Səhv №4: JVM isinməsi və GC təsirini nəzərə almadan vaxt ölçmək — dəqiq bençmarklar üçün JMH istifadə edin.

Səhv №5: Yalnız vaxtı və ya yalnız ölçünü müqayisə etmək — tapşırığınız üçün optimal balansı seçmək üçün hər iki parametrə baxın.

1
Tapşırıq
JAVA 25 SELF, səviyyə, dərs
Bağlanıb
Məlumat arxivçisi: təkrarlanan məlumatların maksimum sıxılması
Məlumat arxivçisi: təkrarlanan məlumatların maksimum sıxılması
1
Tapşırıq
JAVA 25 SELF, səviyyə, dərs
Bağlanıb
Oyun inkişaf etdiricisi: inventarın yadda saxlanmasının performansının qiymətləndirilməsi
Oyun inkişaf etdiricisi: inventarın yadda saxlanmasının performansının qiymətləndirilməsi
1
Sorğu/viktorina
, səviyyə, dərs
Əlçatan deyil
Binar serializasiyanın optimallaşdırılması
Binar serializasiyanın optimallaşdırılması
Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION