mirror of
https://github.com/logseq/logseq.git
synced 2026-05-19 18:32:41 +00:00
feat: add profiler(dev) rightside-tab (#11668)
* perf: add frontend.handler.profiler * perf: add frontend.components.profiler
This commit is contained in:
60
src/main/frontend/components/profiler.cljs
Normal file
60
src/main/frontend/components/profiler.cljs
Normal file
@@ -0,0 +1,60 @@
|
||||
(ns frontend.components.profiler
|
||||
"Profiler UI"
|
||||
(:require [fipp.edn :as fipp]
|
||||
[frontend.handler.profiler :as profiler-handler]
|
||||
[frontend.util :as util]
|
||||
[logseq.shui.ui :as shui]
|
||||
[rum.core :as rum]))
|
||||
|
||||
(rum/defcs profiler < rum/reactive
|
||||
(rum/local nil ::reports)
|
||||
(rum/local nil ::register-fn-name)
|
||||
[state]
|
||||
(let [profiling-fns (keys (rum/react profiler-handler/*fn-symbol->origin-fn))
|
||||
*reports (get state ::reports)
|
||||
*register-fn-name (get state ::register-fn-name)]
|
||||
[:div
|
||||
[:b "Profiling fns:"]
|
||||
[:div.pb-4
|
||||
(for [f-name profiling-fns]
|
||||
[:div.flex.flex-row.items-center.gap-2
|
||||
[:pre.select-text (str f-name)]
|
||||
[:a.inline.close.flex.transition-opacity.duration-300.ease-in
|
||||
{:title "Unregister"
|
||||
:on-pointer-down
|
||||
(fn [e]
|
||||
(util/stop e)
|
||||
(profiler-handler/unregister-fn! f-name))}
|
||||
(shui/tabler-icon "x")]])]
|
||||
[:div.flex.flex-row.items-center.gap-2
|
||||
(shui/button
|
||||
{:on-click (fn []
|
||||
(when-let [fn-sym (some-> @*register-fn-name symbol)]
|
||||
(profiler-handler/register-fn! fn-sym)))}
|
||||
"Register fn")
|
||||
[:input.form-input.my-2.py-1
|
||||
{:on-change (fn [e] (reset! *register-fn-name (util/evalue e)))
|
||||
:on-focus (fn [e] (let [v (.-value (.-target e))]
|
||||
(when (= v "input fn name here")
|
||||
(set! (.-value (.-target e)) ""))))
|
||||
:placeholder "input fn name here"}]]
|
||||
[:hr]
|
||||
[:div.flex.gap-2.flex-wrap.items-center.pb-3
|
||||
(shui/button
|
||||
{:size :sm
|
||||
:on-click (fn [_] (reset! *reports (profiler-handler/profile-report)))}
|
||||
(shui/tabler-icon "refresh") "Refresh reports")
|
||||
(shui/button
|
||||
{:size :sm
|
||||
:on-click (fn [_] (profiler-handler/reset-report!)
|
||||
(reset! *reports (profiler-handler/profile-report)))}
|
||||
(shui/tabler-icon "x") "Reset reports")]
|
||||
(let [update-time-sum
|
||||
(fn [m] (update-vals m (fn [m2] (update-vals m2 #(.toFixed % 6)))))]
|
||||
[:div.pb-4
|
||||
[:pre.select-text
|
||||
(when @*reports
|
||||
(-> @*reports
|
||||
(update :time-sum update-time-sum)
|
||||
(fipp/pprint {:width 20})
|
||||
with-out-str))]])]))
|
||||
@@ -22,7 +22,8 @@
|
||||
[frontend.db.rtc.debug-ui :as rtc-debug-ui]
|
||||
[frontend.handler.route :as route-handler]
|
||||
[logseq.db :as ldb]
|
||||
[frontend.components.icon :as icon]))
|
||||
[frontend.components.icon :as icon]
|
||||
[frontend.components.profiler :as profiler]))
|
||||
|
||||
(rum/defc toggle
|
||||
[]
|
||||
@@ -133,6 +134,10 @@
|
||||
[[:.flex.items-center (ui/icon "cloud" {:class "text-md mr-2"}) "(Dev) RTC"]
|
||||
(rtc-debug-ui/rtc-debug-ui)]
|
||||
|
||||
:profiler
|
||||
[[:.flex.items-center (ui/icon "cloud" {:class "text-md mr-2"}) "(Dev) Profiler"]
|
||||
(profiler/profiler)]
|
||||
|
||||
["" [:span]]))
|
||||
|
||||
(defonce *drag-to
|
||||
@@ -407,7 +412,12 @@
|
||||
[:div.text-sm
|
||||
[:button.button.cp__right-sidebar-settings-btn {:on-click (fn [_e]
|
||||
(state/sidebar-add-block! repo "rtc" :rtc))}
|
||||
"(Dev) RTC"]])]]
|
||||
"(Dev) RTC"]])
|
||||
(when (state/sub [:ui/developer-mode?])
|
||||
[:div.text-sm
|
||||
[:button.button.cp__right-sidebar-settings-btn {:on-click (fn [_e]
|
||||
(state/sidebar-add-block! repo "profiler" :profiler))}
|
||||
"(Dev) Profiler"]])]]
|
||||
|
||||
[:.sidebar-item-list.flex-1.scrollbar-spacing.px-2
|
||||
(if @*anim-finished?
|
||||
|
||||
62
src/main/frontend/handler/profiler.cljs
Normal file
62
src/main/frontend/handler/profiler.cljs
Normal file
@@ -0,0 +1,62 @@
|
||||
(ns frontend.handler.profiler
|
||||
"Provides fns for profiling.
|
||||
TODO: support both main thread and worker thread."
|
||||
(:require [goog.object :as g]))
|
||||
|
||||
(def ^:private *fn-symbol->key->call-count (volatile! {}))
|
||||
(def ^:private *fn-symbol->key->time-sum (volatile! {}))
|
||||
|
||||
(def *fn-symbol->origin-fn (atom {}))
|
||||
|
||||
(defn- get-profile-fn
|
||||
[fn-sym original-fn custom-key-fn]
|
||||
(fn profile-fn-inner [& args]
|
||||
(let [start (system-time)
|
||||
r (apply original-fn args)
|
||||
elapsed-time (- (system-time) start)
|
||||
k (when custom-key-fn (custom-key-fn r))]
|
||||
(vswap! *fn-symbol->key->call-count update-in [fn-sym :total] inc)
|
||||
(vswap! *fn-symbol->key->time-sum update-in [fn-sym :total] #(+ % elapsed-time))
|
||||
(when k
|
||||
(vswap! *fn-symbol->key->call-count update-in [fn-sym k] inc)
|
||||
(vswap! *fn-symbol->key->time-sum update-in [fn-sym k] #(+ % elapsed-time)))
|
||||
r)))
|
||||
|
||||
(defn register-fn!
|
||||
[fn-sym & {:keys [custom-key-fn] :as _opts}]
|
||||
(assert (qualified-symbol? fn-sym))
|
||||
(let [ns (namespace fn-sym)
|
||||
s (munge (name fn-sym))]
|
||||
(if-let [original-fn (find-ns-obj (str ns "." s))]
|
||||
(let [profiled-fn (get-profile-fn fn-sym original-fn custom-key-fn)]
|
||||
(swap! *fn-symbol->origin-fn assoc fn-sym original-fn)
|
||||
(g/set (find-ns-obj ns) s profiled-fn))
|
||||
(throw (ex-info (str "fn-sym not found: " fn-sym) {})))))
|
||||
|
||||
(defn unregister-fn!
|
||||
[fn-sym]
|
||||
(let [ns (namespace fn-sym)
|
||||
s (munge (name fn-sym))]
|
||||
(vswap! *fn-symbol->key->call-count dissoc fn-sym)
|
||||
(vswap! *fn-symbol->key->time-sum dissoc fn-sym)
|
||||
(when-let [origin-fn (get @*fn-symbol->origin-fn fn-sym)]
|
||||
(some-> (find-ns-obj ns) (g/set s origin-fn))
|
||||
(swap! *fn-symbol->origin-fn dissoc fn-sym))))
|
||||
|
||||
(defn reset-report!
|
||||
[]
|
||||
(vreset! *fn-symbol->key->call-count {})
|
||||
(vreset! *fn-symbol->key->time-sum {}))
|
||||
|
||||
(defn profile-report
|
||||
[]
|
||||
{:call-count @*fn-symbol->key->call-count
|
||||
:time-sum @*fn-symbol->key->time-sum})
|
||||
|
||||
(comment
|
||||
(register-fn! 'datascript.core/entity)
|
||||
(prn :profiling (keys @*fn-symbol->origin-fn))
|
||||
(prn :report)
|
||||
(pprint/pprint (profile-report))
|
||||
(reset-report!)
|
||||
(unregister-fn! 'datascript.core/entity))
|
||||
Reference in New Issue
Block a user