Je SQL is snel, maar de API is traag
Je databasequeries zijn snel. Je caching werkt. Je background jobs zijn in orde.
Toch is je API nog steeds traag. Je CPU-gebruik is hoog.
Het probleem is niet je database. Het probleem is de Ruby-laag.
De bottleneck ontstaat vaak nadat de data de database verlaat en je applicatie binnenkomt. Dit komt door drie hoofdoorzaken:
- Opgeblazen serialisatie
- Excessieve objectallocatie
- Herhaalde berekeningen
Hier is hoe je ze oplost.
- Stop met opgeblazen serialisatie
Veel ontwikkelaars zetten volledige modellen om naar JSON.
render json: @shipments
Als een zending 40 kolommen heeft, maar je frontend heeft er slechts 5 nodig, verspil je CPU-cycli. Je loopt ook het risico op het lekken van privacygevoelige gegevens zoals API-sleutels of kosten.
De oplossing: retourneer alleen de velden die je nodig hebt.
render json: @shipments.as_json(only: [:id, :tracking_no, :status])
Voor nog meer snelheid kun je pluck gebruiken om data als arrays op te halen. Hiermee voorkom je het volledig aanmaken van zware ActiveRecord-objecten.
- Verminder objectallocatie
Elk object dat Ruby aanmaakt, kost geheugen. Het aanmaken van duizenden objecten tijdens een enkele request dwingt de Garbage Collector (GC) om harder te werken. Dit vertraagt je hele systeem.
Vermijd het aanmaken van nieuwe hashes of strings binnen loops.
Fout:
@shipments.map do |s|
{ label: "#{s.tracking_no} - #{s.status.upcase}" }
end
Goed: Verplaats statische data buiten de loop. Doe meer werk in de database in plaats van in Ruby.
- Vermijd herhaalde berekeningen
Als je dezelfde methode meerdere keren aanroept in één request, verspil je tijd.
Voorbeeld:
def total_weight
shipments.sum(&:weight)
end
Als je view, helper en serializer dit allemaal aanroepen, bereken je de som drie keer.
De oplossing: gebruik memoization.
def total_weight
@total_weight ||= shipments.sum(&:weight)
end
Dit zorgt ervoor dat de berekening slechts één keer per request plaatsvindt.
Samenvattende tabel:
- Opgeblazen serialisatie: Retourneer alleen de benodigde velden of gebruik
pluck. - Hoge allocatie: Maak minder objecten aan in loops.
- Herhaalde berekeningen: Gebruik memoization om resultaten te hergebruiken.
Database-optimalisatie betekent minder data opvragen. Applicatie-optimalisatie betekent minder onnodig werk doen zodra je de data hebt.
Bron: https://dev.to/danewu/your-sql-is-fast-but-the-api-is-slow-its-the-ruby-layer-2fno
