1 of 44

Is COG Scaleable?

Jeff Albrecht

2 of 44

3 of 44

Tile Server

4 of 44

5 of 44

Blob Store Characteristics

  • Minimize Time to First Byte (TTFB) by sending as few requests as possible.
    • Connecting to the blob store is expensive, data transfer through an open connection is cheap.
  • S3 supports at least 5,500 GETs per second per key prefix.
    • Experimentally, its close to ~8,500 GETs to ~15,000 GETs per second

s3://cog-layers-glad/7/28/49/0231102/tile.tif

6 of 44

Scaling Blob Stores is Easy!

  1. Send as few requests as possible.
  2. Send those requests as fast and efficiently as possible.

7 of 44

COG Internal Structure

8 of 44

8192

8192

Tile(x=28, y=49, z=7)

9 of 44

10 of 44

Web Optimized COG

  • Each internal tile aligned to the web mercator grid, coverings Z7 -> Z12.
    • 16,384 images in the world.
  • Reading a single XYZ tile requires:
    • 1 request to fetch the header.
    • 1 request to fetch the block.

This is, in theory, the most optimized COG layout for this use case.

11 of 44

12 of 44

Caching

13 of 44

Most applications have some sort of local cache.

14 of 44

Requests are load balanced across replicas (round robin).

15 of 44

Requests are load balanced across replicas (round robin).

Requires 3 requests for all replicas to cache the header.

16 of 44

Round Robin

Number Images

Number Replicas

Scenario

Number of Requests

100

100

Perfect Caching

100

100

100

Local Caching

10000

17 of 44

Round Robin

n_replicas = 100

n_images = 100

18 of 44

Round Robin

n_replicas = 100

n_images = 100

19 of 44

Cache (In)efficiency

20 of 44

Distributed Caching Patterns

21 of 44

Cache aside

22 of 44

Peer-to-peer cache

(groupcache)

23 of 44

Forward-proxy

24 of 44

25 of 44

MetaTiling

26 of 44

MetaTiling

  • COGs are row major.
  • Metatiling logically increases chunk size without changing physical chunk size.

(8192, 8192) image with (256x256) chunk size contains 1024 chunks.

(8192, 8192) image with (4096x4096) contains 4 meta-chunks.

27 of 44

28 of 44

Sending Requests Quickly

29 of 44

Send Request Quickly

  • Use async/await where possible, it’s more efficient.
  • Use lower level languages like rust / go.
  • Maintain strong data locality.
  • Always request COG headers in one request (know your header size ahead of time).

30 of 44

In Practice

31 of 44

pyasyncio-benchmark

  • Built a tool specifically designed to benchmark I/O bound python code across different libraries:
    • aioboto3
    • aiohttp
    • fsspec (s3fs)
    • httpx
    • obstore
    • requests
    • rasterio
  • All tests run across 20 containers on an m5.8xlarge instance.

https://github.com/geospatial-jeff/pyasyncio-benchmark

32 of 44

pyasyncio-benchmark

  • Built a tool specifically designed to benchmark I/O bound python code.

33 of 44

Header Requests (m5.8xlarge)

34 of 44

MetaTiling (m5.8xlarge)

Dump all native resolution tiles (1024).

35 of 44

MetaTiling (m5.8xlarge)

ignore httpx :(

36 of 44

Is COG Scaleable?

37 of 44

Yes, it is.

38 of 44

Yes, it is. But our software is not written in a way that encourages or achieves scalable system design in the cloud.

39 of 44

Yes, it is. But our software is not written in a way that encourages or achieves scalable system design in the cloud.

Software, hardware, and data are in constant co-evolution. Code doesn’t age, but context does change.

40 of 44

Yes, it is. But our software is not written in a way that encourages or achieves scalable system design in the cloud.

Software, hardware, and data are in constant co-evolution. Code doesn’t age, but context does change.

As the CNG community standardizes on individual data formats (ex. Zarr / COG) it makes sense to invest more in specialized tooling for those formats.

41 of 44

42 of 44

43 of 44

44 of 44

Questions