0Pricing
Scala for Backend Engineering & Functional Programming · Pelajaran

Mengoptimalkan Kode Konkuren

Pelajari teknik tingkat lanjut untuk mengoptimalkan aplikasi Scala konkuren, termasuk penyetelan kumpulan utas dan cara menghindari perebutan sumber daya.

Mengoptimalkan Kode Konkuren adalah pelajaran Scala for Backend Engineering & Functional Programming gratis di CoddyKit. Ini adalah pelajaran 3 dari 3. Kamu bisa membaca pelajaran lengkapnya di bawah secara gratis — lalu praktikkan langsung di browser dengan editor kode bawaan dan tutor AI 24/7. Ini adalah bagian dari jalur belajar Scala for Backend Engineering & Functional Programming, dan progresmu tersinkronisasi di web dan aplikasi CoddyKit. Kursus Scala for Backend Engineering & Functional Programming mencakup 3 pelajaran total.

Mengapa Kode Konkuren Perlu Dioptimalkan?

Mengoptimalkan kode Scala konkuren sangat penting untuk membangun aplikasi berkinerja tinggi dan dapat diskalakan. Tujuannya adalah membuat program berjalan lebih cepat dan menangani lebih banyak pekerjaan secara bersamaan.

  • Throughput: Berapa banyak operasi yang dapat diselesaikan per satuan waktu?
  • Latensi: Berapa lama waktu yang diperlukan untuk menyelesaikan satu operasi?
  • Pemanfaatan Sumber Daya: Apakah inti CPU dan memori Anda digunakan secara efisien?

Kode konkuren yang tidak dioptimalkan dengan baik dapat menyebabkan hambatan, kebuntuan, dan penggunaan sumber daya yang tidak efisien, sehingga meniadakan manfaat konkurensi.

Cara Kerja Kumpulan Utas

Kumpulan utas adalah sekumpulan utas pekerja yang telah diinisialisasi sebelumnya dan dapat digunakan kembali untuk menjalankan tugas. Alih-alih membuat utas baru untuk setiap tugas, yang membutuhkan biaya besar, tugas dikirimkan ke kumpulan tersebut.

Hal ini mengurangi biaya tambahan pembuatan dan penghancuran utas, meningkatkan daya tanggap, serta membantu mengelola jumlah utas aktif untuk mencegah kehabisan sumber daya.

Mengonfigurasi Kumpulan Global Scala

Dalam Scala, operasi asinkron sering menggunakan ExecutionContext. Secara bawaan, aplikasi Scala menggunakan ExecutionContext global yang biasanya berupa ForkJoinPool.

Anda dapat menyetel kumpulan bawaan ini dengan mengonfigurasi properti sistem atau, yang lebih umum, dengan menentukan pengaturan pengirim di application.conf (khususnya dalam aplikasi berbasis Akka). Hal ini memungkinkan Anda mengendalikan jumlah utas, perilaku pencurian pekerjaan, dan ukuran antrean.

Pengaturan umum yang dapat disesuaikan adalah parallelism-factor untuk menskalakan ukuran kumpulan relatif terhadap inti CPU yang tersedia.

Membuat ExecutionContext Khusus

Meskipun ExecutionContext global praktis digunakan, sering kali lebih baik membuat kumpulan utas khusus untuk berbagai jenis tugas. Misalnya, kumpulan kecil untuk tugas yang terikat CPU dan kumpulan yang lebih besar untuk tugas yang terikat I/O.

Hal ini mencegah operasi I/O yang lambat memblokir tugas yang terikat CPU, sehingga meningkatkan daya tanggap sistem secara keseluruhan. Berikut cara membuat ExecutionContext khusus yang sederhana:

import java.util.concurrent.{Executors, ExecutorService}
import scala.concurrent.ExecutionContext

object CustomPoolExample {
  def main(args: Array[String]): Unit = {
    // Create a fixed thread pool with 4 threads
    val customExecutor: ExecutorService =
      Executors.newFixedThreadPool(4)

    // Wrap it in a Scala ExecutionContext
    implicit val customEC: ExecutionContext =
      ExecutionContext.fromExecutor(customExecutor)

    println("Custom ExecutionContext created.")

    // Don't forget to shut down the executor!
    customExecutor.shutdown()
  }
}

Meminimalkan Perebutan Sumber Daya

Perebutan terjadi ketika beberapa utas mencoba mengakses sumber daya bersama (seperti variabel, struktur data, atau koneksi basis data) pada waktu yang sama, dan satu utas atau lebih harus menunggu.

Penungguan ini menimbulkan penundaan dan biaya tambahan karena utas saling berebut kunci dan siklus CPU. Perebutan yang tinggi dapat sangat menurunkan kinerja aplikasi konkuren, bahkan ketika banyak inti CPU tersedia.

Strategi untuk mengurangi perebutan adalah kunci untuk mewujudkan paralelisme yang sebenarnya.

Penguncian Berbutir Halus

Alih-alih menggunakan satu kunci berbutir kasar untuk melindungi seluruh objek atau blok kode yang besar, penguncian berbutir halus menggunakan kunci yang lebih kecil dan lebih spesifik untuk melindungi hanya bagian data yang benar-benar sedang diubah.

Hal ini memungkinkan berbagai bagian objek diakses secara konkuren oleh utas yang berbeda, sehingga secara signifikan mengurangi perebutan. Namun, cara ini juga meningkatkan kompleksitas dan risiko kebuntuan jika tidak dikelola dengan hati-hati.

class Counter {
  private var value = 0
  private val lock = new Object() // A specific lock for 'value'

  def increment(): Unit = lock.synchronized {
    value += 1
  }

  def get(): Int = lock.synchronized {
    value
  }
}

