ನಿಮ್ಮ SQL ವೇಗವಾಗಿದೆ ಆದರೆ API ನಿಧಾನವಾಗಿದೆ

ನಿಮ್ಮ ಡೇಟಾಬೇಸ್ ಕ್ವೇರಿಗಳು ವೇಗವಾಗಿವೆ. ನಿಮ್ಮ ಕ್ಯಾಶಿಂಗ್ ಸರಿಯಾಗಿ ಕೆಲಸ ಮಾಡುತ್ತಿದೆ. ನಿಮ್ಮ ಬ್ಯಾಕ್‌ಗ್ರೌಂಡ್ ಜಾಬ್‌ಗಳು ಕೂಡ ಚೆನ್ನಾಗಿವೆ.

ಆದರೂ, ನಿಮ್ಮ API ಇನ್ನೂ ನಿಧಾನವಾಗಿದೆ. ನಿಮ್ಮ CPU ಬಳಕೆ ಹೆಚ್ಚಾಗಿದೆ.

ಸಮಸ್ಯೆ ನಿಮ್ಮ ಡೇಟಾಬೇಸ್ ಅಲ್ಲ. ಸಮಸ್ಯೆ Ruby ಲೇಯರ್‌ನಲ್ಲಿದೆ.

ಡೇಟಾ ಡೇಟಾಬೇಸ್‌ನಿಂದ ಹೊರಬಂದು ನಿಮ್ಮ ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಪ್ರವೇಶಿಸಿದ ನಂತರ ಹೆಚ್ಚಾಗಿ ಬಾಟಲ್ನೆಕ್ (bottleneck) ಉಂಟಾಗುತ್ತದೆ. ಇದು ಮುಖ್ಯವಾಗಿ ಮೂರು ಸಮಸ್ಯೆಗಳಿಂದ ಸಂಭವಿಸುತ್ತದೆ:

  • ಅತಿಯಾದ ಸೀರಿಯಲೈಸೇಶನ್ (Bloated serialization)
  • ಅತಿಯಾದ ಆಬ್ಜೆಕ್ಟ್ ಅಲೋಕೇಶನ್ (Excessive object allocation)
  • ಪುನರಾವರ್ತಿತ ಲೆಕ್ಕಾಚಾರ (Repeated computation)

ಅವುಗಳನ್ನು ಸರಿಪಡಿಸುವುದು ಹೇಗೆ ಎಂಬುದು ಇಲ್ಲಿದೆ.

  1. ಅತಿಯಾದ ಸೀರಿಯಲೈಸೇಶನ್ ಅನ್ನು ನಿಲ್ಲಿಸಿ

ಅನೇಕ ಡೆವಲಪರ್‌ಗಳು ಇಡೀ ಮಾಡೆಲ್‌ಗಳನ್ನು JSON ಆಗಿ ಪರಿವರ್ತಿಸುತ್ತಾರೆ.

render json: @shipments

ಒಂದು ಶಿಪ್‌ಮೆಂಟ್‌ಗೆ 40 ಕಾಲಮ್‌ಗಳಿದ್ದರೂ ನಿಮ್ಮ ಫ್ರಂಟ್‌ಎಂಡ್‌ನಲ್ಲಿ ಕೇವಲ 5 ಮಾತ್ರ ಬೇಕಿದ್ದಲ್ಲಿ, ನೀವು CPU ಸೈಕಲ್‌ಗಳನ್ನು ವ್ಯರ್ಥ ಮಾಡುತ್ತೀರಿ. ಅಲ್ಲದೆ, API ಕೀಗಳು ಅಥವಾ ವೆಚ್ಚಗಳಂತಹ ಖಾಸಗಿ ಡೇಟಾವನ್ನು ಸೋರಿಕೆ ಮಾಡುವ ಅಪಾಯವೂ ಇರುತ್ತದೆ.

ಪರಿಹಾರ: ನಿಮಗೆ ಬೇಕಾದ ಫೀಲ್ಡ್‌ಗಳನ್ನು ಮಾತ್ರ ಹಿಂತಿರುಗಿಸಿ.

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

ಇನ್ನೂ ಹೆಚ್ಚಿನ ವೇಗದಿಗಾಗಿ, ಡೇಟಾವನ್ನು ಅರೇಗಳಾಗಿ (arrays) ಪಡೆಯಲು pluck ಬಳಸಿ. ಇದು ಭಾರೀ ActiveRecord ಆಬ್ಜೆಕ್ಟ್‌ಗಳನ್ನು ನಿರ್ಮಿಸುವುದನ್ನು ಸಂಪೂರ್ಣವಾಗಿ ತಪ್ಪಿಸುತ್ತದೆ.

  1. ಆಬ್ಜೆಕ್ಟ್ ಅಲೋಕೇಶನ್ ಅನ್ನು ಕಡಿಮೆ ಮಾಡಿ

