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.