Also what I was referencing in terms of the CAS was deferring submission until the namespace is fully initialised. Something akin to a SQL transaction where it could use mutable state and then transform it to the immutable map at commit (eg end of the file). Until a ns fully parsed and processed (by a single thread) there wouldn’t be any need for the intermediate data structure to be thread-safe. Kind of like Guava data structures but for Namespaces. On Fri, 26 Jan 2018 at 16:57, Nathan Fisher <nfis...@junctionbox.ca> wrote:
> Hi Alex, > > That’s cool! > > I was looking to explore alternatives optimisations to what you had > already outlined and which I could potentially do with little effort. I > started writing something to do parallel loads back in Sept/Oct. and was > replicating some of what Buck/Blaze/Basel do in terms of a DAG. I wanted > “pristine” Clojure VMs for each node in the dependency graph but startup > time was an issue and I couldn’t see an easy way to bring it down. > > For point one I was noticing some amount of non-trivial latency in Var > interning and RT map. Agree Java CAS performance won’t be the issue but (I > think) there’s something in Clojure that I’m working to improve my > understanding. For the map I noticed once I eliminated class loading via > prefetching the map initialisation in RT was a non-trivial amount of time > (double digit ms). Not something that I think needs prioritisation by any > means but just a “huh wonder why that is?”. > > Justin in terms of Java it’s not a matter of JIT or anything like that. > It’ll be relatively efficient out of the box, it’s a handful of cpu > instructions to execute and is around 20 CPU cycles per try (eg > nanoseconds). It should succeed on or about the first time within the > context of Clojure startup. An atomic load side depends on how far up the > memory chain it has to go but shouldn’t be “too expensive” either, more > expensive than a local variable for sure but not enough to worry about in > most cases. > > Cheers, > Nathan > On Fri, 26 Jan 2018 at 15:38, Justin Smith <noisesm...@gmail.com> wrote: > >> a nitpick on point 1 - I would assume you can't expect hotspot to improve >> anything in the timescale of a program startup >> >> am I missing something here? >> >> On Fri, Jan 26, 2018 at 10:32 AM Alex Miller <a...@puredanger.com> wrote: >> >>> With a few custom patches (which are pending in jira) + AOT + direct >>> linking + lazy vars + var meta elision + jvm flags, I have gotten raw >>> startup as low as ~450 ms. Past that, radical changes are probably required >>> which are unlikely to be worth doing. >>> >>> On your conclusions: >>> >>> 1. minimize CAS'es - I'm doubtful this would make much difference. >>> Hotspot is usually pretty good at optimizing that stuff in single-threaded >>> uncontended scenarios. I will wave in the general direction of immutable >>> namespaces to a place that I think is an opportunity to improve a range of >>> issues like this. >>> >>> 2. Lazy vars effectively do this (in tandem with AOT and direct linking) >>> and it can help 20-30% (presuming you have compiled stuff to use). However, >>> most startup cases don't have AOT compiled code to work with and thus this >>> won't help at all. >>> >>> 3. Prefetching - as you found, I would not expect this to be useful >>> enough to be worth the pain and fragility involved. >>> >>> 4. jaotc - I think this *is* likely to be useful for cases where you can >>> pre-stage stuff like this, in particular core itself is a perfect >>> opportunity. People have already tested this ( >>> https://mjg123.github.io/2017/10/04/AppCDS-and-Clojure.html) and found >>> it useful. But again, requires pre-AOT'ed code. >>> >>> I don't think most of these changes help at all though in the most >>> common case where you are spinning up a project with a lot of non-AOT'ed >>> code - the 10s of seconds of read/compile/init times dwarf this stuff. Rich >>> and I working on an idea to help with this. >>> >>> On Thursday, January 25, 2018 at 11:47:32 PM UTC-6, Nathan Fisher wrote: >>>> >>>> It's not a huge contributor but Class loading isn't free and Clojure >>>> could optimise it in a couple of places. I think with a couple of months >>>> effort in optimisation you might be able to get it down to 500ms for a >>>> simple "hello world". I'm doubtful you can get it much lower than that. TBH >>>> I'm not sure if the engineering effort would necessarily be worth it for >>>> many users. >>>> >>>> I wanted to test dynamic loading and docker before I shared the article >>>> more broadly but here's the results from implementing prefetching in >>>> Clojure; >>>> >>>> https://junctionbox.ca/2018/01/04/clojure-class-prefetching.html >>>> <https://www.google.com/url?q=https%3A%2F%2Fjunctionbox.ca%2F2018%2F01%2F04%2Fclojure-class-prefetching.html&sa=D&sntz=1&usg=AFQjCNGztHxa9E7A5PbzIdoK_5PK_bqzVw> >>>> >>>> It's a part of a series that I'm slowly plodding through as I have >>>> time. I hope to cover off the 4 items from the conclusion of this article; >>>> >>>> >>>> https://junctionbox.ca/2017/12/26/clojure-startup-walkthrough.html#conclusions >>>> <https://www.google.com/url?q=https%3A%2F%2Fjunctionbox.ca%2F2017%2F12%2F26%2Fclojure-startup-walkthrough.html%23conclusions&sa=D&sntz=1&usg=AFQjCNFDrtWr7uhBX8IZYnv576PWYVM_TA> >>>> >>>> Cheerio! >>>> Nathan >>>> >>>> >>>> On 26 January 2018 at 01:51, Timothy Baldridge <tbaldri...@gmail.com> >>>> wrote: >>>> >>>>> I would suggest everyone here read this document: >>>>> https://dev.clojure.org/display/design/Improving+Clojure+Start+Time >>>>> It goes into a lot of detail on prior work in this area, and I'd say the >>>>> benchmarks on it should be quite informative. >>>>> >>>>> But let me also go into a bit more detail into how CLJS differs from >>>>> CLJ in how it accesses global function definitions: >>>>> >>>>> In CLJs, clojure core contains a lot of definitions that look >>>>> something like this: >>>>> >>>>> clojure.core.conj = function () {... clojure.core.some_fn(...) . ....} >>>>> >>>>> The cost of creating that global function is then the cost of 2 >>>>> lookups (clojure in the global namespace, core in clojure), the creating >>>>> of >>>>> a JS function object, and the assigning of that function to the core >>>>> object. The internal call to some_fn doesn't matter at load-time because >>>>> of >>>>> Javascript's late binding. >>>>> >>>>> In the JVM this happens: >>>>> >>>>> 1) A class is loaded that implements the IFn or AFn interfaces >>>>> 2) The methods on this class must be loaded and the bytcode parsed, >>>>> and validated >>>>> 3) The static constructor on this method is run >>>>> 4) Inside the static constructor there are calls to find Vars. In the >>>>> case of the above function this would be a lookup to clojure.core.some_fn. >>>>> This is done for every var referenced by this function >>>>> 5) Any non-native constants must be new'd up. This includes hashmaps, >>>>> vectors, lists, keywords (which must be interned), symbols, etc. >>>>> 5) The clojure.core.conj var is created >>>>> 6) The contents of the var are set to the function that was loaded >>>>> (and new'd). Synchronization doesn't matter here as there are no other >>>>> threads that can see this Var. >>>>> 7) The metadata for the function is created. Most of the time this >>>>> includes creating a hashmap with at least 2-3 values. >>>>> 8) The metadata for the var is set. >>>>> >>>>> The systems in play here are completely different. So I re-state what >>>>> I said before: it's apples-to-oranges. >>>>> >>>>> But I'd love to see more benchmarks in this thread, so far we only >>>>> have opinions. >>>>> >>>>> >>>>> On Thu, Jan 25, 2018 at 9:37 PM, Timothy Baldridge < >>>>> tbaldri...@gmail.com> wrote: >>>>> >>>>>> >> If Var reification is part of the slowness of Clojure startup >>>>>> over Java's >>>>>> >>>>>> It's really not. If you completely removed vars from Clojure on the >>>>>> JVM, Clojure wouldn't be faster by any measurable amount. If someone has >>>>>> benchmarks that say that Vars themselves are the cause of Clojure JVM's >>>>>> slower startup, then I'd love to see those benchmarks, because there's >>>>>> most >>>>>> likely a serious flaw in the measurements. >>>>>> >>>>>> On Thu, Jan 25, 2018 at 9:34 PM, Didier <didi...@gmail.com> wrote: >>>>>> >>>>>>> Really, any comparisons between JS and JVM startup times are not >>>>>>>> useful at all. >>>>>>> >>>>>>> >>>>>>> I'd say its useful to me, if anything because I've learned quite a >>>>>>> few things already from this comparison, and I hope to learn more. >>>>>>> >>>>>>> If Var reification is part of the slowness of Clojure startup over >>>>>>> Java's, and ClojureScript managed without it, yet it delivered 90% of >>>>>>> the >>>>>>> practical benefits of Var reification, I could see a potential here >>>>>>> maybe. >>>>>>> Something similar to a dynamic or AOT. Flagging some Vars which need >>>>>>> not be >>>>>>> reified, or compiling to non reified Vars if fast startup time is what >>>>>>> the >>>>>>> user would rather have. I could see this being desirable for use cases >>>>>>> like >>>>>>> AWS Lambda, or small scripts, if it had a drastic startup improvement. >>>>>>> >>>>>>> The concurrency issue is interesting, and would definitely be unique >>>>>>> to Clojure over ClojureScript. First time I hear about this being a >>>>>>> possible bottleneck for startup time. Are the concurrency checks >>>>>>> java's? Or >>>>>>> are these higher level Clojure concurrency checks? Is there possible >>>>>>> improvement from the Clojure side of them to make them faster? >>>>>>> >>>>>>> @tbc++ seems to imply the apples to oranges are due to the >>>>>>> platforms, and I can accept this to be true, except that I've seen >>>>>>> suggestions that the slow startups are due to either Clojure's >>>>>>> implementation causing startup bottlenecks, or Clojure's core design >>>>>>> preventing any kind of fast startup implementation. Meaning the culprit >>>>>>> is >>>>>>> Clojure and not the JVM. But as I find myself thinking about >>>>>>> ClojureScript, >>>>>>> I wonder if this is true. If Clojure's core design is the bottleneck, >>>>>>> then >>>>>>> why doesn't ClojureScript suffer too? And so, maybe its because it has >>>>>>> altered some core design choices, like concurrency and Var reification. >>>>>>> Is >>>>>>> it just that? Or is there also bottleneck in the current Clojure >>>>>>> implementation on the JVM, which were implemented more efficiently on >>>>>>> ClojureScript? I know Alex Miller is working on some of those, and every >>>>>>> version of Clojure optimizes, but I've also heard nothing here is >>>>>>> expected >>>>>>> to create a game changer improvement (appart from possibly grouping >>>>>>> functions under one class). And if its neither the implementation, or >>>>>>> the >>>>>>> core design choices, then I have to conclude that it is in fact the >>>>>>> JVM's >>>>>>> fault, in that its core design is making what Clojure does on startup >>>>>>> more >>>>>>> expensive then say the V8 design. Which one of those three things (or >>>>>>> possible combination is it) is what I'm trying to seek answer for here. >>>>>>> >>>>>>> Thanks everyone, >>>>>>> Didier >>>>>>> >>>>>>> On Thursday, 25 January 2018 12:53:03 UTC-8, tbc++ wrote: >>>>>>>> >>>>>>>> Really, any comparisons between JS and JVM startup times are not >>>>>>>> useful at all. For a long list of reasons, not limited to: >>>>>>>> >>>>>>>> * CLJS doesn't have Vars, CLJ does >>>>>>>> * JS VMs are highly tuned for excellent startup times >>>>>>>> * JVM Bytecode is a binary format expressing classes, JS files are >>>>>>>> text files expressing functions and data transformations >>>>>>>> * JVM is class based, JS is prototype based >>>>>>>> * JVM is multithreaded and designed to handle several GB of data, >>>>>>>> JS VMs are single threaded and designed to often deal with less than a >>>>>>>> GB >>>>>>>> of data. >>>>>>>> * HotSpot (and most) JVMs are method JITS, JS engines often use >>>>>>>> many profiling methods that are closer to that of a tracing JIT >>>>>>>> * The JVM performs extensive security analysis on loaded bytecode, >>>>>>>> JS engines disallow most security flaws via syntax restrictions >>>>>>>> * CLJS supports tree shaking and minifcation. >>>>>>>> >>>>>>>> All this adds up to an apples-to-oranges comparison. They are >>>>>>>> completely different platforms, the numbers between the two won't be >>>>>>>> close, >>>>>>>> and drawing any sort of comparison between the two isn't very useful at >>>>>>>> all. >>>>>>>> >>>>>>>> -- >>>>>>>> >>>>>>>> * No multithreaded safety in vars is not what takes up most of the >>>>>>>> startup time in Clojure. We're talking about single threaded access >>>>>>>> (var >>>>>>>> initing isn't multithreaded) to a primitive that is updated via a CAS. >>>>>>>> The >>>>>>>> highest cost you'll see accessing a var in this situation is somewhere >>>>>>>> in >>>>>>>> the range of a cache miss or two. >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> On Thu, Jan 25, 2018 at 1:26 PM, Stephen Nelson <ste...@montoux.com >>>>>>>> > wrote: >>>>>>>> >>>>>>>>> The JVM is concurrent whereas Javascript VMs are singled-threaded. >>>>>>>>> Var initialisation in Clojure uses concurrency primitives to ensure >>>>>>>>> that >>>>>>>>> namespaces are always consistent for all threads, whereas >>>>>>>>> Clojurescript >>>>>>>>> simply assigns to variables. Our profiling of Clojure on the JVM >>>>>>>>> indicates >>>>>>>>> that a lot of the time spent in namespace initialisation is spent in >>>>>>>>> concurrency structures, and this seems much more significant for >>>>>>>>> non-clojure-core namespaces. >>>>>>>>> >>>>>>>>> On Fri, Jan 26, 2018 at 7:22 AM Mikhail Gusarov < >>>>>>>>> dott...@dottedmag.net> wrote: >>>>>>>>> >>>>>>>>>> cljs vars are not reified. >>>>>>>>>> >>>>>>>>>> On Thu, 25 Jan 2018, at 18:24, Didier wrote: >>>>>>>>>> > Based on the profiling performed here >>>>>>>>>> > http://clojure-goes-fast.com/blog/clojures-slow-start/ on 1.9, >>>>>>>>>> > >>>>>>>>>> > It looks like clojure/core__init.load is the slowest bit with >>>>>>>>>> load and >>>>>>>>>> > requiring spending the most time on, as well as loadClass, >>>>>>>>>> followed by >>>>>>>>>> > clojure/lang/Var.invoke. >>>>>>>>>> > >>>>>>>>>> > Wouldn't ClojureScript also need to initialize all Vars and >>>>>>>>>> execute top >>>>>>>>>> > level forms? You'd think that part would be slower in >>>>>>>>>> JavaScript no? >>>>>>>>>> > >>>>>>>>>> > -- >>>>>>>>>> > You received this message because you are subscribed to the >>>>>>>>>> Google >>>>>>>>>> > Groups "Clojure" group. >>>>>>>>>> > To post to this group, send email to clo...@googlegroups.com >>>>>>>>>> > Note that posts from new members are moderated - please be >>>>>>>>>> patient with >>>>>>>>>> > your first post. >>>>>>>>>> > To unsubscribe from this group, send email to >>>>>>>>>> > clojure+u...@googlegroups.com >>>>>>>>>> > For more options, visit this group at >>>>>>>>>> > http://groups.google.com/group/clojure?hl=en >>>>>>>>>> > --- >>>>>>>>>> > You received this message because you are subscribed to the >>>>>>>>>> Google >>>>>>>>>> > Groups "Clojure" group. >>>>>>>>>> > To unsubscribe from this group and stop receiving emails from >>>>>>>>>> it, send >>>>>>>>>> > an email to clojure+u...@googlegroups.com. >>>>>>>>>> > For more options, visit https://groups.google.com/d/optout. >>>>>>>>>> >>>>>>>>>> -- >>>>>>>>>> You received this message because you are subscribed to the Google >>>>>>>>>> Groups "Clojure" group. >>>>>>>>>> To post to this group, send email to clo...@googlegroups.com >>>>>>>>>> Note that posts from new members are moderated - please be >>>>>>>>>> patient with your first post. >>>>>>>>>> To unsubscribe from this group, send email to >>>>>>>>>> clojure+u...@googlegroups.com >>>>>>>>>> For more options, visit this group at >>>>>>>>>> http://groups.google.com/group/clojure?hl=en >>>>>>>>>> --- >>>>>>>>>> You received this message because you are subscribed to the >>>>>>>>>> Google Groups "Clojure" group. >>>>>>>>>> To unsubscribe from this group and stop receiving emails from it, >>>>>>>>>> send an email to clojure+u...@googlegroups.com. >>>>>>>>>> For more options, visit https://groups.google.com/d/optout. >>>>>>>>>> >>>>>>>>> >>>>>>>>> >>>>>>>>> -- >>>>>>>>> Stephen Nelson | Platform Lead Developer | Montoux >>>>>>>>> e. ste...@montoux.com >>>>>>>>> t. @montoux >>>>>>>>> w. montoux.com >>>>>>>>> >>>>>>>>> -- >>>>>>>>> You received this message because you are subscribed to the Google >>>>>>>>> Groups "Clojure" group. >>>>>>>>> To post to this group, send email to clo...@googlegroups.com >>>>>>>>> Note that posts from new members are moderated - please be patient >>>>>>>>> with your first post. >>>>>>>>> To unsubscribe from this group, send email to >>>>>>>>> clojure+u...@googlegroups.com >>>>>>>>> For more options, visit this group at >>>>>>>>> http://groups.google.com/group/clojure?hl=en >>>>>>>>> --- >>>>>>>>> You received this message because you are subscribed to the Google >>>>>>>>> Groups "Clojure" group. >>>>>>>>> To unsubscribe from this group and stop receiving emails from it, >>>>>>>>> send an email to clojure+u...@googlegroups.com. >>>>>>>>> For more options, visit https://groups.google.com/d/optout. >>>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> -- >>>>>>>> “One of the main causes of the fall of the Roman Empire was >>>>>>>> that–lacking zero–they had no way to indicate successful termination of >>>>>>>> their C programs.” >>>>>>>> (Robert Firth) >>>>>>>> >>>>>>> -- >>>>>>> You received this message because you are subscribed to the Google >>>>>>> Groups "Clojure" group. >>>>>>> To post to this group, send email to clojure@googlegroups.com >>>>>>> Note that posts from new members are moderated - please be patient >>>>>>> with your first post. >>>>>>> To unsubscribe from this group, send email to >>>>>>> clojure+unsubscr...@googlegroups.com >>>>>>> For more options, visit this group at >>>>>>> http://groups.google.com/group/clojure?hl=en >>>>>>> --- >>>>>>> You received this message because you are subscribed to the Google >>>>>>> Groups "Clojure" group. >>>>>>> To unsubscribe from this group and stop receiving emails from it, >>>>>>> send an email to clojure+unsubscr...@googlegroups.com. >>>>>>> For more options, visit https://groups.google.com/d/optout. >>>>>>> >>>>>> >>>>>> >>>>>> >>>>>> -- >>>>>> “One of the main causes of the fall of the Roman Empire was >>>>>> that–lacking zero–they had no way to indicate successful termination of >>>>>> their C programs.” >>>>>> (Robert Firth) >>>>>> >>>>> >>>>> >>>>> >>>>> -- >>>>> “One of the main causes of the fall of the Roman Empire was >>>>> that–lacking zero–they had no way to indicate successful termination of >>>>> their C programs.” >>>>> (Robert Firth) >>>>> >>>>> -- >>>>> You received this message because you are subscribed to the Google >>>>> Groups "Clojure" group. >>>>> To post to this group, send email to clojure@googlegroups.com >>>>> Note that posts from new members are moderated - please be patient >>>>> with your first post. >>>>> To unsubscribe from this group, send email to >>>>> clojure+unsubscr...@googlegroups.com >>>>> For more options, visit this group at >>>>> http://groups.google.com/group/clojure?hl=en >>>>> --- >>>>> You received this message because you are subscribed to the Google >>>>> Groups "Clojure" group. >>>>> To unsubscribe from this group and stop receiving emails from it, send >>>>> an email to clojure+unsubscr...@googlegroups.com. >>>>> For more options, visit https://groups.google.com/d/optout. >>>>> >>>> >>>> >>>> >>>> -- >>>> Nathan Fisher >>>> w: http://junctionbox.ca/ >>>> >>> -- >>> You received this message because you are subscribed to the Google >>> Groups "Clojure" group. >>> To post to this group, send email to clojure@googlegroups.com >>> Note that posts from new members are moderated - please be patient with >>> your first post. >>> To unsubscribe from this group, send email to >>> clojure+unsubscr...@googlegroups.com >>> For more options, visit this group at >>> http://groups.google.com/group/clojure?hl=en >>> --- >>> You received this message because you are subscribed to the Google >>> Groups "Clojure" group. >>> To unsubscribe from this group and stop receiving emails from it, send >>> an email to clojure+unsubscr...@googlegroups.com. >>> For more options, visit https://groups.google.com/d/optout. >>> >> -- >> You received this message because you are subscribed to the Google >> Groups "Clojure" group. >> To post to this group, send email to clojure@googlegroups.com >> Note that posts from new members are moderated - please be patient with >> your first post. >> To unsubscribe from this group, send email to >> clojure+unsubscr...@googlegroups.com >> For more options, visit this group at >> http://groups.google.com/group/clojure?hl=en >> --- >> You received this message because you are subscribed to the Google Groups >> "Clojure" group. >> To unsubscribe from this group and stop receiving emails from it, send an >> email to clojure+unsubscr...@googlegroups.com. >> For more options, visit https://groups.google.com/d/optout. >> > -- > - sent from my mobile > -- - sent from my mobile -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.