Rails JSON APIとサービス高速化 / JSON Serializer 2020

88493e31e8ac7540094d35f7cda46c8a?s=47 lni_T
July 30, 2020

Rails JSON APIとサービス高速化 / JSON Serializer 2020

「リードエンジニアから学ぶMedPeerのプロダクト開発」
https://medpeer.connpass.com/event/181835/

88493e31e8ac7540094d35f7cda46c8a?s=128

lni_T

July 30, 2020
Tweet

Transcript

  1. +40/"1*ͱ αʔϏεߴ଎Խ

  2. ࣗݾ঺հ w 5XJUUFS!MOJ@5
 (JUIVC!MOJU w .FE1FFS&OHJOFFS ʙ  w ޷͖ͳ3BJMTͷϝιου


    QSFTFODF w ݏ͍ͳ3BJMTͷϝιου
 BDDFQUT@OFTUFE@BUUSJCVUFT@GPS
  3. ΫϦχοΫ։ۀࢧԉ ϓϥοτϑΥʔϜ

  4. ෺݅୳͠ ϊ΢ϋ΢ऩू

  5. ͭͬͨ͘ػೳ (PPHMF.BQ্Ͱ ෺݅୳͠ ڝ߹ͷఁ࡯ ױऀ਺༧ଌ ͕ͻͱ໨Ͱ෼͔Δ΍ͭ

  6. ϦϦʔεޙʹ໰୊͕

  7. ͱͯ΋஗͍

  8. ද͕ࣔ஗͍  ݕࡧ͔ͯ͠Β෺݅Λදࣔ͢Δ·Ͱʜ ඵʙඵ

  9. ෺݅୳͠αʔϏε ͳͷʹ ୳͢ͷ͕஗͍ʂ

  10. +40/"1*Λ଎͘ʂ ˢຊ೔ͷςʔϚ

  11. ݪҼ͸ʁ

  12. ୹བྷతࢥߟ  ฦ٫͢Δ݅਺ʹൺྫͯ͠ύϑΥʔϚϯεѱԽ

  13. ୹བྷతࢥߟ  ฦ٫͢Δ݅਺ʹൺྫͯ͠ύϑΥʔϚϯεѱԽ  ύϑΥʔϚϯε໰୊ͱ͍͑͹%# Ͱ ͑ ΂ ͑

  14. ୹བྷతࢥߟ  %#पΓͷΑ͋͘ΔରԠΛ΍ͬͯ΋Βͬͨ  JOEFYுΔ  / ͳ͘͢

  15. ղܾʂ ΊͰͨ͠ʁ

  16. ղܾ͠ͳ͔ͬͨ ෺݅"1*      վળલ վળޙ

  17. ͱͯ΋஗͍ˠ஗͍ ඵˠඵ

  18. ϘτϧωοΫ୳͠  %#͡Όͳ͍ͳΒʜ Completed 200 OK in 2199ms (Views: 2127.1ms

    | ActiveRecord: 51.2ms) Completed 200 OK in 2300ms (Views: 2200.7ms | ActiveRecord: 67.0ms)
  19. ϘτϧωοΫ୳͠  7JFXT͕஗͍ʂ  KTPOͷϨϯμϦϯά෦෼ʁ (Views: 2127.1ms | ActiveRecord: 51.2ms)

    (Views: 2200.7ms | ActiveRecord: 67.0ms)
  20. +40/γϦΞϥΠζ ͳΜͱ͔͢Δ

  21. +40/γϦΞϥΠζ  ʮ"DUJWF.PEFM4FSJBMJ[FSTʯΛར༻͍ͯͨ͠  ࿝ฮHFNͰ࢖͍΍͍͢  ύϑΥʔϚϯε໘ͰଞHFNͱൺֱ͞Ε͕ͪ  KCVJMEFSΑΓ͸଎͍ͷ͕ͩʜ

  22. ৐Γ׵͑ʂ

  23. ͦ΋ͦ΋ +40/γϦΞϥΠβ Կ࢖͑͹͍͍ʁ໰୊

  24. ௐࠪ

  25. ଟछଟ༷ͳબ୒ࢶ

  26. None
  27. +40/γϦΞϥΠβ ઓࠃ࣌୅

  28. ൺֱ

  29. ൺֱ  ൺֱର৅  KCVJMEFS  "DUJWF.PEFM4FSJBMJ[FST ".4  

    GBTU@KTPOBQJ  KC
  30. KCVJMEFS # app/views/messages/show.json.jbuilder json.content format_content(@message.content) json.(@message, :created_at, :updated_at) json.author do

    json.name @message.creator.name.familiar json.email_address @message.creator.email_address_with_name json.url url_for(@message.creator, format: :json) end json.comments @message.comments, :content, :created_at
  31. KCVJMEFS  (PPE  3BJMTσϑΥϧτ౥ࡌ ৽نϝϯόͷֶशίετ௿   ϝϯς͞Ε͍ͯΔ 3BJMTίΞνʔϜ

      ೚ҙͷεΩʔϚͰฦ٫Ͱ͖Δ  #BE  ௿଎ʜ  ಠಛͳه๏͕ͳ͡·ͳ͍ਓ΋ଟ͍  0UIFS  (*U)VCελʔ਺L
  32. ".4 class PostSerializer < ActiveModel::Serializer attributes :title, :body has_many :comments

    has_one :author end class CommentSerializer < ActiveModel::Serializer attributes :name, :body belongs_to :post end
  33. ".4  (PPE  4FSJBMJ[FSΫϥεͷ࣮૷ςετ͕Մೳ  ೚ҙͷεΩʔϚͰฦ٫Ͱ͖Δ  #BE 

    ϝϯςφϯε͞Ε͍ͯͳ͍  0UIFS  KCVJMEFSΑΓ͸଎͍͕ଞHFNͱൺֱ͢Δͱ஗͍  (JU)VCελʔ਺L
  34. GBTU@KTPOBQJ class MovieSerializer include FastJsonapi::ObjectSerializer attributes :name, :year has_many :actors

    belongs_to :owner, record_type: :user belongs_to :movie_type end json_string = MovieSerializer.new(movie).serialized_json
  35. GBTU@KTPOBQJ  (PPE  4FSJBMJ[FSΫϥεͷ࣮૷ςετ͕Մೳ  ߴ଎ʂ  #BE 

    ϝϯςφϯε͞Ε͍ͯͳ͍  ˞ຊՈ͔Β'PSL͞ΕͨϦϙδτϦͰϝϯς͞ΕͯΔ  0UIFS  εΩʔϚ͕+40/"1*ʹݶఆ͞ΕΔ  (JU)VCελʔ਺L
  36. GBTU@KTPOBQJ  +40/"1*  +40/ߏ଄ͷن໿  UZQF JEඞਢ  ΞιγΤʔγϣϯ͸


    SFMBUJPOTIJQT 
 JODMVEFE
 Ͱදݱ͢Δ { "data": [{ "type": "articles", "id": "1", "attributes": { "title": "JSON:API paints my bikeshed!" }, "relationships": { "author": { "data": { "type": "people", "id": "9" } }, }, }], "included": [{ "type": "people", "id": "9", "attributes": { "firstName": "Dan", "lastName": "Gebhardt", }, }] }
  37. KC # app/views/messages/show.json.jb json = { content: format_content(@message.content), created_at: @message.created_at,

    updated_at: @message.updated_at, author: { name: @message.creator.name.familiar, email_address: @message.creator.email_address_with_name, url: url_for(@message.creator, format: :json) } } json[:comments] = @message.comments.map do |comment| { content: comment.content, created_at: comment.created_at } end json
  38. KC  (PPE  KCVJMEFSΑΓૉ௚ʹ3VCZͬΆ͘ॻ͚Δ  ߴ଎ʂ  ೚ҙͷεΩʔϚͰฦ٫Ͱ͖Δ 

    ϝϯςφϯε͞Ε͍ͯΔ  #BE  ʮ4FSJBMJ[FSͷςετॻ͖͍ͨʂʯਓ͸߹Θͳ͍͔΋  3FRVFTU4QFD4ZTUFN4QFDͰॻ͘͜ͱʹͳΔ  0UIFS  (JU)VCελʔ਺
  39. KCVJMEFS ".4 GBTU@ KTPOBQJ KC ଎౓ º ˓ ˕ ˕

    εΩʔϚ ࣗ༝౓ ˓ ˓ ˚ ˓ ςετ ͠΍͢͞ ˚ ˓ ˓ ˚ HFN ϝϯς ˕ º ˚ ˓ ˞ݸਓͷײ૝Ͱ͢
  40. ɾТɾʆ  Ͳ͏͠Α͏

  41. ࠓճ͸଎౓͕໰୊ͳͷͰ ϕϯνϚʔΫ ΈΜͳ͍͖ͩ͢ CFODINBSLJQT

  42. CFODINBSLJQT def benchmark Benchmark.ips do |x| x.report('ams') do render_to_string json:

    ams_tenants, serializer: Ams::TenantSerializer end x.report('fast_jsonapi') do json = FastJsonapi::TenantSerializer.new(tenants).serialized_json render_to_string json: json end x.report('jb') do render_to_string 'index' end x.compare! end end
  43. CFODINBSLJQT  ".4ˠGBTU@KTPOBQJ΍KCʹ৐Γ׵͑Δ͚ͩͰʜ  ഒ଎ݟࠐΈʂ˞EFWFMPQNFOU؀ڥଌఆ  Αͦ͞͏ʂ Comparison: jb: 2.0

    i/s fast_jsonapi: 1.8 i/s - 1.10x (± 0.00) slower ams: 1.2 i/s - 1.64x (± 0.00) slower
  44. ৐Γ׵͑  Ұ෦"1*ͷʮKCʯ΁ͷ৐Γ׵͑Λબ୒  બఆཧ༝  ߴ଎  ೚ҙͷεΩʔϚͰฦ٫Ͱ͖Δ 

    +4ଆ΋࣮૷ࡁͷͨΊεΩʔϚมߋ͸΍Γͨ͘ͳ͍
  45. ຊ൪ϦϦʔε݁Ռ

  46. TҎ಺౸ୡʂ "status":200,"duration":449.96,"view":299.48,"db":97.36

  47. TҎ಺౸ୡʂ ෺݅"1*      վળલ վળͦͷ վળͦͷ

  48.  ΊͰͨ͠ 

  49. ·ͱΊ

  50. ֤HFNͷॴײ  KCVJMEFS  ඪ४౥ࡌ͕ڧΈ ֶशίετɺϝϯςφϯεܧଓੑ   ։ൃίετॏࢹ଎౓ʹ໰୊͕ແ͍৔߹ʹ͓͢͢Ί 

    ࠓޙ৽ͨͳ৐Γ׵͑ઌ͕ݟ͔ͭΔʜ͔΋ʁ  "DUJWF.PEFM4FSJBMJ[FST  ͳΜ͔ͩΜͩ࢖͍΍͍͢  ϝϯς͞Εͯͳ͍ͷ͕ਏ͍ʜ  ࠓ࢖͍͑ͯΔਓ͸ɺ
 ٸ͗৐Γ׵͑ͳͯ͘΋Αͦ͞͏
  51. ֤HFNͷॴײ  GBTU@KTPOBQJ  ଎౓ॏࢹͷ৔߹ʹ͓͢͢Ί  +40/"1*ͷ੍໿Λڐ༰Ͱ͖ΔͳΒ͹࢖͍΍͍͢  ˞ύονͰಈ࡞Λվม͢Δཪٕ΋ 

    KC  ଎౓ॏࢹͷ৔߹ʹ͓͢͢Ί  7JFXʹ௨ৗͷSVCZͬΆ͘ॻ͘ه๏͕߹͑͹࢖͍΍͍͢
  52. ·ͱΊ  ϘτϧωοΫ͸ͭͱ͸ݶΒͳ͍ͷͰࠜؾΑ͘վળ͠Α͏  ϓϩμΫτͷ໰୊ɺϏδωεͷঢ়گΛؑΈͯ
 ͦͷ࣌ʑʹ߹ٕͬͨज़બఆΛ͠Α͏  ͲͷΞϓϦʹ΋߹͏+40/γϦΞϥΠβͷܾఆ൛͸
 ೥ݱࡏܾΊΒΕͳͦ͞͏

  53. KCVJMEFS ".4 GBTU@ KTPOBQJ KC ଎౓ º ˓ ˕ ˕

    εΩʔϚ ࣗ༝౓ ˓ ˓ ˚ ˓ ςετ ͠΍͢͞ ˚ ˓ ˓ ˚ HFN ϝϯςφ ˕ º ˚ ˓