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

-- 
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.

Reply via email to