軽量デバッグツールPostmortemの紹介.pdf

E170ae2eb0adcf3d136ab0990f0ea671?s=47 OHTA Shogo
September 26, 2019

 軽量デバッグツールPostmortemの紹介.pdf

E170ae2eb0adcf3d136ab0990f0ea671?s=128

OHTA Shogo

September 26, 2019
Tweet

Transcript

  1. ܰྔσόοάπʔϧ 1PTUNPSUFNͷ঺հ -JTQNFFUVQ !BUIPT

  2. طଘͷओͳσόοάख๏ ‣ QSJOUσόοά  QSO΍QSJOUMOΛૠೖ͠ɺͦͷ࣌఺ͷ஋Λ֬ೝͨ͠Γͦͷίʔυ͕࣮ߦ͞Εͨ ͜ͱΛ֬ೝ͢Δ  ૉ๿͕ͩखܰͳख๏ͰɺσόοΨ͕࢖͑ͳ͍৔߹ʹ༗ޮͳ͜ͱ΋ଟ͍ ‣ τϨʔεػೳ

     ؔ਺ݺͼग़͠ͷҾ਺΍໭Γ஋ɺݺͼग़͠ͷਂ͞౳Λग़ྗ͢Δ  UPPMTUSBDF΍$*%&3ͷτϨʔεػೳ౳ͱͯ͠ఏڙ͞ΕΔ ‣ σόοΨ  ϒϨʔΫϙΠϯτΛઃఆͯ͠ϓϩάϥϜͷ࣮ߦΛఀࢭ͠ɺεςοϓ࣮ߦ΍ ϩʔΧϧ؀ڥͷΠϯεϖΫτ౳͕Ͱ͖Δ  ৚͖݅ͭͷϒϨʔΫϙΠϯτΛઃఆͯ͠৚݅Λຬͨ͢৔߹͚࣮ͩߦΛࢭΊΔ
  3. طଘख๏͕ద༻ͮ͠Β͍έʔε ‣ ಉ͡ॲཧ͕ ϧʔϓ΍࠶ؼͰ Կ౓΋܁Γฦ࣮͠ߦ͞ΕΔ  QSJOUσόοά΍τϨʔεػೳͷग़ྗ͕ଟ͘ͳΓɺॏཁͳग़ྗͷಛఆ͕೉͘͠ͳΔ  ৚͖݅ͭϒϨʔΫϙΠϯτΛ͏·͘ઃఆ͠ͳ͍ͱԿ౓΋໰୊ͱ௚઀ؔ܎ͳ͍ճͷ܁Γ ฦ͠Ͱ࣮ߦ͕ࢭ·Δ

    ‣ ܁Γฦ͠ͷ݁Ռ͕ޙͷ܁Γฦ͠ʹӨڹΛ༩͑Δ  ໰୊͕ى͖ΔԿճ͔લͷ܁Γฦ͕͠໰୊ͷݪҼʹͳΓ͏Δ  ໰୊͕͋Δͱ෼͔Δ࣌఺Ͱ࣮ߦΛϒϨʔΫͯ͠΋ͦ͜ʹ໰୊ͷݪҼ͕ͳ͘ɺͦͷԿճ ͔લͷ܁Γฦ͠ͷঢ়ଶΛͲ͏ʹ͔ಛఆ͢Δඞཁ͕͋Δ ‣ ϚϧνεϨουͷॲཧ͕བྷΉͱ͞Βʹ໽հ ‣ ྫ  ࣌ؒܦաʹ͕͍ͨ͠ϦΞϧλΠϜʹঢ়ଶ͕มԽ͢Δ΋ͷ ήʔϜɺΞχϝʔγϣϯ   ݴޠॲཧܥ  ͱʹ͔͘ೖྗͷαΠζ͕େ͖͍ू໿ॲཧ FUD
  4. 1PTUNPSUFN ‣ খ͞ͳσόοάࢧԉπʔϧ ‣ ࣮ߦதͷ஋Λه࿥͠ɺࣄޙݕূ͢ΔͨΊͷ༻్Ͱ࢖͏ ‣ ϩάʹͲ͏͍͏஋ΛͲ͏ه࿥͢Δ͔Λτϥϯεσϡʔαʹ ΑͬͯॊೈʹΧελϚΠζͰ͖Δ ‣ ݸผͷηογϣϯΛ࡞Δ͜ͱʹΑΓɺଞͷϩά͔Β෼཭

    ͞ΕͨϩάΛͱΔ͜ͱ͕Ͱ͖Δ
  5. 1PTUNPSUFNͷجຊతͳ࢖͍ํ  ‣ pm/saveݺͼग़͠ຖͷϩʔΧϧ؀ڥΛϚοϓͱͯ͠ه࿥͢Δ ‣ pm/log-forࢦఆͨ͠ΩʔͰه࿥͞ΕͨϩάΛฦ͢ (require '[postmortem.core :as pm])

    (defn sum [n] (loop [n n sum 0] (pm/save :sum) (if (= n 0) sum (recur (dec n) (+ sum n))))) (sum 5) ;=> 15 (pm/log-for :sum) ;=> [{:n 5 :sum 0} {:n 4 :sum 5} {:n 3 :sum 9} {:n 2 :sum 12} {:n 1 :sum 14} {:n 0 :sum 15}]
  6. 1PTUNPSUFNͷجຊతͳ࢖͍ํ  ‣ pm/spy>>ݺͼग़͠ຖʹҾ਺ʹ౉ͨ͠஋Λه࿥͢Δ ‣ pm/logsه࿥͞Εͨ͢΂ͯͷϩάΛฦ͢ (require '[postmortem.core :as pm])

    (defn sum [n] (loop [n n sum 0] (if (= n 0) sum (recur (dec n) (pm/spy>> :sum-val (+ sum n))))) (sum 5) ;=> 15 (pm/log-for :sum-val) ;=> [5 9 12 14 15] (pm/logs) ;=> {:sum [{:n 5 :sum 0} {:n 4 :sum 5} …] :sum-val [5 9 12 14 15]}
  7. 1PTUNPSUFNͷجຊతͳ࢖͍ํ  ‣ pm/log-for ΍pm/logs ͰऔΓग़ͨ͠ϩάͷ݁Ռ͸ pm/reset! ౳ͰϦηοτ͢Δ·Ͱ্ॻ͖͞Εͳ͍ (require '[postmortem.core

    :as pm]) (sum 100) ;=> 5050 (pm/log-for :sum-val) ;=> [5 9 12 14 15] (pm/logs) ;=> {:sum [{:n 5 :sum 0} {:n 4 :sum 5} …] :sum-val [5 9 12 14 15]} (pm/reset!) (pm/logs) ;=> {} (sum 3) ;=> 6 (pm/logs) ;=> {:sum [{:n 3 :sum 0} {:n 2 :sum 1} …] :sum-val [3 5 6]}
  8. τϥϯεσϡʔαͱͷ࿈ܞ  ‣ pm/save ΍pm/spy>> ͸τϥϯεσϡʔαΛΦϓγϣφϧ Ҿ਺ͱͯ͠औΕɺϩάΛͲ͏ه࿥͢Δ͔ΛΧελϚΠζͰ͖Δ (require '[postmortem.core :as

    pm]) (defn sum [n] (loop [n n sum 0] (pm/save :sum (filter #(even? (:n %)))) (if (= n 0) sum (recur (dec n) (+ sum n))))) (sum 5) ;=> 15 (pm/log-for :sum) ;=> [{:n 4 :sum 5} {:n 2 :sum 12} {:n 0 :sum 15}]
  9. τϥϯεσϡʔαͱͷ࿈ܞ  ‣ map-indexed Ͱ࿈൪ΛৼͬͨΓɺrandom-sample Ͱ ϥϯμϜαϯϓϦϯάΛͨ͠Γ΋Ͱ͖Δ (require '[postmortem.core :as

    pm]) (defn sum [n] (loop [n n sum 0] (pm/save :sum (comp (map-indexed #(assoc %2 :id %1)) (random-sample 0.5)) (if (= n 0) sum (recur (dec n) (+ sum n))))) (sum 5) ;=> 15 (pm/log-for :sum) ;=> [{:n 5 :sum 0 :id 0} {:n 4 :sum 5 :id 1} {:n 1 :sum 14 :id 4}]
  10. τϥϯεσϡʔαͱͷ࿈ܞ  ‣ System/nanoTimeͰݺͼग़࣌͠ࠁΛ͚͓͍ͭͯͯɺxf/ debounceͰҰఆִؒͷ࣌ؒ಺ͷϩάΛؒҾ͘͜ͱ΋Ͱ͖Δ (require '[postmortem.core :as pm] '[postmortem.xforms

    :as xf]) (defn sum [n] (loop [n n sum 0] (pm/save :sum (comp (map #(assoc % :t (System/nanoTime))) (xf/debounce :t 10000)) (if (= n 0) sum (recur (dec n) (+ sum n))))) (sum 10) ;=> 55 (pm/log-for :sum) ;=> [{:n 10 :sum 0 :t 105365222743711} {:n 9 :sum 10 :t 105365222775129} {:n 7 :sum 27 :t 105365222789449} {:n 4 :sum 45 :t 105365222802184} {:n 1 :sum 54 :t 105365222813741}]
  11. τϥϯεσϡʔαͱͷ࿈ܞ  ‣ take-whileͰ৚݅Λຬͨؒ͢ͷϩά͚ͩΛ࢒ͨ͠Γɺ xf/take-lastͰ࠷ޙͷ/ݸͷϩά͚ͩΛ࢒ͨ͠Γ΋Ͱ͖Δ (require '[postmortem.core :as pm] '[postmortem.xforms

    :as xf]) (defn sum [n] (loop [n n sum 0] (pm/save :sum (comp (take-while #(< (:sum %) 1000)) (xf/take-last 3)) (if (= n 0) sum (recur (dec n) (+ sum n))))) (sum 100) ;=> 5050 (pm/log-for :sum) ;=> [{:n 92 :sum 772} {:n 91 :sum 864} {:n 90 :sum 955}]
  12. xf/take-lastͷ࣮૷ ‣ τϥϯεσϡʔα͸ͭͷॲཧ͔ΒͳΔ  ॳظԽॲཧεςοϓॲཧ׬ྃॲཧ ‣ xf/take-last ͸εςοϓॲཧͰೖྗΛϦϯάόοϑΝʹ٧Ίͯɺ ׬ྃॲཧͰόοϑΝʹ࢒͍ͬͯΔཁૉΛʮ࠷ޙͷ/ݸʯͱͯ֬͠ఆ͢Δ (defn

    take-last [^long n] (fn [rf] (let [idx (volatile! 0), vals (object-array n)] (fn ([] (rf)) ([result] (let [offset (if (>= @idx n) (long @idx) 0)] (transduce (map #(aget vals (rem (+ % offset) n))) rf result (range n)))) ([acc input] (aset vals (rem @idx n) input) (vswap! idx inc) acc))))) ॳظԽॲཧ ׬ྃॲཧ εςοϓॲཧ
  13. τϥϯεσϡʔαͷ׬ྃॲཧ͸͍ͭݺ͹ΕΔͷ͔ʁ (defn add [x y] (pm/save :add (comp (map (fn

    [x] (prn [:pre x]) x)) (xf/take-last 3) (map (fn [x] (prn [:post x]) x)))) (+ x y)) (redue add 0 (range 5)) ;; [:pre {:x 0, :y 0}] ;; [:pre {:x 0, :y 1}] ;; [:pre {:x 1, :y 2}] ;; [:pre {:x 3, :y 3}] ;; [:pre {:x 6, :y 4}] ;=> 10 (pm/logs) ;; [:post {:x 1, :y 2}] ;; [:post {:x 3, :y 3}] ;; [:post {:x 6, :y 4}] ;=> {:add [{:x 1, :y 2} {:x 3, :y 3} {:x 6, :y 4}]} (pm/logs) ;=> {:add [{:x 1, :y 2} {:x 3, :y 3} {:x 6, :y 4}]}
  14. τϥϯεσϡʔαͷ׬ྃॲཧ͸͍ͭݺ͹ΕΔͷ͔ʁ ‣ ϩάΛࢀরͱͨ͠௚લʹճ͚ͩ׬ྃॲཧ͕࣮ߦ͞ΕΔΑ ͏ʹͳ͍ͬͯΔ ‣ Ұ୴׬ྃॲཧΛͨ͠ϩάΛ͞Βʹߋ৽Ͱ͖ͯ͠·͏ͱΑ ͘෼͔Βͳ͍ڍಈʹͳΓ͏ΔͷͰɺpm/logs౳ͰϩάΛ ࢀরͨ͠Βpm/reset!౳ͰϦηοτ͢Δ·Ͱߋ৽Ͱ͖ ͳ͍࢓༷ʹͳ͍ͬͯΔ

  15. ηογϣϯʹΑΔϩάͷ෼཭ ‣ ηογϣϯ͸Ұ࿈ͷϩάͷอଘઌ ‣ ৽͍͠ηογϣϯΛ࡞Δ͜ͱͰଞͷϩάͱͷ෼཭͕Ͱ͖Δ (require '[postmortem.core :as pm]) (def

    sess1 (pm/make-session)) (def sess2 (pm/make-session)) (let [f0 (fn [n] (pm/save :f)) f1 (fn [n] (pm/save sess1 :f identity)) f2 (fn [n] (pm/save sess2 :f identity))] (f0 1) (f1 10) (f2 100) (f0 2) (f1 20) (f2 200)) (pm/logs) ;=> {:f [{:n 1} {:n 2}]} ;; ↑͸ (pm/logs (pm/current-session)) ͱಉ͡ (pm/logs sess1) ;=> {:f [{:n 10} {:n 20}]} (pm/logs sess2) ;=> {:f [{:n 100} {:n 200}]}
  16. ݱࡏͷηογϣϯ ‣ pm/set-current-session!ݱࡏͷηογϣϯΛมߋ ‣ pm/with-sessionϚΫϩຊମ಺ͷΈݱࡏͷηογϣϯΛมߋ (require '[postmortem.core :as pm]) (defn

    add [x y] (pm/save :add) (+ x y)) (def sess1 (pm/make-session)) (pm/set-current-session! sess1) (add 1 2) ;=> 3 (def sess2 (pm/make-session)) (pm/with-session sess2 (add 3 4)) ;=> 7 (pm/log-for sess1 :add) ;=> [{:x 1 :y 2}] (pm/log-for sess2 :add) ;=> [{:x 3 :y 4}]
  17. ηογϣϯͱτϥϯεσϡʔα ‣ ηογϣϯʹτϥϯεσϡʔαΛ࣋ͨͤΔ͜ͱ͕Ͱ͖ɺͦͷ ηογϣϯΛ࢖͏͢΂ͯͷpm/save౳ʹͦΕ͕ద༻͞ΕΔ (require '[postmortem.core :as pm]) (defn add

    [x y] (pm/save :add) (+ x y)) (def sess (pm/make-session (map (fn [x] (prn 'Logging x) x)))) (pm/set-current-session! sess) (add 1 2) ;; Logging {:x 1 :y 2} ;=> 3 (add 3 4) ;; Logging {:x 3 :y 4} ;=> 7
  18. ಉظతηογϣϯ ‣ pm/make-sessionͰ࡞ΒΕΔηογϣϯ͸εϨουηʔϑͰͳ͍ ‣ pm/make-synchronized-sessionͰ࡞ΒΕΔηογϣϯ΁ͷมߋ͸ಉظ͞ΕΔ (require '[postmortem.core :as pm]) (defn

    f [x] (pm/save :f (comp (map-indexed #(assoc %2 :i %1)) (xf/take-last)))) (defn test [] (run! deref [(future (dotimes [i 10000] (f i))) (future (dotimes [i 10000] (f i)))])) (test) (pm/log-for :f) ;=> [{:n 9999, :i 19982}] (pm/set-current-session! (pm/make-synchronized-session)) (test) (pm/log-for :f) ;=> [{:n 9999, :i 19999}]
  19. ·ͱΊ ‣ ैདྷͷσόοάख๏Ͱσόοάͮ͠Β͍έʔεʹରԠͨ͠ 1PTUNPSUFNͱ͍͏σόοάπʔϧΛ։ൃͨ͠ ‣ τϥϯεσϡʔαͱͷ࿈ܞʹΑΓɺϩάʹͲ͏͍͏஋ΛͲ ͏ه࿥͢Δ͔ΛॊೈʹΧελϚΠζͰ͖ΔΑ͏ʹͳͬͨ ‣ ηογϣϯͷ֓೦Λಋೖͨ͜͠ͱͰɺϚϧνεϨουͰͷ σόοάͰ΋࢖͑ΔΑ͏ʹͳͬͨ

  20. IUUQTHJUIVCDPNBUIPTQPTUNPSUFN