Alex: I'd bet heavily on the "slower" ones being measurement noise (they only differ by a few percent) - I typically see that much variation between runs. I probably shouldn't have reported them as "slower" - 1-5% is (in my experience) typically just noise, so don't think it's worth digging into.
On Thursday, 2 April 2015 21:39:54 UTC+9, Alex Miller wrote: > > Great to hear feedback like this! I'd be particularly interested if you > had any suspicions about the characteristics of the ones that are slower. > > > > On Apr 2, 2015, at 3:22 AM, tcrayford <tcra...@gmail.com <javascript:>> > wrote: > > Yeller (yellerapp.com) (which I maintain) has a comprehensive benchmark > suite > (using criterium, with a heck of a lot of work put into getting real and > good > results). I've run Yeller's benchmark suite against clojure 1.7 alpha6 - > it's > pretty comprehensive, and covers a wide range of things. Results are below. > > Mostly some things got very minorly slower (but not enough to make a real > impact for the application), but quite a few benchmarks saw **dramatic** > speedups. > > Given these promising results, I ran Yeller's `test.check` suite for 8 > hours in > CI, and didn't see any failures, so I've deployed 1.7 alpha6 to > production, and > haven't seen any issues as of yet. > > Yeller's build also got ~24 seconds faster, which is super awesome (and it > no > longer breaks under CLJ-1604 because that patch is in). > > Much love to all the folk who put time and work into this release. > > Benchmark names retracted because they're proprietary. Each line is a > seperate benchmark, recorded on production level hardware, with the same > jvm options/version used in production. Each benchmark is run in its own > JVM (because otherwise JIT path dependence will kill you). > > Benchmarks that were slower under 1.7 alpha6 vs 1.6.0 (with percentage > changed amounts): > 3.12% > 2.62% > 2.27% > 2.19% > 2.17% > 2.06% > 1.97% > 1.43% > 1.29% > 0.89% > 0.74% > 0.71% > 0.58% > 0.45% > 0.42% > 0.34% > 0.27% > 0.25% > 0.21% > 0.2% > 0.08% > 0.03% > > Benchmarks that were faster under 1.7 alpha6 vs 1.6.0 (with percentage > changed amounts): > +0.0% > +0.0% > +0.01% > +0.02% > +0.03% > +0.03% > +0.03% > +0.04% > +0.04% > +0.09% > +0.12% > +0.16% > +0.31% > +0.33% > +0.52% > +0.53% > +0.85% > +1.74% > +1.84% > +1.99% > +2.14% > +2.17% > +2.42% > +2.96% > +3.0% > +5.18% > +5.36% > +9.86% > +11.93% > +12.41% > +14.36% > +16.95% > +24.71% > +53.5% > +53.62% > +72.07% > > Thanks again! Super excited about this release. > > On Wednesday, 1 April 2015 01:51:13 UTC+9, Alex Miller wrote: > > Clojure 1.7.0-alpha6 is now available. > > Try it via > - Download: > https://repo1.maven.org/maven2/org/clojure/clojure/1.7.0-alpha6/ > - Leiningen: [org.clojure/clojure "1.7.0-alpha6"] > > Regression fixes from previous alphas (and one from 1.6): > > 1) CLJ-1544 was rolled back and will be investigated for a future release. > 2) CLJ-1637 fixed regression with vec on MapEntry > 3) CLJ-1663 fixed regression in classloader (affected Cursive) > 4) CLJ-1638 fixed regression with removed PersistentVector.create(List) > method > 5) CLJ-1681 fixed regression in 1.6 with NPE on reflection warning for > literal nil arg > 6) CLJ-1604 fixed problem with AOT and shadowing clojure.core symbols that > prevented update > > Some highlights new in alpha6: > > ## Transducer-related changes: > > The LazyTransformer introduced to create lazy transforming sequences has > been > replaced with a TransformingIterator. This was done to simplify the code > around transformations and to make certain use cases around eduction more > efficient. > > ## Faster reduce, iterator, and sequence paths > > A lot of work has been done across a set of tickets to improve the ability > of > collections to provide more efficient reduce or iterator performance, and > also to > make common sequence generators create faster sequence and reduce paths. > You > should see significant performance in many reduce-related paths (this > includes > reduce, transduce, into, and anything else built on reduce). > > Many of those changes also have beneficial sequence performance, so you > may see > some benefits even in code that does not use transducers. > > * Most uses of SeqIterator have now been replaced with iterators that > directly walk > the underlying source for improved efficiency. This includes maps, sets, > records, etc. > * repeat - now returns a faster sequence with a fast reduce path > * cycle - now returns a faster sequence with a fast reduce path > * iterate - now returns a faster sequence with a fast reduce path > * range - (did not quite make it in, but coming soon...) > * keys - iterates directly over the keys of a map, without seq or MapEntry > allocation > * vals - iterates directly over the vals of a map, without seq or MapEntry > allocation > * iterator-seq - now creates a chunked sequence when previously it was > unchunked > * vec and set - were not changed in this release but were set up in a > previous alpha > to take advantage of the reduce and iterator changes above > > ## Reader conditionals > > Reader Conditionals is a new capability to support portable code that > can run on multiple Clojure platforms with only small changes. In > particular, this feature aims to support the increasingly common case > of libraries targeting both Clojure and ClojureScript. > > Code intended to be common across multiple platforms should use a new > supported file extension: ".cljc". When requested to load a namespace, > the platform-specific file extension (.clj, .cljs) will be checked > prior to .cljc. > > A new reader form can be used to specify "reader conditional" code in > cljc files (and *only* cljc files). Each platform defines a feature > identifying the platform (:clj, :cljs, :cljr). The reader conditional > specifies code that is read conditionally based on the feature/ > > Form #? takes a list of alternating feature and expression. These are > checked like cond and the selected expression is read and returned. Other > branches are unread. If no branch is selected, the reader reads nothing > (not nil, but literally as if reading ""). An optional ":default" branch > can be used as a fallthrough. > > Reader conditional with 2 features and a default: > > #?(:clj Double/NaN > :cljs js/NaN > :default nil) > > There is also a reader conditional splicing form. The evaluated expression > should be sequential and will be spliced into the surrounded code, similar > to unqoute-splicing. > > For example: > > [1 2 #?@(:clj [3 4] :cljs [5 6])] > > This form would read as [1 2 3 4] on Clojure, [1 2 5 6] on ClojureScript, > and [1 2] on any other platform. > > Additionally, the reader can now be invoked with options for the features > to use and how to interpret reader conditionals. By default, reader > conditionals > are not allowed, but that can be turned on, or a "preserve" mode can be > used to > preserve all branches (most likely useful for tooling or source > transforms). > > In the preserve mode, the reader conditional itself and any tagged literals > within the unselected branches are returned as tagged literal data. > > For more information, see: > http://dev.clojure.org/display/design/Reader+Conditionals > > Two important side notes: > - Clojure dependencies have been updated and you must re-run antsetup.sh > if you > build Clojure locally with ant. > - The equivalent ClojureScript support for reader conditionals is not yet > available > but is a top priority to release as soon as possible... stay tuned. > > ## Printing as data > > There have been enhancements in how the REPL prints values without a > print-method, specifically Throwable and the fallthrough Object case. > Both cases now print in a tagged literal data form that can be read > by the reader. > > Unhandled objects print with the class, hash code, and toString: > > user=> *ns* > #object[clojure.lang.Namespace 0x55aa628 "user"] > > Thrown exceptions will still be printed in the normal way by the default > REPL but printing them to a stream will show a different form: > > user=> (/ 1 0) > ArithmeticException Divide by zero clojure.lang.Numbers.divide > (Numbers.java:158) > user=> (println *e) > #error{:cause Divide by zero, > :via [{:type java.lang.ArithmeticException, > :message Divide by zero, > :at [clojure.lang.Numbers divide Numbers.java 158]}], > :trace > [[clojure.lang.Numbers divide Numbers.java 158] > [clojure.lang.Numbers divide Numbers.java 3808] > [user$eval5 invoke NO_SOURCE_FILE 3] > ;; elided ... > ]]} > > For all changes new in alpha6, see the issues marked "(alpha6)" in the > full changes below. > > ------------------------------------------------------------ > Clojure 1.7.0-alpha6 has the following updates since 1.6.0: > > ## 1 New and Improved Features > > ### 1.1 Transducers > > Transducers is a new way to decouple algorithmic transformations from their > application in different contexts. Transducers are functions that transform > reducing functions to build up a "recipe" for transformation. > > Also see: http://clojure.org/transducers > > Many existing sequence functions now have a new arity (one fewer argument > than before). This arity will return a transducer that represents the same > logic but is independent of lazy sequence processing. Functions included > are: > > * conj (conjs to []) > * map > * mapcat > * filter > * remove > * take > * take-while > * drop > * drop-while > * take-nth > * replace > * partition-by > * partition-all > * keep > * keep-indexed > * map-indexed > * distinct > * interpose > > Additionally some new transducer functions have been added: > > * cat - concatenates the contents of each input > * dedupe - removes consecutive duplicated values > * random-sample - returns items from coll with random probability > > And this function can be used to make completing transforms: > > * completing > > There are also several new or modified functions that can be used to apply > transducers in different ways: > > * sequence - takes a transformation and a coll and produces a lazy seq > * transduce - reduce with a transformation (eager) > * eduction - returns a reducible/iterable of applications of the > transducer to items in coll. Applications are re-performed with every > reduce/iterator. > * run! - run the transformation for side effects on the collection > > There have been a number of internal changes to support transducers: > > * volatiles - there are a new set of functions (volatile!, vswap!, > vreset!, volatile?) to create and use volatile "boxes" to hold state in > stateful transducers. Volatiles are faster than atoms but give up atomicity > guarantees so should only be used with thread isolation. > * array iterators - added support for iterators over arrays > > Some related issues addressed during development: > * [CLJ-1511](http://dev.clojure.org/jira/browse/CLJ-1511) > * [CLJ-1497](http://dev.clojure.org/jira/browse/CLJ-1497) > * [CLJ-1549](http://dev.clojure.org/jira/browse/CLJ-1549) > * [CLJ-1537](http://dev.clojure.org/jira/browse/CLJ-1537) > * [CLJ-1554](http://dev.clojure.org/jira/browse/CLJ-1554) > * [CLJ-1601](http://dev.clojure.org/jira/browse/CLJ-1601) > * [CLJ-1606](http://dev.clojure.org/jira/browse/CLJ-1606) > * [CLJ-1621](http://dev.clojure.org/jira/browse/CLJ-1621) > * [CLJ-1600](http://dev.clojure.org/jira/browse/CLJ-1600) > * [CLJ-1635](http://dev.clojure.org/jira/browse/CLJ-1635) (alpha6) > * [CLJ-1683](http://dev.clojure.org/jira/browse/CLJ-1683) (alpha6) > * [CLJ-1669](http://dev.clojure.org/jira/browse/CLJ-1669) (alpha6) > > ### 1.2 Reader Conditionals (alpha6) > > Reader Conditionals is a new capability to support portable code that > can run on multiple Clojure platforms with only small changes. In > particular, this feature aims to support the increasingly common case > of libraries targeting both Clojure and ClojureScript. > > Code intended to be common across multiple platforms should use a new > supported file extension: ".cljc". When requested to load a namespace, > the platform-specific file extension (.clj, .cljs) will be checked > prior to .cljc. > > A new reader form can be used to specify "reader conditional" code in > cljc files (and *only* cljc files). Each platform defines a feature > identifying the platform (:clj, :cljs, :cljr). The reader conditional > specifies code that is read conditionally based on the feature/ > > Form #? takes a list of alternating feature and expression. These are > checked like cond and the selected expression is read and returned. Other > branches are unread. If no branch is selected, the reader reads nothing > (not nil, but literally as if reading ""). An optional ":default" branch > can be used as a fallthrough. > > Reader conditional with 2 features and a default: > > #?(:clj Double/NaN > :cljs js/NaN > :default nil) > > There is also a reader conditional splicing form. The evaluated expression > should be sequential and will be spliced into the surrounded code, similar > to unqoute-splicing. > > For example: > > [1 2 #?@(:clj [3 4] :cljs [5 6])] > > This form would read as [1 2 3 4] on Clojure, [1 2 5 6] on ClojureScript, > and [1 2] on any other platform. > > Additionally, the reader can now be invoked with options for the features > to use and how to interpret reader conditionals. By default, reader > conditionals > are not allowed, but that can be turned on, or a "preserve" mode can be > used to > preserve all branches (most likely useful for tooling or source > transforms). > > In the preserve mode, the reader conditional itself and any tagged literals > within the unselected branches are returned as tagged literal data. > > For more information, see: > http://dev.clojure.org/display/design/Reader+Conditionals > > * [CLJ-1424](http://dev.clojure.org/jira/browse/CLJ-1424) > > ### 1.3 Keyword and Symbol Construction > > In response to issues raised in [CLJ-1439]( > http://dev.clojure.org/jira/browse/CLJ-1439), > several changes have been made in symbol and keyword construction: > > 1) The main bottleneck in construction of symbols (which also occurs > inside keywords) was > interning of the name and namespace strings. This interning has been > removed, resulting > in a performance increase. > > 2) Keywords are cached and keyword construction includes a cache check. A > change was made > to only clear the cache reference queue when there is a cache miss. > > ### 1.4 Warn on Boxed Math > > One source of performance issues is the (unintended) use of arithmetic > operations on > boxed numbers. To make detecting the presence of boxed math easier, a > warning will now > be emitted about boxed math if \*unchecked-math* is set to :warn-on-boxed > (any truthy > value will enable unchecked-math, only this specific value enables the > warning). > > Example use: > > user> (defn plus-2 [x] (+ x 2)) ;; no warning, but boxed > #'user/plus-2 > user> (set! *unchecked-math* :warn-on-boxed) > true > user> (defn plus-2 [x] (+ x 2)) ;; now we see a warning > Boxed math warning, NO_SOURCE_PATH:10:18 - call: public static > java.lang.Number > clojure.lang.Numbers.unchecked_add(java.lang.Object,long). > #'user/plus-2 > user> (defn plus-2 [^long x] (+ x 2)) ;; use a hint to avoid boxing > #'user/plus-2 > > * [CLJ-1325](http://dev.clojure.org/jira/browse/CLJ-1325) > * [CLJ-1535](http://dev.clojure.org/jira/browse/CLJ-1535) > * [CLJ-1642](http://dev.clojure.org/jira/browse/CLJ-1642) (alpha6) > > ### 1.5 update - like update-in for first level > > `update` is a new function that is like update-in specifically for > first-level keys: > > (update m k f args...) > > Example use: > > user> (update {:a 1} :a inc) > {:a 2} > user> (update {:a 1} :a + 2) > {:a 3} > user> (update {} :a identity) ;; missing returns nil > {:a nil} > > * [CLJ-1251](http://dev.clojure.org/jira/browse/CLJ-1251) > > ### 1.6 Faster reduce and iterator paths (alpha6) > > Several important Clojure functions now return sequences that also > contain fast reduce() (or in some cases iterator()) paths. In many > cases, the new implementations are also faster for lazy sequences > > * repeat - now implements IReduce > * cycle - implements IReduceInit > * iterate - implements IReduceInit > * range - implements IReduce, specialized case handles common case of all > longs > * keys - iterates directly over the keys of a map, without seq or MapEntry > allocation > * vals - iterates directly over the vals of a map, without seq or MapEntry > allocation > * iterator-seq - creates a chunked sequence when previously it was > unchunked > > Additionally, hash-maps and hash-sets now provide iterators that walk > the data structure directly rather than via a sequence. > > A new interface (IMapIterable) for direct key and val iterators on maps > was added. External data structures can use this interface to provide > direct key and val iterators via keys and vals. > > These enhancements are particularly effective when used > in tandem with transducers via transduce, sequence, into, and > eduction. > > * [CLJ-1603](http://dev.clojure.org/jira/browse/CLJ-1603) > * [CLJ-1515](http://dev.clojure.org/jira/browse/CLJ-1515) > * [CLJ-1602](http://dev.clojure.org/jira/browse/CLJ-1602) > * [CLJ-1669](http://dev.clojure.org/jira/browse/CLJ-1669) > > ### 1.7 Printing as data (alpha6) > > There have been enhancements in how the REPL prints values without a > print-method, specifically Throwable and the fallthrough Object case. > Both cases now print in a tagged literal data form that can be read > by the reader. > > Unhandled objects print with the class, hash code, and toString: > > user=> *ns* > #object[clojure.lang.Namespace 0x55aa628 "user"] > > Thrown exceptions will still be printed in the normal way by the default > REPL but printing them to a stream will show a different form: > > user=> (/ 1 0) > ArithmeticException Divide by zero clojure.lang.Numbers.divide > (Numbers.java:158) > user=> (println *e) > #error{:cause Divide by zero, > :via [{:type java.lang.ArithmeticException, > :message Divide by zero, > :at [clojure.lang.Numbers divide Numbers.java 158]}], > :trace > [[clojure.lang.Numbers divide Numbers.java 158] > [clojure.lang.Numbers divide Numbers.java 3808] > [user$eval5 invoke NO_SOURCE_FILE 3] > ;; elided ... > ]]} > > ## 2 Enhancements > > ### 2.1 Error messages > > * [CLJ-1261](http://dev.clojure.org/jira/browse/CLJ-1261) > Invalid defrecord results in exception attributed to consuming ns > instead of defrecord ns > * [CLJ-1169](http://dev.clojure.org/jira/browse/CLJ-1169) > Report line,column, and source in defmacro errors > * [CLJ-1297](http://dev.clojure.org/jira/browse/CLJ-1297) > Give more specific hint if namespace with "-" not found to check file > uses "_" > > ### 2.2 Documentation strings > > * [CLJ-1417](http://dev.clojure.org/jira/browse/CLJ-1417) > clojure.java.io/input-stream h > > ... -- 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.