38 poin oleh GN⁺ 2026-01-02 | 1 komentar | Bagikan ke WhatsApp
  • Hasil benchmark yang mengukur angka kinerja operasi, memori, dan I/O Python secara sistematis, serta mengkuantifikasi waktu dan penggunaan memori untuk tiap operasi
  • Dari sisi kecepatan, disajikan latensi relatif berbagai operasi seperti akses atribut 14ns, penambahan ke list 29ns, membuka file 9μs, respons FastAPI 8.6μs, dan lainnya
  • Dari sisi memori, disajikan angka konkret seperti string kosong 41 byte, integer 28 byte, list kosong 56 byte, dictionary kosong 64 byte, dan proses kosong 16MB
  • Untuk struktur data, serialisasi, dan pemrosesan asinkron, dibandingkan perbedaan performa antara pustaka standar dan pustaka alternatif seperti orjson dan msgspec
  • Pelajaran utama yang ditekankan mencakup tingginya overhead memori objek Python, cepatnya lookup pada dict/set, efek penghematan memori dari __slots__, dan perlunya memahami overhead pemrosesan asinkron

Gambaran Umum

  • Materi yang merangkum metrik kinerja yang perlu diketahui pengembang Python, dengan menyajikan kecepatan operasi dan penggunaan memori berdasarkan hasil pengukuran nyata
  • Benchmark dijalankan pada lingkungan CPython 3.14.2, Mac Mini M4 Pro (ARM, 14-core, RAM 24GB)
  • Hasil berfokus pada perbandingan relatif, dan kode serta datanya dibuka di repositori GitHub

Penggunaan Memori (Memory Costs)

  • Proses Python kosong menggunakan memori 15.73MB
  • String memiliki ukuran dasar 41 byte, dengan tambahan 1 byte per karakter
    • Contoh: string kosong 41B, string 100 karakter 141B
  • Tipe numerik: integer kecil (0–256) 28B, integer besar (1000) juga 28B, integer sangat besar (10ⁱ⁰⁰) 72B, floating point 24B
  • Ukuran dasar koleksi: list 56B, dictionary 64B, set 216B
    • Pada 1.000 item: list 35.2KB, dictionary 63.4KB, set 59.6KB
  • Instance kelas: kelas biasa (5 atribut) 694B, kelas __slots__ 212B
    • Untuk 1.000 instance: kelas biasa 165.2KB, kelas __slots__ 79.1KB

Operasi Dasar (Basic Operations)

  • Operasi aritmetika: penjumlahan integer 19ns, penjumlahan float 18.4ns, perkalian integer 19.4ns
  • Operasi string: konkatenasi 39.1ns, f-string 64.9ns, .format() 103ns, format % 89.8ns
  • Operasi list: append() 28.7ns, list comprehension (1.000 item) 9.45μs, for loop yang sama 11.9μs
    • List comprehension sekitar 26% lebih cepat daripada for loop

Akses dan Iterasi Koleksi (Collection Access and Iteration)

  • Akses key/indeks: lookup dictionary 21.9ns, keanggotaan set 19ns, akses indeks list 17.6ns
    • Keanggotaan list (1.000 item) memakan 3.85μs, sekitar 200 kali lebih lambat dibanding set/dictionary
  • Pemeriksaan panjang: len() pada list 18.8ns, dictionary 17.6ns, set 18ns
  • Iterasi: list (1.000 item) 7.87μs, dictionary 8.74μs, sum() 1.87μs

Kelas dan Atribut (Class and Object Attributes)

  • Kecepatan akses atribut: baik kelas biasa maupun kelas __slots__ sama-sama 14.1ns untuk baca, dan sekitar 16ns untuk tulis
  • Operasi lain: baca @property 19ns, getattr() 13.8ns, hasattr() 23.8ns
  • Dengan __slots__, efek penghematan memori lebih dari 2 kali lipat, sementara kecepatan akses tetap setara