object FineGrainedLocking {
  def main(args: Array[String]): Unit = {
    val counter = new Counter()
    println(s"Initial counter value: ${counter.get()}")
    counter.increment()
    println(s"Incremented value: ${counter.get()}")
  }
}

Operasi Atomik untuk Kinerja

Struktur data tanpa kunci menggunakan operasi atomik tingkat rendah (seperti Compare-And-Swap, CAS) untuk memperbarui variabel bersama tanpa kunci eksplisit. Hal ini menghindari biaya tambahan dan potensi perebutan yang terkait dengan mekanisme penguncian tradisional.

Scala memanfaatkan paket Java java.util.concurrent.atomic untuk keperluan ini. Kelas seperti AtomicInteger, AtomicLong, dan AtomicReference menyediakan pembaruan atomik sehingga ideal untuk skenario dengan perebutan tinggi.

import java.util.concurrent.atomic.AtomicInteger

object AtomicCounterExample {
  def main(args: Array[String]): Unit = {
    val atomicCounter = new AtomicInteger(0)

    // Increment the counter atomically
    atomicCounter.incrementAndGet()
    println(s"Atomic counter after increment: ${atomicCounter.get()}")

    // Another atomic operation: add 5
    atomicCounter.addAndGet(5)
    println(s"Atomic counter after adding 5: ${atomicCounter.get()}")
  }
}

Mengukur Kinerja Secara Akurat

Untuk benar-benar mengetahui apakah pengoptimalan konkuren Anda efektif, Anda harus mengukurnya secara akurat. Pengukuran waktu sederhana dengan System.nanoTime() sering kali tidak memadai untuk kode konkuren karena pengoptimalan JVM, periode pemanasan, dan pergantian konteks.

Alat pembandingan profesional seperti JMH (Java Microbenchmark Harness) dirancang untuk tujuan ini. Alat tersebut menangani pemanasan JVM dan penghapusan kode mati, serta menyediakan analisis statistik sehingga memberi Anda metrik kinerja yang andal untuk algoritme konkuren.

Berfokuslah pada metrik seperti operasi per detik (throughput) dan waktu eksekusi rata-rata (latensi) dalam kondisi beban yang beragam.

Uji Pengoptimalan Konkurensi

Manakah dari strategi berikut yang efektif untuk mengoptimalkan aplikasi Scala konkuren dan mengurangi perebutan?

Ringkasan: Kinerja Konkuren yang Lebih Baik

Dalam pelajaran ini, kita menjelajahi teknik lanjutan untuk mengoptimalkan aplikasi Scala konkuren:

  • Kita mempelajari pentingnya penyetelan kumpulan utas, termasuk mengonfigurasi ExecutionContext bawaan Scala dan membuat kumpulan khusus untuk jenis tugas tertentu.
  • Kita membahas strategi untuk menghindari perebutan, seperti mengurangi cakupan penguncian dengan penguncian berbutir halus.
  • Kita melihat bagaimana struktur data tanpa kunci, khususnya variabel atomik, dapat menyediakan pembaruan status bersama yang efisien dengan biaya tambahan rendah.

Ingatlah untuk selalu mengukur dampak pengoptimalan Anda dengan alat pembandingan yang tepat guna memastikan peningkatan kinerja yang nyata!

Pertanyaan yang Sering Diajukan

Apakah pelajaran “Mengoptimalkan Kode Konkuren” gratis?

Ya — teks lengkap “Mengoptimalkan Kode Konkuren” gratis dibaca di sini di web. Untuk praktiknya secara interaktif (editor kode bawaan dan tutor AI 24/7) dan buka sisa kursus Scala for Backend Engineering & Functional Programming, upgrade ke CoddyKit PRO. Kursus Scala for Backend Engineering & Functional Programming mencakup 3 pelajaran total.

Apa yang akan aku pelajari di “Mengoptimalkan Kode Konkuren”?

Pelajari teknik tingkat lanjut untuk mengoptimalkan aplikasi Scala konkuren, termasuk penyetelan kumpulan utas dan cara menghindari perebutan sumber daya. Kamu berlatih Scala for Backend Engineering & Functional Programming dengan kode praktik yang langsung kamu jalankan di browser, dan tutor AI 24/7 menjawab pertanyaanmu saat kamu mengerjakan pelajaran ini.

Apakah aku perlu pengalaman untuk memulai Scala for Backend Engineering & Functional Programming?

Tidak diperlukan pengalaman sebelumnya. Scala for Backend Engineering & Functional Programming di CoddyKit dirancang untuk pemula hingga pelajar tingkat lanjut, jadi kamu bisa memulai di sini atau dari awal dan belajar sesuai kecepatan kamu sendiri. Ini adalah pelajaran 3 dari 3.

Berapa lama pelajaran “Mengoptimalkan Kode Konkuren” memakan waktu?

Sebagian besar pelajaran CoddyKit memakan waktu sekitar 5–10 menit. Setiap pelajaran ringkas dan interaktif, jadi kamu membuat kemajuan stabil dan melanjutkan dari tempat kamu tinggalkan di web dan aplikasi.

Bisakah aku menulis dan menjalankan kode dalam pelajaran Scala for Backend Engineering & Functional Programming ini?

Ya. Setiap pelajaran Scala for Backend Engineering & Functional Programming menyertakan editor kode bawaan, jadi kamu menulis dan menjalankan kode nyata langsung di browser dan mendapatkan umpan balik AI instan — tidak diperlukan penyiapan lokal.

Semua pelajaran dalam kursus ini

  1. Membuat Profil Aplikasi Scala
  2. Pengelolaan Memori & Penyetelan GC
  3. Mengoptimalkan Kode Konkuren
← Kembali ke Scala for Backend Engineering & Functional Programming