Skip to content

Performance: Throughput Scaling & Parallel Operations ​

Tại Sao Quan Trọng Trong Production ​

GCS không phải block storage — throughput không phụ thuộc vào provisioned capacity. Thay vào đó, throughput phụ thuộc vào request rate pattern và object naming strategy. Hiểu sai model này dẫn đến hai failure modes: hotspotting (request tập trung vào prefix nhỏ → throttle) và under-utilization (không parallelize đủ → 10x slower than achievable). Với ML training pipelines hay data processing at scale, chênh lệch có thể là vài giờ vs vài phút.


Internal Model — Auto-Scaling Request Handling ​

GCS Không Có "Provisioned Throughput" ​

Khác với Persistent Disk hay Filestore (cần provision IOPS), GCS auto-scale throughput dựa trên demand. Nhưng không phải vô hạn ngay lập tức — có baseline capacity và scale-up mechanism.

Baseline capacity mặc định:

  • ~1,000 write requests/giây (per bucket)
  • ~5,000 read requests/giây (per bucket)

Với object size 1MB, điều này tương đương:

  • Write: ~1 GB/s
  • Read: ~5 GB/s

Baseline này apply cho tổng bucket, không phải per-prefix hay per-object.

Auto-Scaling Mechanism — Gradual Ramp-Up ​

Khi workload vượt baseline, GCS tự động scale bằng cách redistribute load across more servers. Nhưng quá trình này mất thời gian:

Theo GCP documentation: "Cloud Storage typically takes on the order of minutes to detect and accordingly redistribute the load."

Trong thời gian transition, requests vượt baseline có thể nhận:

  • Higher latency (server load tăng)
  • 429 Too Many Requests errors (temporary throttle)
  • 503 Service Unavailable (server overload)

Implication cho production: Không thể đột ngột spike từ 100 req/s lên 10,000 req/s. Cần gradual ramp-up:

# Recommended ramp-up pattern
# Tăng không nhanh hơn 2x mỗi 20 phút
Giờ 0:    100 req/s
Giờ 0:20  200 req/s
Giờ 0:40  400 req/s
Giờ 1:00  800 req/s
...

Với migration jobs hay batch processing lớn, bắt đầu từ số nhỏ và tăng dần.

Hierarchical Namespace (HNS) Buckets ​

Buckets với hierarchical namespace enabled có baseline cao hơn 8x:

  • Write: ~8,000 req/s initial
  • Read: ~40,000 req/s initial

HNS cũng enable atomic directory operations và better directory listing performance. Đây là default recommendation cho high-throughput workloads (AI/ML data pipelines, analytics).


Object Naming Strategy — Hotspot Avoidance ​

Cơ Chế Phân Tải Theo Prefix ​

GCS distribute load theo lexicographic prefix ranges. Internal sharding assign ranges của key space cho các servers:

Server A: "aaa..." - "mzz..."
Server B: "n..." - "zzz..."

Nếu tất cả objects của bạn có prefix 2024-01-01-, mọi requests đều đến cùng shard → hotspot.

Sequential Naming — Anti-Pattern ​

# Hotspot pattern:
log-2024-01-01-000001.gz
log-2024-01-01-000002.gz
log-2024-01-01-000003.gz
...
# Tất cả bắt đầu bằng "log-2024-01-01-" → cùng shard

Sequential names (timestamps, counters) tập trung traffic vào narrow prefix range → single shard bị overwhelm.

Random Prefix — Cách Đúng ​

python
import hashlib
import time

def distributed_object_name(base_name: str) -> str:
    # Tính MD5 hash của tên gốc
    hash_prefix = hashlib.md5(base_name.encode()).hexdigest()[:6]
    return f"{hash_prefix}-{base_name}"

# Output:
# "a3f2c1-log-2024-01-01-000001.gz"  → shard 'a'
# "b7d4e2-log-2024-01-01-000002.gz"  → shard 'b'
# "f1a8c3-log-2024-01-01-000003.gz"  → shard 'f'

Với single hex character prefix, có 16 possible prefixes → distribute across ~16 shards. Hai hex characters → 256 prefixes → tốt hơn.

Tradeoff: Object listing không còn sequential theo thời gian — cần metadata (BigQuery table, Firestore) để track nếu cần ordered access.

Khi Sequential Naming Acceptable ​

Nếu write rate thấp (< 1000 req/s) và objects có distribution tự nhiên đủ rộng, sequential naming không nhất thiết gây vấn đề. Chỉ cần random prefix khi:

  • Write rate cao (> 1000 req/s)
  • Nhiều objects chia sẻ long common prefix
  • Cần maximum throughput

Parallel Operations ​

Parallel Uploads — Multipart và Composite Objects ​

Resumable uploads (cho files > 5MB) upload từng chunk sequentially qua HTTP. Single-stream throughput bị giới hạn bởi:

  • Network latency (RTT)
  • TCP window size
  • Một connection duy nhất

