---
id: e52d68870be3de9f644fcfc584bd8aec
author: Lemon Mint
title: 'gosuda.org/zstd: Sıfır CGO ve Çökme İzolasyonu ile DataDog/zstd''nin Doğrudan Yerine Kullanılabilen Sıkıştırma Kütüphanesi'
description: CGO_ENABLED=0 ile çalışan, paylaşımlı bellek tabanlı bir işçi içinde upstream C libzstd 1.5.7 sürümünü çalıştıran, DataDog/zstd ile uyumlu bir API sunan, yeniden kullanılabilir bağlamlar (contexts) ve toplu işleme (bulk batching) desteği bulunan bir Go Zstandard kütüphanesi.
language: tr
date: 2026-10-18T14:07:11.281986997Z
path: /zstd
go_package: gosuda.org/zstd
go_repourl: https://github.com/gosuda/hqq-zstd.git
category: lowlevel
---

`gosuda.org/zstd`, `CGO_ENABLED=0` ile çalışan bir Go sıkıştırma kütüphanesidir; resmi C Zstandard (`libzstd 1.5.7`) motorunu, [HQQ](https://gosuda.org/hqq) paylaşımlı belleği üzerinden yalıtılmış bir çalışan süreç (worker process) içinde çalıştırır. `github.com/DataDog/zstd` için doğrudan yerine geçebilen bir API sunar (tek seferlik `Compress`/`Decompress`, akış tabanlı `io.Writer`/`io.Reader`, önceden işlenmiş sözlükler ve yeniden kullanılabilir sıfır ayırmalı bağlamlar dahil) ve C yürütmesini Go çalışma zamanı adres alanının tamamen dışında tutar.

```bash
go get gosuda.org/zstd@v0.3.10507
```

## Sıkıştırma ve Açmanın Neden Go Yığınınızın Dışında Yer Alması Gerektiği

Üretim ortamındaki arka uç sistemlerinde sıkıştırma ve sıkıştırma açma işlemleri doğrudan güvenilmeyen girdi sınırında gerçekleşir. Günlük toplayıcıları, mesaj aracıları, RPC ağ geçitleri ve depolama motorları, her dakika gigabaytlarca dışarıdan sağlanan çerçeveyi açar.

Birçok Go ekibi `github.com/DataDog/zstd` kütüphanesini tercih eder; çünkü bu kütüphane doğrudan üst akış C `libzstd` ile bağlanır: C uygulaması yüksek tek çekirdek verimi, küçük kayıtlarda sıkı sözlük sıkıştırma oranları ve Go çöp toplama tarama sürelerini artırmayan, yığın dışı C bellek alanları (`ZSTD_CCtx` ve `ZSTD_DCtx`) sunar.

Ancak `libzstd` kütüphanesini `cgo` üzerinden bir Go servisine bağlamak iki operasyonel sorun doğurur:

1. **Derleme ve Dağıtım Sürtünmesi**: `go-sqlite3` gibi, `DataDog/zstd` de `CGO_ENABLED=1` ve hedef bir C derleyici araç zinciri gerektirir. `linux/arm64` veya `windows/arm64` için servisleri çapraz derlemek ya da statik ikili dosyalar oluşturmak harici C sysroot'ları gerektirir.
2. **Güvenilmeyen Girdilerde Paylaşılan Adres Alanı**: Bozuk veya düşmanca yükleri Go sunucunuzla aynı sanal adres alanında açmak, yerel C kodundaki veya özel sözlük işlemesindeki herhangi bir hata tüm Go sürecini sonlandırabilir.

`gosuda.org/zstd`, tam olarak üst akış C `libzstd 1.5.7` motorunu ve tanıdık `github.com/DataDog/zstd` API'sini korur; ancak C yürütmesini, önbellek hattı paylaşımlı belleği üzerinden Go programınıza bağlı doğrulanmış bir alt süreçe (`zstd_server`) taşır.

## `github.com/DataDog/zstd` İçin Doğrudan Yerine Geçen Kütüphane

`github.com/DataDog/zstd` kütüphanesinden geçiş yapmak yalnızca içe aktarma yolunun `"gosuda.org/zstd"` olarak değiştirilmesini gerektirir. Harici bir ikili dosya kurulumu veya kurulum kodu gerekmez: ilk çağrıda `gosuda.org/zstd`, platformunuz için gömülü, SLSA ile onaylanmış bir `zstd_server` ikili dosyasını açığa çıkarır, SHA-256 özetini `gosuda.org/hqq/secureexec` aracılığıyla doğrular ve bir paylaşımlı bellek oturum havuzu açar.

```go
package main

import (
	"bytes"
	"fmt"
	"io"
	"log"

	"gosuda.org/zstd"
)

func main() {
	// 1. Tek seferlik Compress / Decompress (github.com/DataDog/zstd ile aynıdır)
	src := []byte("shared-memory zstd payload without cgo")
	compressed, err := zstd.CompressLevel(nil, src, zstd.BestSpeed)
	if err != nil {
		log.Fatal(err)
	}
	plain, err := zstd.Decompress(nil, compressed)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("one-shot: %d bytes -> %d bytes (%s)\n", len(src), len(compressed), plain)

	// 2. Sözlük desteğiyle akış Writer ve Reader
	var buf bytes.Buffer
	w := zstd.NewWriterLevel(&buf, zstd.DefaultCompression)
	if _, err := w.Write(src); err != nil {
		log.Fatal(err)
	}
	if err := w.Close(); err != nil {
		log.Fatal(err)
	}

	r := zstd.NewReader(&buf)
	defer r.Close()
	streamed, err := io.ReadAll(r)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("streamed: %s\n", streamed)
}
```

### Desteklenen Platformlar ve Gömülü İkili Dosyalar

Altı hedef platformun tamamı, platforma özgü derleme etiketleri (`internal/embedded/embed_<goos>_<goarch>.go`) aracılığıyla gömülü, SHA-256 ile sabitlenmiş önceden derlenmiş çalışan ikili dosyalarla gelir:

| Hedef İşletim Sistemi | Hedef Mimari (`GOARCH`) | Gömülü İkili Dosya              |   İkili Dosya Boyutu | Derleme Araç Zinciri ve Köken                     |
| :-------------------- | :---------------------- | :------------------------------ | -------------------: | :------------------------------------------------ |
| **Linux**             | `amd64`, `arm64`        | `zstd_server_linux_<arch>`      | ~770 - 880 KiB       | GCC `-O3`, SLSA Build L3 Köken                    |
| **macOS**             | `arm64`, `amd64`        | `zstd_server_darwin_<arch>`     | ~660 - 795 KiB       | AppleClang `-O3`, SLSA Build L3 Köken             |
| **Windows**           | `amd64`                 | `zstd_server_windows_amd64.exe` |          ~818 KiB    | MSVC `-O2`, SLSA Build L3 Köken                   |
| **Windows**           | `arm64`                 | `zstd_server_windows_arm64.exe` |          ~551 KiB    | `zig cc -target aarch64-windows-gnu -O3`, SLSA L3 |

## Paylaşımlı Bellek Veri Yolunun İçinde

`gosuda.org/zstd`, süreç içi `cgo` ile rekabetçi verimi korumak için sıcak yolda soket serileştirmesinden ve yığın ayırmalarından kaçınır.

### 1. Sıfır Ayırmalı Yuva Kodlaması (`zstd_ctx.go` ve `c/zstd_hooks.c`)

Yeniden kullanılabilir bir `zstd.Ctx` kullandığınızda (veya paket düzeyindeki `Compress` ve `Decompress` fonksiyonları dahili oturum havuzundan bir `Ctx` ödünç aldığında), veri eşlenmiş `StandardLink` yuvası üzerinden doğrudan akar:

```text
Go Çağrıcı (zstd.Ctx)                   Paylaşımlı Bellek Yuvası              C11 Çalışanı (zstd_hooks.c)
---------------------                   ------------------------              ---------------------------
src []byte  ------------------------->  İstek Yuvası Yükü  ---------------->  ZSTD_compressCCtx(
                                                                                cctx, resp_slot, src, level)
dst []byte  <-------------------------  Yanıt Yuvası Yükü  <----------------  Sıkıştırılmış çerçeveyi doğrudan
                                                                              paylaşımlı yanıt yuvasına yazar
```

1. Üretilmiş `hqq-bindgen` istemcisi, `src` verisini bellek eşlemeli istek yuvasına doğrudan kopyalar ve `SeqLock` sıra sözcüğünü çevirir.
2. C çalışanı `src` verisini istek yuvasından yerinde okur ve yanıt yuvasının yük işaretçisini hedef arabellek olarak doğrudan `ZSTD_compressCCtx` veya `ZSTD_decompressDCtx` fonksiyonuna geçirir.
3. Go istemcisi ortaya çıkan dilimi yanıt yuvasından çağıranın sağladığı `dst` dilimine kopyalar. Kararlı durumda `ctx.CompressTo(dst, src, level)` ve `ctx.DecompressInto(dst, src)` işlemleri `0 allocs/op` gerçekleştirir.

Önceden işlenmiş sözlükler (`CDict` ve `DDict`), `zstd.idl` içindeki nesil kontrollü 64 bitlik tutamaçların (`handle CDict`, `handle DDict`) arkasında C çalışanı üzerinde yaşar. `ctx.NewCDict(rawDict, level)` ile bir sözlüğü bir kez oluşturmak, sözlük tablolarını C çalışanının içinde ayrıştırır ve sözlük baytlarını yeniden göndermeden binlerce çağrı boyunca yeniden kullanılabilen hafif bir tutamaç döndürür.

### 2. Toplu Çerçeveleme ile IPC Ek Yükünün Amortismanı (`zstd_bulk.go`)

Büyük yükler (16 KiB ve üzeri) için yaklaşık 200 ns'lik paylaşımlı bellek gidiş-dönüş süresi, `libzstd` içinde harcanan CPU süresiyle karşılaştırıldığında ihmal edilebilir düzeydedir. Ancak her biri 100 bayt ile 1 KiB arasında olan binlerce küçük mesajı bir seferde sıkıştıran iş yükleri için, öğe başına 200 ns bile birikir.

`gosuda.org/zstd`, öğe başına gidiş-dönüşleri ortadan kaldırmak için `BulkCtx` (`zstd_bulk.go`) üzerinde `CompressBulk` ve `DecompressBulk` sağlar:

```go
bctx, err := client.NewBulkCtx(1 << 20)
if err != nil {
	log.Fatal(err)
}
defer bctx.Close()

items := [][]byte{
	[]byte(`{"event":"login","user":101}`),
	[]byte(`{"event":"purchase","user":101,"amount":4200}`),
	[]byte(`{"event":"logout","user":101}`),
}
compressedItems, err := bctx.CompressBulk(nil, items, zstd.DefaultCompression)
```

`CompressBulk`, tüm `[][]byte` grubunu paylaşımlı bellekte tek bir uzunluk önekli istek çerçevesine paketler. C çalışanı, her öğe üzerinde C içinde döngü yapar (`c/zstd_hooks.c` içindeki `compress_bulk`), sıkıştırılmış tüm çerçeveleri yanıt yuvasına bitişik olarak yazar ve tüm grubu tek bir paylaşımlı bellek gidiş-dönüşünde döndürür.

### 3. Çağıranı Çökertmeden Çalışan Sonlanmasından Kurtulma

`zstd_server` ayrı bir işletim sistemi sürecinde çalıştığı için, C çalışanının içindeki ölümcül bir hata Go uygulamanızı asla çökertmez:

- `zstd_server` dışarıdan sonlandırılırsa (örneğin `SIGKILL` veya bellek yetersizliği olayı ile), HQQ taşıma katmanı bozulmuş eşi hemen algılar ve devam eden `Compress` veya `Decompress` çağrısından tipli bir `*rt.TransportError` döndürür.
- Paket düzeyindeki işlevler (`zstd.Compress`, `zstd.Decompress`, `zstd.NewWriter`, `zstd.NewReader`), paylaşılan varsayılan çalışanın ortadan kalktığını otomatik olarak algılar, bir sonraki çağrıda yeni bir doğrulanmış `zstd_server` örneği başlatır ve normal işleyişe devam eder.

## Depo Yapısı

Kod tabanı, doğrudan `DataDog/zstd` yüzünü düşük seviyeli `hqq-bindgen` oturum ve toplu ilkellerinden ayırır:

```text
gosuda.org/zstd
├── autolaunch.go / hashes.go  # Doğrudan Compress/Decompress API'si, otomatik kurtarma havuzu ve SHA-256 özetleri
├── zstd_stream.go             # Akış Writer/Reader (NewWriterLevelDict, NewReaderDict)
├── zstd_ctx.go                # hqq-bindgen üzerinde sıfır ayırmalı Ctx, CDict ve DDict sarmalayıcıları
├── zstd_bulk.go               # Tek gidiş-dönüşlü CompressBulk ve DecompressBulk çerçevelemesi
├── zstd.go                    # Üretilmiş hqq-bindgen Go istemcisi (zstd IDL servisi için)
├── zstd.idl                   # Context, CDict, DDict ve RPC yöntemlerini tanımlayan HQQ IDL şeması
├── internal/embedded/         # Platform etiketli //go:embed zstd_server ikili dosyaları (6 OS/Mimari hedefi)
└── c/                         # C11 sunucu uygulaması (zstd_server.c, zstd_hooks.c, main.c)
```

## Başlarken

`gosuda.org/zstd` kütüphanesini `go get` ile kurun ve `CGO_ENABLED=0` ile kullanın:

```bash
go get gosuda.org/zstd@v0.3.10507
```

- **GitHub Deposu**: [https://github.com/gosuda/hqq-zstd](https://github.com/gosuda/hqq-zstd)
- **Mimari ve Kıyaslamalar**: [docs/ARCHITECTURE.md](https://github.com/gosuda/hqq-zstd/blob/main/docs/ARCHITECTURE.md)
- **HQQ Çekirdek Çalışma Zamanı**: [https://gosuda.org/hqq](https://gosuda.org/hqq)
