cicadel

Measure performance

Measure a real route or query before you change it. Include authentication, database access and rendering when they are part of the path.

#Ask your agent

Text
Read https://cicadel.fauzaanu.com/en/0.2.8/howto/performance/index.md.
Investigate [slow route or operation] in this application.
Create a representative benchmark, record latency and allocations, and profile it.
Fix the measured bottleneck while preserving behavior and permissions.
Compare repeated runs and report the workload and any remaining uncertainty.

#Benchmark a handler

Add a benchmark next to the handler you want to measure. This template uses a generated notes app. Replace it with your real handler and its dependencies.

Go
package notes

import (
    "net/http/httptest"
    "testing"
)

func BenchmarkIndex(b *testing.B) {
    request := httptest.NewRequest("GET", "/notes/", nil)
    b.ReportAllocs()
    for b.Loop() {
        recorder := httptest.NewRecorder()
        Index(recorder, request)
        if recorder.Code != 200 {
            b.Fatalf("status = %d", recorder.Code)
        }
    }
}

Run it five times:

Terminal
go test ./apps/notes -run '^$' -bench BenchmarkIndex -benchmem -count=5

This measures the handler directly. It leaves out network, middleware and database costs unless your setup includes them.

#Profile the operation

Terminal
go test ./apps/notes -run '^$' -bench BenchmarkIndex -benchtime=5s \
  -cpuprofile=cpu.out -memprofile=mem.out
go tool pprof -top cpu.out
go tool pprof -top -alloc_space mem.out

For database work, load representative rows into a disposable PostgreSQL database.

#Compare a change

  1. Keep the same inputs, dataset and concurrency before and after the change.
  2. Record errors as well as latency.
  3. Repeat the runs. One short run is not enough to claim a speedup.

Do not use a development server’s latency as your production capacity estimate.

#Compared with Django

The documentation home page compares the standard Cicadel project with a vanilla Django 6.1 project on the same machine, both on PostgreSQL with auth, sessions and CSRF.

MeasureCicadelDjango
Container image35 MB320 MB
Memory at idle24 MB86 MB (1 gunicorn worker)
Requests per second~23,000~10,300 (10 gunicorn workers, 581 MB)
Median response1 ms2 ms (10 workers)

The method, versions, raw results and a harness to reproduce them are in the comparison notes. Re-run it on your own hardware before relying on a number.

Type to search this version.