Ruby ರಚಿಸುವ ಪ್ರತಿಯೊಂದು ಆಬ್ಜೆಕ್ಟ್ ಕೂಡ ಮೆಮೊರಿಯನ್ನು ಬಳಸುತ್ತದೆ. ಒಂದೇ ರಿಕ್ವೆಸ್ಟ್ ಸಮಯದಲ್ಲಿ ಸಾವಿರಾರು ಆಬ್ಜೆಕ್ಟ್‌ಗಳನ್ನು ರಚಿಸುವುದು ಗಾರ್ಬೇಜ್ ಕಲೆಕ್ಟರ್ (Garbage Collector - GC) ಅನ್ನು ಹೆಚ್ಚು ಕೆಲಸ ಮಾಡಲು ಒತ್ತಾಯಿಸುತ್ತದೆ. ಇದು ನಿಮ್ಮ ಇಡೀ ಸಿಸ್ಟಮ್ ಅನ್ನು ನಿಧಾನಗೊಳಿಸುತ್ತದೆ.

ಲೂಪ್‌ಗಳ (loops) ಒಳಗೆ ಹೊಸ ಹ್ಯಾಶ್‌ಗಳು ಅಥವಾ ಸ್ಟ್ರಿಂಗ್‌ಗಳನ್ನು ರಚಿಸುವುದನ್ನು ತಪ್ಪಿಸಿ.

ಕೆಟ್ಟದು:

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

ಒಳ್ಳೆಯದು: ಸ್ಟ್ಯಾಟಿಕ್ ಡೇಟಾವನ್ನು ಲೂಪ್‌ನ ಹೊರಗೆ ತನ್ನಿ. Ruby ಗಿಂತ ಡೇಟಾಬೇಸ್‌ನಲ್ಲಿ ಹೆಚ್ಚಿನ ಕೆಲಸವನ್ನು ಮಾಡಿ.

  1. ಪುನರಾವರ್ತಿತ ಲೆಕ್ಕಾಚಾರವನ್ನು ತಪ್ಪಿಸಿ

ಒಂದೇ ರಿಕ್ವೆಸ್ಟ್‌ನಲ್ಲಿ ನೀವು ಒಂದೇ ಮೆಥಡ್ ಅನ್ನು ಹಲವು ಬಾರಿ ಕರೆ ಮಾಡಿದರೆ, ನೀವು ಸಮಯವನ್ನು ವ್ಯರ್ಥ ಮಾಡುತ್ತೀರಿ.

ಉದಾಹರಣೆ:

def total_weight
  shipments.sum(&:weight)
end

ನಿಮ್ಮ ವ್ಯೂ (view), ಹೆಲ್ಪರ್ (helper) ಮತ್ತು ಸೀರಿಯಲೈಸರ್ ಎಲ್ಲವೂ ಇದನ್ನು ಕರೆ ಮಾಡಿದರೆ, ನೀವು ಮೂರು ಬಾರಿ ಮೊತ್ತವನ್ನು ಲೆಕ್ಕಾಚಾರ ಮಾಡುತ್ತೀರಿ.

ಪರಿಹಾರ: ಮೆಮೊಯೈಸೇಶನ್ (memoization) ಬಳಸಿ.

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

ಇದು ಪ್ರತಿ ರಿಕ್ವೆಸ್ಟ್‌ಗೆ ಗಣಿತದ ಕೆಲಸ ಒಮ್ಮೆ ಮಾತ್ರ ನಡೆಯುವುದನ್ನು ಖಚಿತಪಡಿಸುತ್ತದೆ.

ಸಾರಾಂಶ ಕೋಷ್ಟಕ:

  • ಅತಿಯಾದ ಸೀರಿಯಲೈಸೇಶನ್: ಬೇಕಾದ ಫೀಲ್ಡ್‌ಗಳನ್ನು ಮಾತ್ರ ಹಿಂತಿರುಗಿಸಿ ಅಥವಾ pluck ಬಳಸಿ.
  • ಹೆಚ್ಚಿನ ಅಲೋಕೇಶನ್: ಲೂಪ್‌ಗಳಲ್ಲಿ ಕಡಿಮೆ ಆಬ್ಜೆಕ್ಟ್‌ಗಳನ್ನು ನಿರ್ಮಿಸಿ.
  • ಪುನರಾವರ್ತಿತ ಲೆಕ್ಕಾಚಾರ: ಫಲಿತಾಂಶಗಳನ್ನು ಮರುಬಳಕೆ ಮಾಡಲು ಮೆಮೊಯೈಸೇಶನ್ ಬಳಸಿ.

ಡೇಟಾಬೇಸ್ ಆಪ್ಟಿಮೈಸೇಶನ್ ಎಂದರೆ ಕಡಿಮೆ ಡೇಟಾವನ್ನು ಕೇಳುವುದು ಎಂದರ್ಥ. ಅಪ್ಲಿಕೇಶನ್ ಆಪ್ಟಿಮೈಸೇಶನ್ ಎಂದರೆ ಡೇಟಾ ಸಿಕ್ಕಿದ ನಂತರ ಕಡಿಮೆ ಅನಗತ್ಯ ಕೆಲಸಗಳನ್ನು ಮಾಡುವುದು ಎಂದರ್ಥ.

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