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.