Parallel upload pattern: Chia file thành nhiều chunks, upload song song, compose thành object cuối:

python
from google.cloud import storage
import concurrent.futures

def parallel_upload(bucket_name: str, object_name: str, file_path: str, chunk_size_mb: int = 32):
    client = storage.Client()
    bucket = client.bucket(bucket_name)
    
    # Đọc file và chia thành chunks
    chunks = read_chunks(file_path, chunk_size_mb * 1024 * 1024)
    part_names = []
    
    def upload_chunk(i, data):
        part_name = f"{object_name}.part.{i:04d}"
        blob = bucket.blob(part_name)
        blob.upload_from_string(data)
        return part_name
    
    # Upload song song
    with concurrent.futures.ThreadPoolExecutor(max_workers=16) as executor:
        futures = {executor.submit(upload_chunk, i, data): i
                   for i, data in enumerate(chunks)}
        for future in concurrent.futures.as_completed(futures):
            part_names.append(future.result())
    
    # Sort parts theo thứ tự
    part_names.sort()
    
    # Compose thành final object
    destination = bucket.blob(object_name)
    sources = [bucket.blob(name) for name in part_names]
    destination.compose(sources)
    
    # Cleanup parts
    for name in part_names:
        bucket.blob(name).delete()

Composite Objects là GCS feature cho phép compose tối đa 1024 component objects thành 1 object. Mỗi component tối đa 5 TiB → total composite object tối đa 5 TiB.

compose là server-side operation — không cần download và re-upload data. GCS concatenate components on server. Tuy nhiên, composed object có một limitation: không có MD5 checksum (do GCS không biết tổng checksum khi compose). CRC32c checksum vẫn available.

Parallel Downloads ​

Download throughput scale bằng cách:

1. Multiple parallel requests cho different objects:

python
def parallel_download(objects: list, local_dir: str):
    with concurrent.futures.ThreadPoolExecutor(max_workers=32) as executor:
        futures = [
            executor.submit(download_object, obj, local_dir)
            for obj in objects
        ]
        for f in concurrent.futures.as_completed(futures):
            f.result()

2. Range requests cho single large object:

python
def download_large_object(bucket_name: str, object_name: str, output_path: str):
    client = storage.Client()
    blob = client.bucket(bucket_name).blob(object_name)
    
    size = blob.size
    chunk_size = 64 * 1024 * 1024  # 64MB chunks
    
    def download_range(start, end):
        with blob.open("rb") as f:
            f.seek(start)
            return f.read(end - start)
    
    chunks = []
    with concurrent.futures.ThreadPoolExecutor(max_workers=8) as executor:
        futures = [
            executor.submit(download_range, start, min(start + chunk_size, size))
            for start in range(0, size, chunk_size)
        ]
        chunks = [f.result() for f in futures]
    
    with open(output_path, "wb") as f:
        for chunk in chunks:
            f.write(chunk)

GCS support range reads (Range: bytes=start-end header) — không cần download toàn bộ object chỉ để đọc một portion.


Performance Ceilings Thực Tế ​

Per-Object Throughput ​

Một single object download bị giới hạn bởi:

  • Single TCP connection bandwidth
  • Network egress bandwidth của VM
  • GCS per-object streaming rate

GCS không publish per-object cap chính thức, nhưng trong practice:

  • Regional bucket, same region VM: ~1-2 Gbps per connection
  • Multi-region bucket: lower và variable

Để maximize throughput cho single large object: dùng parallel range reads.

Aggregate Bucket Throughput ​

Với đủ parallelism và tốt object naming, aggregate bucket throughput của GCS có thể đạt hundreds of Gbps. Điều này không phải cap mà là practical limit dựa trên:

  • Number of parallel requests
  • Object size distribution (nhỏ → overhead cao hơn)
  • Network capacity của client

Client-Side Bottlenecks ​

Thường bottleneck không phải GCS mà là:

1. Network bandwidth của VM:

n1-standard-4: ~10 Gbps (burst), ~2 Gbps sustained
c2-standard-8: ~32 Gbps

Nếu cần > 10 Gbps throughput từ GCS, cần nhiều VMs hoặc VMs với high-bandwidth.

2. CPU cho checksum computation:

CRC32c được hardware-accelerated trên modern CPUs (ARM và x86 với SSE4.2). MD5 không được hardware-accelerated → có thể bottleneck ở CPU với high-throughput downloads.

3. Disk I/O:

Write speed của local disk thường là bottleneck cho download pipelines. Local SSD (~800MB/s) vs standard HDD (~200MB/s).


Best Practices Summary ​

SituationRecommendation
> 1000 req/s write rateRandom prefix cho object names
Large file upload (> 100MB)Parallel upload + compose
Many objects downloadThreadPoolExecutor với 16-64 workers
Single large downloadParallel range requests
Gradual scale-upDouble request rate mỗi 20 phút
High-throughput AI/MLBuckets với HNS enabled
On-prem dataTransfer Service + dedicated agents

References ​