This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-03-31
Channels
- # announcements (20)
- # asami (14)
- # aws (6)
- # babashka (15)
- # beginners (83)
- # biff (6)
- # calva (93)
- # cider (3)
- # clj-kondo (21)
- # cljdoc (106)
- # cljs-dev (32)
- # clojure (165)
- # clojure-dev (78)
- # clojure-europe (54)
- # clojure-italy (9)
- # clojure-nl (9)
- # clojure-norway (24)
- # clojure-uk (4)
- # clojurescript (6)
- # community-development (2)
- # conjure (2)
- # core-typed (14)
- # datahike (4)
- # datomic (2)
- # emacs (40)
- # events (1)
- # fulcro (11)
- # graalvm-mobile (29)
- # graphql (8)
- # honeysql (19)
- # java (1)
- # jobs (1)
- # lsp (232)
- # malli (5)
- # membrane (112)
- # nextjournal (11)
- # off-topic (63)
- # portal (12)
- # re-frame (6)
- # reagent (3)
- # reitit (4)
- # rewrite-clj (2)
- # shadow-cljs (25)
- # tools-deps (6)
Skia isn't required. If Skia isn't available, it should use java swing to display everything.
If you do want to use the skialib backend, you just need the skialib dependency that matches your OS and architecture. One of:
• com.phronemophobic.membrane/skialib-linux-x86-64 {:mvn/version "0.9.31.0-beta"}
• com.phronemophobic.membrane/skialib-macosx-aarch64 {:mvn/version "0.9.31.0-beta"}
• com.phronemophobic.membrane/skialib-macosx-x86-64 {:mvn/version "0.9.31.0-beta"}
You can also just add all 3 with no issue.
the skia toolkit? or any toolkit?
can you load (require 'membrane.skia)
at the repl?
ok, I think I found the issue
(defonce toolkit
#?(:clj
(if-let [tk (resolve 'membrane.skia/toolkit)]
@tk
@(requiring-resolve 'membrane.java2d/toolkit))
:cljs
nil))
pretty sure the resolve for skia should be requiring-resolve
instead of resolve
😞maybe I did that on purpose
so that it only uses skia if that namespace has already been loaded
right but that would almost always use skia
because I think the skia namespace loads even if skialib isn't available
I think I did this as a hack because I didn't expect anyone else besides me to use the skia version
and I like to default to skia
generally, loading a namespace isn't a big deal, but some UI libraries (cough AWT, GLFW) expect to be the only UI library to be running
hmmm, the issue is that I cheated and made monospaced
, cell-width
and cell-height
top level defs. The right way to do it is to pass those values as arguments.
I can fix this, but I think my brain might be a little too tired to fix it tonight. I should be able to fix it tomorrow.
if you're running the code base locally, you can work around it by changing the toolkit definition in viscous.cljc to:
(require 'membrane.skia)
(defonce toolkit membrane.skia/toolkit)
or just requiring membrane.skia
anywhere before the toolkit in viscous.cljc gets initialized
@UK0810AQ2 fyi, just updated viscous on github. As long as you require membrane.skia
before opening the inspector, it should use membrane.skia
now.
@U7RJTCH6J I'm happy to report this works and now I have a new fun one for you: try inspecting some pathological data structure like a tools.analyzer output then resize the window, program becomes functionally unresponsive
@UK0810AQ2 Interesting. Just tried some tools.analyzer output and didn't notice anything weird. Is there a repro I can follow?
Big hairy data structures like tools.analyzer output are the kinds of data that viscous was made for so if that use case isn't working well, I'd like to fix it!
The only datastructures I would consider truly pathological are infinitely empty sequences like (filter (constantly false) (range))
since there's no way to inspect it without calling first
which loops forever.
when you say resize, is that resizing the window or the viscous view?
Is it slow for both skia and java2d or just skia backend?
And do you recall if it was slow when shrinking and growing?
or possibly just growing?
and just to double check, do you know if the data structures you were inspecting were fully realized?
Were any other operations laggy or just grow/shrink? • hovering over child data structures • navigating • popping • etc
that would be great
@U7RJTCH6J here you go
@UK0810AQ2 thanks for the extra info! 🙏
Yep, that's no bueno.
I'm pretty surprised that it's showing path->spec
as eating so many cycles. I'm sure path->spec
could be more efficient, but that same code runs fine on my machine and in the browser, https://phronmophobic.github.io/viscous/.
How are you starting the inspector? Are you specifying your own version of specter? Is anything being printed to stdout?
I think I remember you saying you were running on linux? I'll see if I can reproduce that locally. I'm pretty puzzled by the symptoms so far. My initial guess is that some part of the event handling is running several times more often than it should be.
I ran this
(require 'membrane.skia)
(defonce toolkit membrane.skia/toolkit)
Then the example from READMELet me double check running the example from the README. That's not how I usually run it.
anyway, I find the paths get recompiled constantly and it hits a dynamic var thing in specter which incurs a clojure.core/walk
which takes forever and a half and generates more garbage than all social media combined
impressive
Right, so the question is why this is slow for you, but runs well enough in clj and cljs locally
I'm not assuming that you're doing anything weird. I'm assuming membrane is doing something weird on linux
like calling on-mouse-move
several times for each event for some reason
or having on-mouse-move
trigger a redraw which triggers an on-mouse-move
or something
If I do this first, then load an example, it's laggy
(require 'membrane.skia)
(defonce toolkit membrane.skia/toolkit)
it should say if you print com.phronemophobic.viscous/toolkit
ok, I have an idea. one sec
ok, nevermind. I'm confused again
I'd love to see the clojure -Stree
for the project
just to make sure that we're using the same versions of things
org.clojure/clojure 1.10.3
. org.clojure/spec.alpha 0.2.194
. org.clojure/core.specs.alpha 0.2.56
com.phronemophobic.membrane/skialib-linux-x86-64 0.9.31.0-beta
com.phronemophobic/membrane 0.9.31.8-beta
. cnuernber/dtype-next 8.041
. org.ow2.asm/asm 9.0
. insn/insn 0.5.2
. org.ow2.asm/asm 9.0
. camel-snake-kebab/camel-snake-kebab 0.4.2
. it.unimi.dsi/fastutil 8.2.1
. org.xerial.larray/larray-mmap 0.4.1
. org.xerial.larray/larray-buffer 0.4.1
. org.apache.commons/commons-math3 3.6.1
. org.roaringbitmap/RoaringBitmap 0.9.0
. org.roaringbitmap/shims 0.9.0
. com.github.wendykierp/JTransforms 3.1
X org.apache.commons/commons-math3 3.5 :older-version
. pl.edu.icm/JLargeArrays 1.5
X org.apache.commons/commons-math3 3.5 :older-version
. techascent/tech.resource 5.04
. org.clojure/tools.logging 1.1.0
. com.google.guava/guava 30.1.1-jre
. com.google.guava/failureaccess 1.0.1
. com.google.guava/listenablefuture 9999.0-empty-to-avoid-conflict-with-guava
. com.google.code.findbugs/jsr305 3.0.2
. org.checkerframework/checker-qual 3.8.0
. com.google.errorprone/error_prone_annotations 2.5.1
. com.google.j2objc/j2objc-annotations 1.3
. org.apache.commons/commons-text 1.9
. org.apache.commons/commons-lang3 3.11
. net.n01se/clojure-jna 1.0.0
X net.java.dev.jna/jna 4.0.0 :older-version
. net.java.dev.jna/jna 5.10.0
. com.rpl/specter 1.1.3
. riddley/riddley 0.1.12
. org.clojure/core.async 1.4.627
. org.clojure/tools.analyzer.jvm 1.2.0
. org.clojure/tools.analyzer 1.1.0
. org.clojure/core.memoize 1.0.236
. org.clojure/core.cache 1.0.207
. org.clojure/data.priority-map 1.0.0
X org.ow2.asm/asm 5.2 :older-version
. org.clojure/tools.reader 1.3.2
Now you'll tell me I'm using a bad version of skia linuxnope, that's the latest one
I guess it might still be bad, but if it is, there's not a better one yet
com.google.guava/listenablefuture 9999.0-empty-to-avoid-conflict-with-guava
😆So one of the things that is different is that locally, I use the monospaced Menlo font, but it should fall back to the system's monospaced if that's not available
however, the way to load the default monospaced font differs between java2d and skia. there's a way to do that correctly, but viscous currently does it the wrong way
and it actually use the new font?
the spacing might be wrong since the sizes are hard-coded when the namespaces is loaded
fonts are annoying
ok, so there's some other difference between java2d and skia that is slowing things down a lot
There's a reason I stay away from UI/UX. You stumble in dark, bang little toe against couch. You had an experience. You're welcome
so if I could test this locally, I would just run something like:
(require '[membrane.ui :as ui])
(require '[membrane.skia :as backend]
;'[membrane.java2d :as backend]
)
(def pos (atom nil))
(defn test-mouse-move []
(ui/on
:mouse-move
(fn [pos']
(println pos)
(reset! pos pos')
nil)
[(ui/with-style ::ui/style-stroke
(ui/rectangle 400 400))
(ui/label @pos)]))
(backend/run #'test-mouse-move)
and see if it's doing anything weird
see if 1) that minimal app is slow and 2) if it's printing out the same position multiple times.
ok, so this isn't calling path->spec
anywhere so the problem is elsewhere
I also added
(def ticker (java.util.concurrent.atomic.AtomicLong. 0))
(defn tick!
^long [^java.util.concurrent.atomic.AtomicLong n]
(let [m (.get n)
l (System/currentTimeMillis)]
(.set n l)
(- l m)))
right now, it only redraws when there's an event. there's other ways to setup, but I think that's what it should be doing now
40 fps isn't impressive, but it shouldn't be unusable
It's getting a bit late so I'm tapping out for today, I'll profile it tomorrow in more detail and let you know if I found something weird
ok, thanks again!
fyi, I tried to reproduce locally, but it seemed to run fine. fwiw, I'm running linux inside of virtualbox so it might not be the best environment to reproduce.
Not sure how interested you are in falling down this rabbit hole with me, so obviously, feel free to ignore. To recap, the main symptom we have is sluggish UI and key difference we have is seems to work except on some linuxs with skia. I know sluggishness is generally debugged with profiling, but there's almost no platform specific code inside of membrane. Most of the platform specific code is inside of the skia graphics library and the glfw windowing library. At this point, I'm assuming that the skia and glfw libraries are correct and that the problem is that I've written some non-portable code that uses those libraries incorrectly. I think it's much more likely that the problem is with the glfw integration rather than the skia integration. If the bug is an integration issue, profiling may or may not be that helpful. > I get pretty constant 25ms refresh rate This is pretty weird since I think the events happen on the same thread as the repaint (membrane doesn't particularly care, but I know mac OS does and I think it's the same on linux). So if events were triggering every 25ms, you would expect the screen to update regularly as well.
Another theory is that the screen isn't being redrawn for some reason. This snippet should print on every redraw:
(require '[membrane.ui :as ui])
(require '[membrane.skia :as backend]
;'[membrane.java2d :as backend]
)
(def pos (atom nil))
(defn on-draw [f]
(ui/no-events
(reify
ui/IOrigin
(-origin [elem]
[0 0])
ui/IBounds
(-bounds [elem]
[0 0])
backend/IDraw
(draw [this]
(f)))))
(defn test-mouse-move []
(ui/on
:mouse-move
(fn [pos']
#_(println pos')
(reset! pos pos')
nil)
[(ui/with-style ::ui/style-stroke
(ui/rectangle 400 400))
(on-draw #(println "draw!"))
(ui/label @pos)]))
(backend/run #'test-mouse-move)