JSON dan Serialisasi (JSON and Serialization)

  • Performa pustaka alternatif dibanding pustaka standar
    • orjson menserialisasi objek kompleks dalam 310ns, lebih dari 8 kali lebih cepat dibanding json yang membutuhkan 2.65μs
    • msgspec 445ns, ujson 1.64μs
  • Untuk deserialisasi, orjson juga yang tercepat dengan 839ns
  • Pydantic: model_dump_json() 1.54μs, model_validate_json() 2.99μs

Framework Web (Web Frameworks)

  • Dengan respons JSON yang sama: FastAPI 8.63μs, Starlette 8.01μs, Litestar 8.19μs, Flask 16.5μs, Django 18.1μs
  • FastAPI memberikan waktu respons sekitar 2 kali lebih cepat daripada Django

File I/O (File I/O)

  • Membuka dan menutup file 9.05μs, membaca 1KB 10μs, membaca 1MB 33.6μs
  • Menulis: 1KB 35.1μs, 1MB 207μs
  • Pickle sekitar 2 kali lebih cepat daripada json untuk serialisasi maupun deserialisasi (pickle.dumps() 1.3μs, json.dumps() 2.72μs)

Database dan Cache (Database and Persistence)

  • SQLite: insert 192μs, select 3.57μs, update 5.22μs
  • diskcache: set 23.9μs, get 4.25μs
  • MongoDB: insert 119μs, find_one 121μs
  • SQLite paling cepat dalam kecepatan baca, sementara diskcache unggul dalam performa tulis

Pemanggilan Fungsi dan Exception (Function and Call Overhead)

  • Pemanggilan fungsi: fungsi kosong 22.4ns, method 23.3ns, lambda 19.7ns
  • Penanganan exception: try/except (normal) 21.5ns, saat exception terjadi 139ns
  • Pemeriksaan tipe: isinstance() 18.3ns, perbandingan type() 21.8ns

Overhead Async (Async Overhead)

  • Pembuatan coroutine 47ns, run_until_complete 27.6μs
  • asyncio.sleep(0) 39.4μs, gather(10 coroutines) 55μs
  • Dibanding pemanggilan fungsi sinkron (20ns), eksekusi async (28μs) sekitar 1.000 kali lebih lambat

Pelajaran Utama (Key Takeaways)

  • Overhead memori objek Python besar; bahkan list kosong pun memakai 56 byte
  • Lookup dictionary dan set ratusan kali lebih cepat daripada pencarian pada list
  • Pustaka JSON alternatif seperti orjson dan msgspec 3–8 kali lebih cepat daripada versi standar
  • Pemrosesan async memiliki overhead besar, sehingga disarankan hanya saat benar-benar membutuhkan paralelisme
  • __slots__ dapat memangkas memori hingga kurang dari setengah tanpa hampir ada kehilangan performa

