உங்கள் SQL வேகமானது, ஆனால் API மெதுவாக உள்ளது

உங்கள் தரவுத்தள வினவல்கள் (database queries) வேகமானவை. உங்கள் கேச்சிங் (caching) சரியாக வேலை செய்கிறது. உங்கள் பின்னணி வேலைகள் (background jobs) சீராக உள்ளன.

இருப்பினும், உங்கள் API இன்னும் மெதுவாகவே உள்ளது. உங்கள் CPU பயன்பாடு அதிகமாக உள்ளது.

பிரச்சனை உங்கள் தரவுத்தளத்தில் இல்லை. பிரச்சனை Ruby லேயரில் (layer) உள்ளது.

தரவு தரவுத்தளத்திலிருந்து வெளியேறி உங்கள் பயன்பாட்டிற்குள் நுழையும்போது பெரும்பாலும் இந்தத் தடை (bottleneck) ஏற்படுகிறது. இது மூன்று முக்கிய காரணங்களால் நிகழ்கிறது:

  • வீக்கமடைந்த சீரியலைசேஷன் (Bloated serialization)
  • அதிகப்படியான ஆப்ஜெக்ட் ஒதுக்கீடு (Excessive object allocation)
  • மீண்டும் மீண்டும் செய்யப்படும் கணக்கீடுகள் (Repeated computation)

அவற்றைச் சரிசெய்வது எப்படி என்று இங்கே காணலாம்.

1. வீக்கமடைந்த சீரியலைசேஷனைத் தவிர்க்கவும் (Stop Bloated Serialization)

பல டெவலப்பர்கள் முழு மாடல்களையும் (models) JSON ஆக மாற்றுகிறார்கள்.

render json: @shipments

ஒரு ஷிப்மென்ட்டில் (shipment) 40 காலம்கள் (columns) இருந்து, உங்கள் முன்பக்கத்திற்கு (frontend) 5 மட்டும் தேவைப்பட்டால், நீங்கள் CPU சுழற்சிகளை (cycles) வீணடிக்கிறீர்கள். மேலும், API சாவிகள் (keys) அல்லது செலவுகள் போன்ற தனிப்பட்ட தரவுகள் கசியும் அபாயமும் உள்ளது.

தீர்வு: உங்களுக்குத் தேவையான புலங்களை (fields) மட்டும் திருப்பி அனுப்பவும்.

render json: @shipments.as_json(only: [:id, :tracking_no, :status])

இன்னும் சிறந்த வேகத்திற்கு, தரவை அரேக்களாக (arrays) எடுக்க pluck பயன்படுத்தவும். இது கனமான ActiveRecord ஆப்ஜெக்ட்களை உருவாக்குவதைத் முற்றிலும் தவிர்க்கிறது.

2. ஆப்ஜெக்ட் ஒதுக்கீட்டைக் குறைக்கவும் (Reduce Object Allocation)

Ruby உருவாக்கும் ஒவ்வொரு ஆப்ஜெக்ட்டும் நினைவகத்தை (memory) எடுத்துக்கொள்கிறது. ஒரு ஒற்றை கோரிக்கையின் (request) போது ஆயிரக்கணக்கான ஆப்ஜெக்ட்களை உருவாக்குவது, Garbage Collector (GC)-ஐ கடினமாக உழைக்கத் தூண்டுகிறது. இது உங்கள் முழு அமைப்பையும் மெதுவாக்குகிறது.

லூப்களுக்குள் (loops) புதிய ஹாஷ்கள் (hashes) அல்லது சரங்களை (strings) உருவாக்குவதைத் தவிர்க்கவும்.

தவறு:

@shipments.map do |s|
  { label: "#{s.tracking_no} - #{s.status.upcase}" }
end

சரி: நிலையான தரவை (static data) லூப்பிற்கு வெளியே கொண்டு வரவும். Ruby-யில் செய்வதை விட தரவுத்தளத்திலேயே அதிக வேலைகளைச் செய்யவும்.

3. மீண்டும் மீண்டும் செய்யப்படும் கணக்கீடுகளைத் தவிர்க்கவும் (Avoid Repeated Computation)

ஒரு கோரிக்கையில் ஒரே மெத்தடை (method) பலமுறை அழைத்தால், நீங்கள் நேரத்தை வீணடிக்கிறீர்கள்.

உதாரணம்:

def total_weight
  shipments.sum(&:weight)
end

உங்கள் வியூ (view), ஹெல்பர் (helper) மற்றும் சீரியலைசர் (serializer) ஆகிய அனைத்தும் இதை அழைத்தால், நீங்கள் கூட்டலை மூன்று முறை கணக்கிடுகிறீர்கள்.

தீர்வு: மெமோயைசேஷனை (memoization) பயன்படுத்தவும்.

def total_weight
  @total_weight ||= shipments.sum(&:weight)
end

இது ஒரு கோரிக்கைக்கு ஒருமுறை மட்டுமே கணக்கீடு நடப்பதை உறுதி செய்கிறது.

சுருக்க அட்டவணை:

  • வீக்கமடைந்த சீரியலைசேஷன்: தேவையான புலங்களை மட்டும் திருப்பி அனுப்பவும் அல்லது pluck பயன்படுத்தவும்.
  • அதிக ஒதுக்கீடு: லூப்களில் குறைவான ஆப்ஜெக்ட்களை உருவாக்கவும்.
  • மீண்டும் மீண்டும் செய்யப்படும் கணக்கீடு: முடிவுகளை மீண்டும் பயன்படுத்த மெமோயைசேஷனைப் பயன்படுத்தவும்.

தரவுத்தள மேம்படுத்தல் (Database optimization) என்பது குறைந்த தரவைக் கேட்பதாகும். பயன்பாட்டு மேம்படுத்தல் (Application optimization) என்பது தரவைப் பெற்ற பிறகு தேவையற்ற வேலைகளைக் குறைப்பதாகும்.

Source: https://dev.to/danewu/your-sql-is-fast-but-the-api-is-slow-its-the-ruby-layer-2fno