How are you going to recompile at all, when the compiler doesn't store the
source code of functions after it compiles them? This is why this proposal
needs to have a working prototype, to prove that these ideas actually work,
until then proposals don't do much at all.  Personally I don't see how the
ideas in this proposal would work from the repl, and the repl is where most
people do their work.
On Sep 14, 2013 10:55 PM, "Mikera" <mike.r.anderson...@gmail.com> wrote:

> On Saturday, 14 September 2013 01:04:16 UTC+8, tbc++ wrote:
>
>> >> This would be better, IMHO, than forever accepting semantics that
>> prevent idiomatic code from ever being truly fast.
>>
>> You're going to have a hard time convincing people to give up some of
>> the dynamism of Clojure just for the sake of more performance. Especially
>> considering that many Clojure users are perfectly okay with boxed values,
>> let alone need floats or other primitives.
>>
>
> Let's be clear - I'm not asking anyone to give up on any dynamism. I am
> asking for an agreement that we want to allow high performance *options* in
> Clojure, so that we can at least match Scala/Java, for those use cases
> where people have genuine performance requirements. Some people don't care
> about performance enough for the distinction between float and double to
> matter. But others do.
>
> I think we (as a community) should try to support both use cases. Clojure
> has the potential to be *both* dynamic and fast if we design it right.
>
> It would be a shame if people in the community took a general stance that
> "performance is good enough for me, so we aren't interested in supporting
> further performance improvements". I'm sure that isn't what is intended,
> but it could appear like that to people who raise performance issues only
> to get challenged / told that they don't have a valid problem.
>
>
>>
>> But what you are describing creates a whole ton of new problems, problems
>> I don't see a good solution for. What you are describing would require the
>> recompilation of entire source trees when a inner function is modified. So
>> now we're in the Scala/Java land of recompile after every edit. Perhaps
>> there's a use-case for invoke dynamic here, but now you're talking about
>> breaking backwards compatibility for everyone not using Java 7+.
>>
>
> I'm not suggesting "recompile everything after edit". I'm suggesting
> "lazily recompile stuff that is dependent on the one thing you changed".
> That's a much smaller compilation unit in most cases - maybe you are
> recompiling 2-5 functions instead of 1. If you change something that is
> used everywhere in your whole app, then yes: maybe it's going to recompile
> 100 or so functions. But even then, I doubt it will be a significant
> compile time compared to Java/Scala land.
>
> And note that we're talking about incurring this cost only for people
> doing dynamic changes to existing vars. This isn't common production usage
> (if you are mutating production state, I would hope you are using something
> with proper concurrency semantics like atoms or agents or refs to mutate
> data!). So performance probably shouldn't matter at all, apart from the
> subjective experience of compiling fast enough to be usable at the REPL.
> Which I'm pretty sure is a fairly easy target to hit.
>
> Like I said, this would be a big change, but it would be a good way to
> combine dynamism with excellent runtime performance.
>
>
>>
>> I'll be the first to admit that I'd like to rewrite the Clojure compiler
>> as a true multi-pass optimizing compiler. But that's a task I haven't
>> undertaken for two reasons 1) it's a ton of work that would take months (if
>> not years) to reach the level of performance currently offered by Clojure.
>> 2) I really don't need it. Every time I need that level of performance I
>> drop to Java, CUDA or some other high performance toolkit.
>>
>> Personally I think it would be much better for someone to come up with a
>> typed lisp that interops very cleanly with Clojure. That way you can build
>> your inner kernels using a lisp-like language, and then glue it together
>> with Clojure.
>>
>> But let me close by saying, if you really want better primitives, I'd
>> suggest writing up a proposal for how it would work, perhaps even with some
>> example using macros and genclass. Until then we don't have anything to go
>> off of, people say "I'd love to have feature X", well we all would, but all
>> the suggestions thus far won't work, so how do you plan on fixing that?
>>
>
> My pragmatic proposal for now is very simple: allow metadata to specify
> functions to be compiled in a way that invocation is compiled statically to
> an invokevirtual. You lose the dynamic var deref, but gain better runtime
> performance and the ability to use arbitrary types / primitives (which
> solves the OP's problem).
>
> This limited-scope proposal won't effect any existing dynamic usage, so
> people who like their fully mutable vars with their dynamic lookups can
> keep them.
>
> It is on JIRA as CLJ-1263 , comments / improvements welcome.
>
> http://dev.clojure.org/jira/browse/CLJ-1263
>
>
>> Timothy
>>
>>
>> On Fri, Sep 13, 2013 at 1:54 AM, Mikera <mike.r.an...@gmail.com> wrote:
>>
>>> On Friday, 13 September 2013 12:11:50 UTC+8, tbc++ wrote:
>>>
>>>> >> If we can do away with the interface generation, then support for
>>>> arbitrary primitive arguments should become relatively straightforward.
>>>>
>>>> How would we even call a function without an interface? Remember
>>>> everything is defined behind vars, so you simply can't assume that a
>>>> function won't be re-defed without notice. This is the reason interfaces
>>>> exist notice how the following works:
>>>>
>>>> user=> (defn foo ^long [^long x] x)
>>>> #'user/foo
>>>> user=> (defn baz [x] (foo x))
>>>> #'user/baz
>>>> user=> (baz 42)
>>>> 42
>>>> user=> (defn foo ^double [^double x] x)
>>>> #'user/foo
>>>> user=> (baz 42)
>>>>
>>>> ClassCastException user$foo cannot be cast to clojure.lang.IFn$LL
>>>>  user/baz (NO_SOURCE_FILE:1)
>>>> user=>
>>>>
>>>
>>> Good example to discuss!
>>>
>>> I agree there is a subtle tradeoff between performance and dynamism here.
>>>
>>> Any interface dispatch via a var uses an extra level of indirection (in
>>> the dynamic var case, this includes a thread-local check for any bindings)
>>> and already adds some overhead. If you are happy using Clojure's dynamic
>>> features to pass arbitrary (boxed / Object) arguments and redefine vars on
>>> the fly like that, you probably don't really care about optimal performance
>>> very much anyway and a standard IFn invoke should be OK.
>>>
>>> For performance-sensitive code, you ideally want primitive-typed code to
>>> be compiled to a direct method call (invokevirtual) and not go via any var
>>> lookup / interface invoke at all. This would mean you would also need to
>>> redefine/recompile baz if you wanted to use a changed version of foo, but
>>> that's a relatively minor inconvenience IMHO. If you redefine baz after
>>> redefining foo (e.g. by reloading the whole namespace), then everything
>>> will still work. I'm not sure if it is possible to get this precise
>>> behaviour in Clojure at present - but it would certainly be great for high
>>> performance code.
>>>
>>> If we want *both* maximum performance and dynamic flexibility, then I
>>> think we need a completely different approach. Clojure vars as currently
>>> designed won't cut it. Probably something like an on-demand re-compilation
>>> strategy based on a var dependency graph would be needed. I personally
>>> think that's the right long-term direction, but that's definitely Clojure
>>> 2.0 territory.
>>>
>>>
>>>>
>>>> Do a prototype with definterface/genclass or something and then report
>>>> your results. My suspicions are that you'll find doing this without
>>>> interfaces, while maintaining Clojure's semantics, is impossible.
>>>>
>>>
>>> You may be right. Though it also probably depends on what you consider
>>> documented (promised not to change in public API) vs. undocumented
>>> (implementation detail) semantics. Some of the subtleties on what happens
>>> to existing code when you redefine vars are arguably in the latter
>>> category. Observe:
>>>
>>> (defn foo ^double [^double x] (inc x))
>>> (defn baz [x] (foo x))
>>> (baz 42)
>>> => 43.0
>>> (ns-unmap *ns* 'foo)
>>> (defn foo ^double [^double x] (dec x))
>>> (baz 42)
>>> => 43.0
>>>
>>> i.e. it's fairly easy to trick Clojure into keeping an old version of a
>>> var around. Does that count as officially documented behaviour we are
>>> obliged to maintain?
>>>
>>> Either way, if Clojure's semantics prove to be a fundamental issue for
>>> performance, then I think it is better to start work to improve Clojure's
>>> semantics (perhaps targeting 2.0 if we think it's a really big breaking
>>> change). This would be better, IMHO, than forever accepting semantics that
>>> prevent idiomatic code from ever being truly fast. I'd rather see a bit of
>>> breakage and fix my code when upgrading to Clojure 2.0 than be stuck with
>>> poor performance forever.
>>>
>>>
>>>
>>>>
>>>> Timothy
>>>>
>>>>
>>>> On Thu, Sep 12, 2013 at 8:41 PM, Mikera <mike.r.an...@gmail.com> wrote:
>>>>
>>>>> People *have* run into this problem a lot. People have just worked
>>>>> around it. The existence of great libraries like HipHip and vectorz-clj 
>>>>> and
>>>>> some of Zach's stuff is IMHO to a large extent because people have needed
>>>>> high performance operations (often involving primitives / primitive arrays
>>>>> / custom JVM types) and have found it easier to implement these in a new
>>>>> library than wait for the support to appear in Clojure itself.
>>>>>
>>>>> So we have lots of great, performance-oriented libraries. Cool.
>>>>>
>>>>> But not having comprehensive JVM primitive support is still a big
>>>>> problem for Clojure. It means that:
>>>>> a) We'll get lots of ecosystem fragmentation as people with slightly
>>>>> different requirements implement their own solutions in slightly
>>>>> different/incompatible ways. We're seeing this already. Lisp Curse 
>>>>> etc.....
>>>>> b) People with very strong performance requirements on the JVM (e.g.
>>>>> OpenGL, big data numerics, scientific computing, heavy duty websites) are
>>>>> more likely to avoid Clojure and do their work in Scala / Java instead. 
>>>>> The
>>>>> community will lose exactly the people who have both the motivation and
>>>>> skills to fix these kind of issues.
>>>>> c) We won't get the wider reputation for performance that I think
>>>>> Clojure deserves and should aspire to. And this is important - rightly or
>>>>> wrongly, many people are attracted to languages with good performance
>>>>> credentials.
>>>>>
>>>>> I'd really love to be able to write everything in pure idiomatic
>>>>> Clojure and still guarantee great performance. Currently I can't, and in a
>>>>> large part this is due to JVM type-related issues like the following:
>>>>> 1) Not all primitive types are fully supported as function args and
>>>>> return values (the issue raised in this thread)
>>>>> 2) Lack of an efficient way to extend abstract base types (CLJ-1255 in
>>>>> Jira, for those interested)
>>>>> 3) Lack of support for statically compiled reference types as function
>>>>> args (avoiding unnecessary instance checks and casting, CLJ-1256)
>>>>> 4) The compiler still isn't very clever about using type inference to
>>>>> eliminate boxing / typecasts (perhaps CinC can help here?)
>>>>>
>>>>> Personally I'm less interested in floats (when I'm doing numerical
>>>>> stuff, double precision is usually more important), but I've certainly
>>>>> wanted ints many many times. I'm sure other people have wanted chars or
>>>>> bytes for various reasons (text processing? IO?). The point is that there
>>>>> are many valid reasons to use the primitive types on the JVM. I guess
>>>>> somebody even has a use for "short" somewhere...... ;-)
>>>>>
>>>>> Now let's get practical.
>>>>>
>>>>> What we need, I think, is some kind of "official" recognition that
>>>>> full JVM primitive support (i.e. all primitives supported in all
>>>>> situations) is an objective for Clojure in 1.6 or maybe 1.7. Then people
>>>>> can put in the time / effort to implement it. I'm personally very happy to
>>>>> help implement this myself providing that there is agreement that full
>>>>> primitive support is the way we want to go. Without official blessing, I'm
>>>>> unlikely to spend my weekends on speculative work that might not be
>>>>> accepted or appreciated. I suspect this is true for others too.
>>>>>
>>>>> If, on the other hand, the "official" answer is "Clojure will never
>>>>> support anything other than Objects, doubles and longs" then I'd want to
>>>>> know that too. I think that would be a *really* poor design decision
>>>>> because good compiled performance and good JVM interop ("embracing the 
>>>>> host
>>>>> platform") seem to be two key principles of Clojure that have attracted
>>>>> many people. But hey, then I could at least save my weekends and focus on
>>>>> writing performance-oriented code in other languages (whether that is 
>>>>> Java,
>>>>> Scala, pure bytecode, or some crazy new performance-oriented JVM Lisp).
>>>>>
>>>>>
>>>>> On Thursday, 12 September 2013 23:11:40 UTC+8, tbc++ wrote:
>>>>>
>>>>>> There are a combination of issues all contributing to the lack of
>>>>>> response on this subject. But before I continue let me state that these
>>>>>> opinions are my own. I have worked on Clojure and core.async, but these
>>>>>> comments are going to be personal conjecture and opinions:
>>>>>>
>>>>>> 1) As mentioned there is a high amount of complexity required to
>>>>>> implement all the interfaces needed for the different variants of 
>>>>>> functions
>>>>>> you want. Primitive hinted functions currently implement Java interfaces,
>>>>>> implementing every combination of float, double, object, short, int, 
>>>>>> long,
>>>>>> and byte for arities up to 5 would require the addition of over 16,000
>>>>>> interfaces. With the current config, we only need 81 interfaces. I'm not
>>>>>> saying this couldn't be changed to happen on-the-fly, it would just take
>>>>>> some serious work, and would cause problems with Java Interop
>>>>>>
>>>>>> 2) The current system works, there are production databases (see
>>>>>> Datomic), neural networks (see the work by Prismatic), and many high
>>>>>> performance libraries (Zach Tellman has a reputation for bending Clojure 
>>>>>> to
>>>>>> his will in this area), all written in Clojure.
>>>>>>
>>>>>> 3) Because of #2, some may even go so far as to say that we should
>>>>>> drop everything but longs and doubles. Other dynamic languages (Python 
>>>>>> for
>>>>>> instance) do this without problems, they simply relegate all the high
>>>>>> performance stuff to highly optimized libraries. This is what Prismatic 
>>>>>> did
>>>>>> with HipHop (http://blog.getprismatic.com/******
>>>>>> blog/2013/7/10/introducing-**hip****hip-array-fast-and-**flexible-**
>>>>>> nu**merical-**computation-in-**clojure<http://blog.getprismatic.com/blog/2013/7/10/introducing-hiphip-array-fast-and-flexible-numerical-computation-in-clojure>
>>>>>> **).
>>>>>>
>>>>>> 4) Writing small functional libraries in Java that interop with
>>>>>> Clojure is actually quite nice. So perhaps the answer is to build the 
>>>>>> inner
>>>>>> kernels of your system in Java and then wrap them? I know that doesn't
>>>>>> sound fun, but you won't get much faster code than that.
>>>>>>
>>>>>> So all the above make me sit back and say "what is it about your
>>>>>> problem that is unique and really requires floats? Why haven't we had
>>>>>> problems like this in the past."
>>>>>>
>>>>>> 5) And I think the problem really comes down to your API and target
>>>>>> platform (GPU). See, most of us would just typehint to doubles and take 
>>>>>> the
>>>>>> memory hit. Doubles are fast on modern CPUs and memory is cheap. Not so 
>>>>>> in
>>>>>> your case, as you mentioned you have concerns about memory size and
>>>>>> performance of certain primitives.
>>>>>>
>>>>>> My conclusion is that you'd probably be best looking at the HipHop
>>>>>> library, and figuring out how you can adapt their ideas to your own code.
>>>>>> That is, write a small Java library that contains all the kernel code you
>>>>>> need, and then stitch together these primitives with Clojure.
>>>>>>
>>>>>> As it stands, Clojure's support for type hinting floats is poor, but
>>>>>> that's not likely to change soon.
>>>>>>
>>>>>> ----
>>>>>>
>>>>>> TL;DR - The reason you haven't heard back is because no one has a
>>>>>> good answer as to how to fix it, or if it even needs to be fixed. That's
>>>>>> not the answer anyone likes to hear, but I'm afraid that's the truth.
>>>>>> Anyone else on this list can feel free to correct me.
>>>>>>
>>>>>> Timothy Baldridge
>>>>>>
>>>>>>
>>>>>> On Thu, Sep 12, 2013 at 8:38 AM, Alex Fowler <alex.m...@gmail.com>wrote:
>>>>>>
>>>>>>>
>>>>>>> Does somebody from the development team read this user group? Or
>>>>>>> maybe I have addressed my questions to a wrong place?
>>>>>>>
>>>>>>> --
>>>>>>> --
>>>>>>> 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<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/**grou****
>>>>>>> ps/opt_out <https://groups.google.com/groups/opt_out>.
>>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>> --
>>>>>> “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 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<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/**grou**ps/opt_out<https://groups.google.com/groups/opt_out>
>>>>> .
>>>>>
>>>>
>>>>
>>>>
>>>> --
>>>> “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 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<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/**groups/opt_out<https://groups.google.com/groups/opt_out>
>>> .
>>>
>>
>>
>>
>> --
>> “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/groups/opt_out.
>

-- 
-- 
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/groups/opt_out.

Reply via email to