1 komentar

 
GN⁺ 2026-01-02
Komentar Hacker News
  • Banyak orang berkata bahwa jika kita harus peduli pada angka latensi di Python, maka sebaiknya gunakan bahasa lain, tetapi saya tidak setuju.
    Basis kode berskala besar seperti Instagram, Dropbox, dan OpenAI juga berkembang dengan Python. Pada akhirnya kita akan menemui masalah performa, dan kemampuan untuk menyelesaikannya di dalam Python tanpa memindahkan semuanya ke bahasa lain itu penting.
    Sebagian besar masalah performa bukan berasal dari keterbatasan bahasa, melainkan dari kode yang tidak efisien. Misalnya, loop yang tanpa perlu mengulang pemanggilan fungsi 10 ribu kali.
    Python latency quiz yang saya buat juga layak dilihat.

    • Saya bertanggung jawab atas optimisasi performa untuk sistem yang ditulis dengan Python. Namun angka-angka seperti ini sebenarnya tidak berarti sampai benar-benar menjadi masalah. Saat masalah muncul, saya mengukurnya langsung. Jika menulis kode dengan pola seperti menghemat pemanggilan method, kita justru kehilangan kelebihan Python.
    • Bahkan operasi dasar di Python pun lambat. Pekerjaan sederhana seperti pemanggilan fungsi atau akses dictionary juga lambat. Sebenarnya Python bisa bertahan berkat library berbasis C/C++ seperti Numpy.
    • Angka-angka seperti ini bukan masalah Python saja. Di Zig pun orang mempertimbangkan siklus CPU atau cache miss. Semua bahasa punya latensi pada operasi tertentu. Mungkin ada alasan untuk tidak memakai Python, tetapi ini bukan salah satunya.
    • Beberapa operasi bisa ditingkatkan dengan memakai modul pengganti. Mengetahui hal seperti ini penting, tetapi orang yang benar-benar membutuhkannya kemungkinan sudah tahu. Meski begitu, Python tetap bahasa yang sangat bagus untuk prototyping.
    • Sistem build kami juga dibuat dengan Python, jadi saya ingin mempertahankan Python sambil meningkatkan performa. Karena itu angka-angka seperti ini sangat penting.
  • Secara ironis, saat angka-angka seperti ini mulai penting, Python bukan lagi alat yang cocok untuk pekerjaan tersebut.

    • Pendekatan yang realistis adalah tetap mempertahankan kode Python, lalu menurunkan hanya bagian performa inti ke ekstensi C atau Rust. Itulah yang dilakukan numpy, pandas, dan PyTorch.
      Dalam praktiknya, yang penting adalah menginstrumentasi kode dan menemukan bottleneck, misalnya dengan alat seperti pyspy. Jika Anda sudah sampai mengkhawatirkan kecepatan menambahkan elemen ke list, maka operasi itu memang seharusnya tidak dilakukan di Python.
    • Saya sudah bekerja dengan Python selama 20 tahun, tetapi tidak pernah perlu mengetahui angka-angka seperti ini. Sebagai gantinya, saya menyelesaikannya dengan alat seperti profiling, Cython, SWIG, dan JIT.
    • Jika aplikasinya sampai membutuhkan perhatian pada angka-angka seperti ini, menurut saya Python terlalu high-level sehingga sulit dioptimalkan.
    • Tetapi saya pernah membangun pipeline data skala besar dengan Python. Kombinasi turbodbc + pandas memberi kecepatan setara C++. Memori memang lebih banyak terpakai, tetapi jika mempertimbangkan biaya tenaga kerja, itu jauh lebih efisien.
      Pendekatan seperti ini dimungkinkan berkat interoperabilitas Python dan C. Zig juga makin bagus. Saya mungkin tidak akan menerbangkan pesawat dengan Python, tetapi sense terhadap resource tetap penting.
    • Angka-angka seperti ini adalah langkah terakhir. Ini baru dipertimbangkan setelah bottleneck umum seperti disk I/O, jaringan, dan kompleksitas algoritme sudah diselesaikan.
  • Mengetahui berapa byte yang dipakai string kosong tidak terlalu berarti. Yang penting adalah memahami kompleksitas waktu dan ruang.
    Daripada tahu bahwa int berukuran 28 byte, yang lebih penting adalah menilai apakah program memenuhi kebutuhan performa, dan jika tidak, mencari algoritme yang lebih baik.

    • Tetapi performa selalu merupakan abstraksi yang bocor. Entah kita sadari atau tidak, ia memengaruhi seluruh kode.
      Misalnya, fakta bahwa konkatenasi string bersifat O(n²) juga memengaruhi desain f-string di Python.
      Karena dictionary cepat, struktur itu juga dipakai luas di seluruh Python.
      Angka-angka seperti ini berperan sebagai pembenaran dalam bentuk angka atas pengetahuan implisit tersebut.
    • Fakta bahwa int berukuran 28 byte benar-benar penting dalam masalah yang harus membuat objek dalam jumlah besar.
      Ini mengingatkan saya pada tulisan tentang masalah yang dialami Eric Raymond saat memigrasikan GCC dengan Reposurgeon.
  • Judulnya membingungkan, padahal sebenarnya ini parodi dari makalah Jeff Dean tahun 2012, “Latency Numbers Every Programmer Should Know”.
    Permainan judul seperti ini umum dalam makalah CS.

    • Kalau ada yang menulis makalah berjudul “latency numbers considered harmful is all you need”, mungkin akan langsung sangat populer di akademia.
    • Tetapi penulis artikel ini tampaknya menulisnya dengan serius. Jadi bukan pembaca yang salah paham terhadap judulnya.
    • Agar judulnya masuk akal, angka-angkanya harus benar-benar berguna, tetapi jumlahnya terlalu banyak dan kurang praktis.
    • Sebagai catatan, versi asli Jeff Dean tampaknya ditulis jauh sebelum 2012.
      Itu adalah materi internal untuk desain RAM vs Disk pada mesin pencari Google di masa awal.
      Setelah flash memory muncul, angkanya berubah, dan ada juga kisah bahwa Jeff membuat algoritme kompresi untuk langsung menyajikan data genom dari flash.
  • Kebanyakan pengembang Python sebaiknya fokus pada hal-hal yang lebih penting daripada detail performa tingkat rendah seperti ini.
    Materi semacam ini bagus sebagai referensi, tetapi dalam praktiknya jarang benar-benar dibutuhkan.

    • Tetapi pengetahuan umum tentang alat yang kita gunakan selalu bernilai. Itu adalah aset intelektual dan dalam situasi tertentu bisa sangat membantu.
    • Jika sudah mentok pada batasannya, kita bisa mencari modul yang diimplementasikan dalam C atau menulisnya sendiri. Python memang berkembang seperti itu sejak awal.
    • Saya juga selama ini bekerja dengan intuisi bahwa kebanyakan hal “cukup cepat”. Materi ini membantu memverifikasi intuisi itu dengan angka.
  • Penjelasan tentang ukuran string salah. Python memiliki tiga tipe string yang memakai 1, 2, atau 4 byte per karakter.
    Untuk detailnya, lihat blog ini.

  • Judul dan contoh di artikel ini agak kurang akurat.
    Misalnya, “item in set 200 kali lebih cepat daripada item in list” sebenarnya berbicara tentang membership test, bukan perbandingan kecepatan iterasi.
    Meski begitu, secara keseluruhan format dan susunannya menarik.

  • Pengukuran waktu pembuatan instance class tidak ada.
    Setelah refactor kode, saya pernah mengubah struktur list sederhana menjadi class dan waktu eksekusinya naik dari beberapa mikrodetik menjadi beberapa detik.
    Akan bagus jika kasus seperti ini juga diukur.

    • Ini mengingatkan saya pada lelucon tentang pasien yang berkata kepada dokter, “Kalau saya melakukan ini, rasanya sakit,” lalu dokter menjawab, “Kalau begitu jangan lakukan.”
      Mungkin masalahnya adalah penggunaan class yang berlebihan. Kadang struktur list sederhana memang lebih baik.
    • Pembuatan instance class sendiri biasanya bukan masalah performa.
      Kemungkinan yang lebih besar adalah penggunaan paradigma berorientasi objek yang kurang tepat.
      Sebaiknya unggah kodenya ke StackOverflow atau CodeReview.SE untuk mendapatkan masukan.
  • Saya membaca artikel ini dengan sudut pandang, “apakah ada sesuatu yang secara fundamental salah dengan Python modern”.
    Tetapi saya tidak setuju dengan klaim bahwa kita harus mengetahui semua angka ini.
    Cukup punya intuisi untuk beberapa operasi inti saja.

  • Rentang small int caching di Python bukan 0~256, melainkan -5~256.
    Karena itu, pemula sering bingung dan mencampuradukkan identitas (is) dengan kesetaraan (==).

    • Java juga punya perilaku serupa. Bagi pemula ini bisa membingungkan.