cljs-dev

ClojureScript compiler & std lib dev, https://clojurescript.org/community/dev
lilactown 2019-10-18T07:31:58.006900Z

Is there a way to measure how much memory a CLJS data structure takes up?

2019-10-18T08:10:05.007Z

In Chrome DevTools this can be measured by comparing two heap snapshots, where first doesn't have anything and second one includes a value of interest assigned to a global variable so it doesn't get GCed

2019-10-18T08:10:39.007200Z

Comparing two snapshots shows allocations diff

2019-10-18T08:11:22.007400Z

Also can be measured in node https://github.com/roman01la/js-memory-usage

borkdude 2019-10-18T09:29:14.008700Z

I have a toJS function exposed here to make working with CLJS values easier from JS. It also converts MetaFns to normal functions so they are easier to work with: https://github.com/borkdude/sci/blob/e895c4524a1a43568e4919315364978ea61df607/src/sci/impl/js.cljs#L36 Does it make sense to add that part to clj->js proper?

borkdude 2019-10-18T09:29:22.009100Z

Maybe the use case is too niche.

thheller 2019-10-18T09:31:17.009800Z

you can already do that via the protocols clj->js uses

thheller 2019-10-18T09:32:04.010600Z

(defprotocol IEncodeJS
  (-clj->js [x] "Recursively transforms clj values to JavaScript")
  (-key->js [x] "Transforms map keys to valid JavaScript keys. Arbitrary keys are
  encoded to their string representation via (pr-str x)"))

borkdude 2019-10-18T09:32:31.011300Z

@thheller I'm interested in the bundle size visualisation to see how much of several parts of sci occupy in the final bundle. I remember vaguely you had something for this in shadow-cljs. Any tutorial how to set this up just for the visualization? I have almost 0 experience with shadow.

borkdude 2019-10-18T09:32:43.011500Z

Thanks for the protocol pointer.

thheller 2019-10-18T09:33:23.012Z

do you build for the browser? the build reports currently only work for browser builds

borkdude 2019-10-18T09:33:46.012500Z

it's a library that can be used in both environments, so also for the browser

thheller 2019-10-18T09:34:39.013300Z

basically you just create a simple build config and run the build report normally

thheller 2019-10-18T09:35:11.013500Z

:builds {:sci {:target :browser :modules {:sci {:entries [sci.core]}}}}

borkdude 2019-10-18T09:36:19.014Z

thanks!

thheller 2019-10-18T09:41:22.014200Z

you may need to setup an actual example use though

thheller 2019-10-18T09:41:39.014400Z

if the library is written "correctly" all the code will be removed as dead code otherwise

thheller 2019-10-18T09:41:50.014600Z

since nothing is actually used if you just import the ns

borkdude 2019-10-18T09:45:44.014800Z

Right. Also a lot of the core functions are pulled in by the lib, but might already be used the the app otherwise, so it wouldn't be 100% on the lib

borkdude 2019-10-18T09:46:11.015Z

Just to get going for now, I'm getting: Can't find 'shadow.cljs.devtools.cli' as .class or .clj for lein run: please check the spelling. I've set :lein true in shadow-cljs.edn. Should I add a dep to project.clj?

thheller 2019-10-18T09:46:28.015200Z

yes. include the dep

thheller 2019-10-18T09:47:00.015500Z

the build report shows how much your code contributed

thheller 2019-10-18T09:47:11.015700Z

so cljs.core code is shown separately

borkdude 2019-10-18T09:47:15.015900Z

right

borkdude 2019-10-18T09:52:05.016100Z

thheller 2019-10-18T09:53:26.016600Z

thats likely the (def clojure-core ... etc which can never be removed

thheller 2019-10-18T09:54:03.016800Z

acceptable size though. so probably best to set up an actual example with the common uses

borkdude 2019-10-18T09:57:58.017Z

yeah, it was the point of def clojure-core to hold on to all those functions, because you don't know up front which ones the user is going to use in their program string. When I compile sci to an npm library (advanced compiled JS) I end up with ~350KB unzipped

Filipe Silva 2019-10-18T11:20:39.017400Z

there's some caveats to this approach though

Filipe Silva 2019-10-18T11:21:00.017600Z

depending on the data structure and the way it is operated upon, it can suffer either optimizations/deoptimizations

Filipe Silva 2019-10-18T11:21:43.017800Z

like this

Filipe Silva 2019-10-18T11:21:43.018Z

https://github.com/nodejs/node/issues/28205

2019-10-18T11:26:57.018300Z

You mean different runtimes right? That’s true. I imagine numbers can be different between browser JS VMs as well

Filipe Silva 2019-10-18T11:27:51.018600Z

is it meant for npm consumption by js clients?

Filipe Silva 2019-10-18T11:28:41.018800Z

in that case, using the same runtime but changing a for loop slightly reduced memory usage by 30 to 70%

Filipe Silva 2019-10-18T11:29:14.019Z

it didn't affect node 10 but did affect node 12

Filipe Silva 2019-10-18T11:29:18.019200Z

this was the change

Filipe Silva 2019-10-18T11:29:19.019400Z

https://github.com/angular/angular/pull/31638/files

Filipe Silva 2019-10-18T11:29:32.019600Z

for (let prop in obj) { -> for (let prop of Object.keys(obj)) {

2019-10-18T11:30:18.019800Z

hehe, reminded me about this talk https://www.youtube.com/watch?v=r-TLSBdHe1A

Filipe Silva 2019-10-18T11:31:10.020100Z

I haven't seen it, but this sounds like it's just up my alley πŸ˜„

2019-10-18T11:32:14.020300Z

there’s a funny moment he describes how having a shorter user name on his machine caused GCC to produce 100x faster code πŸ˜„

Filipe Silva 2019-10-18T11:34:02.020600Z

you know what, that doesn't surprise me at all

Filipe Silva 2019-10-18T11:34:19.020800Z

webpack had a similar problem around two years ago

borkdude 2019-10-18T11:34:58.021Z

@filipematossilva That's certainly one of the goals: https://www.npmjs.com/package/@borkdude/sci

Filipe Silva 2019-10-18T11:35:18.021300Z

https://github.com/webpack/webpack/issues/5992

Filipe Silva 2019-10-18T11:35:45.021700Z

it's similar insofar as names and paths would be concatenated indefinitely

Filipe Silva 2019-10-18T11:36:06.021900Z

so the longer your file paths were, the quicker you'd hit the memory limit

borkdude 2019-10-18T11:37:01.022100Z

You can see an example of it here: https://github.com/borkdude/sci-birch

Filipe Silva 2019-10-18T11:37:42.022600Z

350kb is a fair bit but for nodejs consumers it's not the worst thing in the world

Filipe Silva 2019-10-18T11:37:47.022800Z

especially if it's a single lib

Filipe Silva 2019-10-18T11:38:32.023Z

typescript, for instance, is 7mb in a single file

Filipe Silva 2019-10-18T11:39:11.023200Z

and TS ships several versions of the compiler, to cater for different consumers

borkdude 2019-10-18T11:41:00.023400Z

yeah. I guess TS is just a dev dependency though

Filipe Silva 2019-10-18T11:41:29.023600Z

not quite

Filipe Silva 2019-10-18T11:41:38.023800Z

in your case you want to interpret cljs

Filipe Silva 2019-10-18T11:41:49.024Z

but there are plenty of libs that want to interpret ts

Filipe Silva 2019-10-18T11:41:57.024200Z

like ts-node

borkdude 2019-10-18T11:42:06.024400Z

oh, then I'm fine I guess πŸ™‚

Filipe Silva 2019-10-18T11:42:11.024600Z

or that require TS to be compiled with, like Angular

borkdude 2019-10-18T11:42:19.024800Z

I was more worried about front-end bundle size

Filipe Silva 2019-10-18T11:42:20.025Z

TS is a total of 47mb on a clean install

borkdude 2019-10-18T11:42:37.025200Z

it's about 80kb zipped

borkdude 2019-10-18T11:42:50.025400Z

which is fine maybe, trade-off

dnolen 2019-10-18T13:14:20.026100Z

@alexmiller hey I built a Google Closure Library artifact today - could we get a release?

alexmiller 2019-10-18T13:15:02.027Z

Sure, do I just need to press the button on the build box?

dnolen 2019-10-18T13:18:19.027400Z

no you have to do those sonatype steps

dnolen 2019-10-18T13:18:30.027700Z

we talked about this last time - this could be automated

dnolen 2019-10-18T13:18:58.028300Z

the build has the instructions at the top

souenzzo 2019-10-18T13:19:44.028400Z

@borkdude you can generate source maps and inspect with any bundler inspector from npm

borkdude 2019-10-18T13:20:40.028600Z

thanks! @thheller already guided me to a solution with shadow-cljs which works quite nicely

πŸ‘ 1
alexmiller 2019-10-18T13:28:06.028900Z

that dimly rings a bell

alexmiller 2019-10-18T13:28:41.029200Z

so you did the build, I just need to do the sonatype part?

alexmiller 2019-10-18T13:30:43.029800Z

I see two staging repos, one for google-closure-library-third-party and one for google-closure-library. I assume these both need to be released?

alexmiller 2019-10-18T13:33:42.030100Z

released both, I assume will take a bit to show up

alexmiller 2019-10-18T13:48:33.030600Z

google-closure-library 0.0-20191016-6ae1f72f and org/clojure/google-closure-library-third-party 0.0-20191016-6ae1f72f are out there now

alexmiller 2019-10-18T13:51:47.031700Z

the third party jar is ~50% the size of the last release. not sure if that's weird

dnolen 2019-10-18T13:52:15.032Z

@alexmiller yeah both need to be released

dnolen 2019-10-18T13:52:36.032600Z

thanks!

thheller 2019-10-18T15:50:33.033100Z

oh nice, thanks for the new releases!

lilactown 2019-10-18T16:26:16.033200Z

This is awesome. Thank you both! What I need this for is to measure the relative size as a data structure grows, so I think Roman's suggestions should suffice.

πŸ‘ 1