[HN Gopher] Julia 1.6 Highlights
       ___________________________________________________________________
        
       Julia 1.6 Highlights
        
       Author : 3JPLW
       Score  : 308 points
       Date   : 2021-03-25 14:45 UTC (8 hours ago)
        
 (HTM) web link (julialang.org)
 (TXT) w3m dump (julialang.org)
        
       | cbkeller wrote:
       | See also Lyndon's blog post [1] about what all has changed since
       | 1.0, for anyone who's been away for a while.
       | 
       | [1] https://www.oxinabox.net/2021/02/13/Julia-1.6-what-has-
       | chang...
        
       | f6v wrote:
       | Is there a per-project way to manage dependencies yet? I find
       | global package installation to be the biggest weakness of all the
       | R projects out there. Anaconda can help, but it's not widely used
       | for R projects. And Docker... well, don't get me started.
        
         | eigenspace wrote:
         | Yes, absolutely. Julia has very strong per-project dependency
         | tracking and reproducibility.
        
         | adgjlsfhk1 wrote:
         | Yeah. Julia's had that since (at least) 1.0. Environments are
         | built-in, and you specify project dependencies in a
         | Projects.toml file https://pkgdocs.julialang.org/v1/toml-
         | files/.
        
           | staticfloat wrote:
           | Small nitpick; its Project.toml (or JuliaProject.toml, to
           | avoid name clashes) not Projects.toml
        
           | UncleOxidant wrote:
           | Or you can activate a local project in a directory, add
           | packages and the Project.toml gets created for you.
        
           | oxinabox wrote:
           | Since 0.7 (which was 1.0 with deprecations) In julia 0.6 and
           | before it was exactly as bad as described. (though there were
           | things like Playground.jl to kind of work around it)
        
         | krastanov wrote:
         | I might be misunderstanding your question, but this post is
         | about Julia, not R. Julia has a pretty great per-project
         | dependency management.
        
           | 00117 wrote:
           | Julia is a competitor of R, hence the comparison.
        
         | psychometry wrote:
         | renv is how R projects do per-package dependency management.
         | Before renv there was packrat. This has been a solved problem
         | for years now...
        
           | f6v wrote:
           | Doesn't mean it's adopted though.
        
       | odipar wrote:
       | I like Julia (mostly because of multiple dispatch). The only
       | thing that's lacking is an industry strength Garbage Collector,
       | something that can be found in the JVM.
       | 
       | I know that you shouldn't produce garbage, but I happen to like
       | immutable data structures and those work better with optimised
       | GCs.
        
         | superdimwit wrote:
         | A low-latency GC would also be great. But again, the JVM only
         | has that due to many millions of dollars spent over decades.
        
         | eigenspace wrote:
         | Julia's garbage collector is quite good.
         | 
         | > I know that you shouldn't produce garbage, but I happen to
         | like immutable data structures and those work better with
         | optimised GCs.
         | 
         | If you use immutable data-structures in julia, you're rather
         | unlikely to end up with any heap allocations at all. Unlike
         | Java, Julia is very capable of stack allocating user defined
         | types.
        
         | newswasboring wrote:
         | I didn't even know julia GC had issues. Care to elaborate?
        
           | adgjlsfhk1 wrote:
           | The biggest struggle Julia's GC has is that in multi-threaded
           | workloads, it sometimes isn't aggressive enough to reclaim
           | memory leading to OOM.
        
             | StefanKarpinski wrote:
             | This is very legit issue that the compiler team has their
             | eye on and plans to work on.
        
               | adgjlsfhk1 wrote:
               | fyi, I'm oscardssmith on most other channels.
        
               | StefanKarpinski wrote:
               | Hi, Oscar! Nice user name :P
        
           | StefanKarpinski wrote:
           | It doesn't, it just doesn't have a $100B GC like Java does.
           | Rather than spending that kind of money trying to compensate
           | for a language design that generates massive amounts of
           | garbage (ie Java), Julia takes the approach of making it
           | easier to avoid generating garbage in the first place, eg by
           | using immutable structures that can be stack allocated and
           | having nice APIs for modifying pre-allocated data structures
           | in place.
        
             | odipar wrote:
             | I don't think you can allocate immutable data structures on
             | the stack.
             | 
             | I've never seen a 10 million entry immutable set on the
             | stack but I could be wrong.
        
               | StefanKarpinski wrote:
               | Obviously a 10-million-element array doesn't get stack
               | allocated. But if individual objects of some type are
               | immutable, then they can be stack allocated, or maybe not
               | allocated at all (kept in registers).
               | 
               | Edit: reading your other post, it seems like you may mean
               | persistent data structures, a la Clojure, rather than
               | immutable structures, which are quite different. The
               | former would indeed always be heap-allocated (it's
               | necessary since they are quite pointer-heavy). Immutable
               | structures, on the other hand are detached from any
               | particular location in memory.
               | 
               | Moreover, if the elements in an array are mutable, eg
               | Java objects, then each one needs to be individually heap
               | allocated with a vtable pointer and the array has to be
               | an array of pointers to those individually allocated
               | objects. For pointer-sized objects (say an object that
               | has a single pointer-sized field), that takes 3x memory
               | to store x objects, so that's already brutal, but worse
               | is that since the objects are all individually allocated,
               | the GC needs to look at every single one, and freeing the
               | space is a fragmentation nightmare. If the objects are
               | immutable (and the type is final; btw _all_ concrete
               | types are final in Julia), then you can store them inline
               | with no overhead and GC can deal with them a single big
               | block.
               | 
               | Btw, I had to vouch for you to undead your posts in order
               | to reply. Looks like you got downvoted a bunch.
        
             | leephillips wrote:
             | Ouch.
        
               | StefanKarpinski wrote:
               | I mean I'm not trying to hate on Java -- pointer-heavy
               | programming was all the rage when it was designed, and GC
               | was a hot research topic, so there was good reason to be
               | optimistic about that approach. But it turns out that
               | it's very hard to make up for generating tons of garbage
               | and pointer-heavy programming hasn't aged well given the
               | way hardware has evolved (pointers are large and
               | indirection is expensive).
        
               | leephillips wrote:
               | Hating on Java seems perfectly reasonable to me.
        
               | odipar wrote:
               | so are you _for_ GC or _against_ GC?
               | 
               | In other posts you actually argue that GCs help you
               | reduce complexity because manual memory management is too
               | much of a hassle.
               | 
               | May be immutable is not the correct term - persistent
               | data structures is what I like support for: that is my
               | use-case.
               | 
               | I think you can have efficient persistent data structures
               | without a GC, but that requires fast reference counting
               | and in turn, that requires a lot of work to be
               | competitive with the JVM.
               | 
               | I also understand that my use-case is not Julia's focus.
               | That's perfectly fine.
        
               | StefanKarpinski wrote:
               | I love GC -- it solves a ton of nasty problems in a
               | programming language design with a single feature that
               | users mostly don't have to worry about. Just because you
               | have a GC, however, doesn't mean that it's a good idea to
               | generate as much garbage as you can -- garbage collection
               | isn't free. That's where Java IMO went wrong. Java's
               | design -- objects are and subtypeable (by default) and
               | mutable with reference semantics -- generates an absolute
               | epic amount of garbage. It seems like the hope was that
               | improvements in GC technology would make this a non-issue
               | in the future, but we're in the future and it hasn't
               | turned out that way: even with vast amounts of money that
               | have been spent on JVM GCs, garbage is still often an
               | issue in Java. And this has given GC _in general_ a bad
               | name IMO quite unfairly. It just happens that Java
               | simultaneously popularized GC _and_ gave it a bad name by
               | having a design that made it virtually impossible for the
               | GC to keep up with the amount of garbage that was
               | generated.
               | 
               | It is entirely possible to design a garbage collected
               | language that doesn't generate so goddamned much garbage
               | -- and this works much, much better because a relatively
               | simple GC can easily keep up. Julia and Go are good
               | examples of this. Julia uses immutable types extensively
               | and by default, while Go uses value semantics, which has
               | a similar effect on garbage (but has other issues). With
               | a language design that doesn't spew so much garbage, if
               | you only care about throughput, a relatively simple
               | generational mark-and-sweep collector is totally fine.
               | This is what Julia has. If you also want to minimize GC
               | pause latency, then you need to get fancier like Go (I
               | think they have a concurrent collector that can be paused
               | when it's time slice is up and resumed later).
               | 
               | Persistent data structures are a whole different question
               | that I haven't really spent much time thinking about.
               | Clojure seems to be the state of the art there but I have
               | no idea if that's because of the JVM or despite it.
        
               | pron wrote:
               | > garbage is still often an issue in Java.
               | 
               | Not anymore. That future is here. Java is getting
               | "flattenable" types not because of GC, but because of
               | iteration.
        
               | StefanKarpinski wrote:
               | Has a version of Java with value types been released?
        
               | pron wrote:
               | No, but there's now a JEP, which normally means that
               | release is imminent (I'm not involved with that project,
               | so I have no inside information):
               | https://openjdk.java.net/jeps/401
               | 
               | As part of this change, existing built-in primitive types
               | (like int or double) will retroactively become instances
               | of these more general objects.
        
               | odipar wrote:
               | Thanks for the reply!
               | 
               | Unfortunately, persistent data structures tend to produce
               | (short-lived) garbage which the JVM is very good at
               | collecting!
               | 
               | So yes, Clojure benefits immensely from the JVM.
               | 
               | It is also an interesting research topic whether
               | (optimised) reference counting would be a better
               | approach.
               | 
               | Regarding objects, there is also a "middle ground" to
               | consider:
               | 
               | Split big (immutable) arrays in smaller ones, connect
               | them with some pointers in between, and you are still
               | cache friendly.
               | 
               | Also, you can do a lot on the application level to reduce
               | garbage, and most Java programmers don't care for that
               | exactly _because_ of JVM.
        
               | ChrisRackauckas wrote:
               | That's a major oversimplification. GC is good for ease of
               | use and safety of a high level language. GC is never as
               | performant as not requiring heap allocations at all.
               | Julia has a GC, but also provides a lot of tools to avoid
               | needing the GC in high performance computations. This
               | combination gives ease of use and performance.
               | 
               | Java sacrifices some performance for having this "one
               | paradigm" of all objects, and then heavily invested in
               | the GC, but in many cases like writing a BLAS it still
               | just will not give performance exactly matching a highly
               | tuned code, where as in Julia for example you can write
               | really fast BLAS codes like Octavian.jl.
               | 
               | Julia is multi-paradigm in a way that is purposely
               | designed for how these features compose. I think it's
               | important to appreciate that design choice, in both its
               | pros and cons.
        
               | StefanKarpinski wrote:
               | I don't know that the object model is why writing a BLAS
               | in Java doesn't make sense. After all they special case
               | `float` and `double` as primitives, which bifurcates the
               | whole type system and is its own whole issue, but means
               | that you can store them efficiently inline. I'm actually
               | not sure what stops someone from writing a BLAS in Java
               | except that it would be hard and there's no point.
        
               | celrod wrote:
               | To tie Octavian.jl into this memory allocation
               | discussion:
               | 
               | Octavian uses stack-allocated temporaries when "packing"
               | left matrix ("A" in "A*B"). These temporaries can have
               | tens of thousands of elements, so that's a non-trivial
               | stack allocation (the memory is mutable to boot). No heap
               | allocations or GC activity needed (just a GC.@preserve to
               | mark its lifetime). If I understand correctly, this isn't
               | something that'd be possible in Java?
               | 
               | To be fair, you can also just use preallocated global
               | memory for your temporaries, since the maximum amount of
               | memory needed is known ahead of time.
        
               | odipar wrote:
               | I like your response, and yes, it was a major
               | oversimplification and I'm sorry for that.
               | 
               | Indeed, it is always about design choices and trade-offs.
               | I can see why BLAS code is important and why Julia is an
               | optimal choice for computation heavy problems.
        
               | pron wrote:
               | You're mixing two things here: memory management and
               | memory layout. This "pointer-heavy programming" is,
               | indeed, a bad fit for modern hardware in terms of
               | processing speed due to cache misses, which is why even
               | Java is now getting user-defined primitive types (aka
               | inline types, aka value types), but in terms of memory
               | management, in recent versions OpenJDK is pretty
               | spectacular, not only in throughput but also latency (ZGC
               | in JDK 16 has sub millisecond maximum pause time for any
               | size of heap and up to a very respectable allocation
               | rate: https://malloc.se/blog/zgc-jdk16 and both
               | throughput and max allocation rate are expected to grow
               | drastically in the coming year with ZGC becoming
               | generational). As far as performance is concerned, GC can
               | now be considered a solved problem (albeit one that
               | requires a complex implementation); the only real price
               | you pay is in footprint overhead.
        
               | StefanKarpinski wrote:
               | I'm not -- memory layout and memory management are
               | (fairly obviously, I would think) intimately related. In
               | particular, pointer-heavy memory layouts put way more
               | stress on the garbage collector. Java's choice of making
               | objects mutable, subtypeable and have reference
               | semantics, basically forces them to be individually heap-
               | allocated and accessed via pointers. On the other hand,
               | if you design your language so that you can avoid heap
               | allocating lots of individual objects, then you can get
               | away with a much simpler garbage collector. Java only
               | needs spectacular GC technology because the language is
               | designed in such a way that it generates a spectacular
               | amount of garbage.
        
               | pron wrote:
               | I would say no. To have stellar performance, you'll need
               | compaction, you'll need parallelism (of GC threads), and
               | you'll need concurrency between the GC threads and
               | mutator threads; and for good throughput/footprint
               | tradeoff you'll need generational collection. True, you
               | might not need to contend with allocation rates that are
               | that high, but getting, say, concurrent compaction (as in
               | ZGC) and/or partial collections (as in G1), requires a
               | sophisticated GC. E.g. Go isn't as pointer-heavy as (pre-
               | Valhalla) Java, and its GC is simple and offers very good
               | latency, but it doesn't compact and it throttles, leading
               | to lower throughput (I mean total program sluggishness)
               | than you'd see in Java, even with a much higher
               | allocation rate. The thing is that even with a low
               | allocation rate, you'd get some challenging heaps, only
               | later, say, every 10 seconds instead of every 5.
               | 
               | It's true that a simpler GC might get you acceptable
               | performance for your requirements if your allocation rate
               | is relatively low, but you still won't get OpenJDK
               | performance. So I'd say that if you design your language
               | to require fewer objects, then you can get by with a
               | simple GC _if_ your performance requirements aren 't too
               | demanding.
               | 
               | All that dereferencing puts a higher load on data
               | structure traversal (which is why Java is getting
               | "flattenable" types) than on the GC. The main reason for
               | Java's particular GC challenges isn't its pointer-heavy
               | (pre-Valhalla) design but the mere fact that it is the
               | GCed platform that sees the heaviest workloads and most
               | challenging requirements by far. Java's GC needs to work
               | hard mostly for the simple reason that Java is asked to
               | do _a lot_ (and the better some automated mechanism
               | works, the more people push it).
        
               | bbatha wrote:
               | Go has only concurrency of the features you talk about
               | but is often competitive with Java in benchmarks. In my
               | experience I'll take administration of go processes any
               | day of the week over Java -- I've lost count of the
               | number of hours lost to debugging gc stalls, runaway
               | heaps and other garbage collector related issues never
               | once had those problems in go.
               | 
               | Go even reverted a generational collector because it had
               | no performance benefits since most generational objects
               | would be stack allocated anyway -- Julia's JIT and way
               | more advanced llvm backend should do even better than go
               | in keeping objects stack local and inline.
        
               | pron wrote:
               | It's competitive in pretty forgiving benchmarks. And LLVM
               | is way more advanced than Go's compiler, but not
               | OpenJDK's. I'm not saying you have to prefer Java to Go,
               | but its throughput _is_ better. As to the stack-
               | allocation claim, young generations might be hundreds of
               | MBs; that might correspond to the stacks of 100K
               | goroutines on some server workloads, but not of a few
               | threads.
               | 
               | So I'm not saying you must prefer Go to Java, or that
               | Go's performance isn't adequate for many reasonable
               | workloads, only that 1. a flatter object landscape might
               | still not match Java's memory management performance
               | without sophisticated GCs, and 2. I wouldn't extrapolate
               | from Go to Julia, as they are languages targeting very
               | different workloads. E.g. Julia might well prefer higher
               | throughput over lower latency, and Go's GC's throughput
               | is not great.
        
       | siproprio wrote:
       | On 1.6, I tried "] add Plots" and julia got stuck.
        
         | StefanKarpinski wrote:
         | Please file an issue describing the situation:
         | https://github.com/JuliaLang/julia/issues/new
        
           | siproprio wrote:
           | After the issue, I nuked the .julia folder, and now it is
           | taking too long to clone the "JuliaRegistries/General.git"
           | repo.
           | 
           | By the download speed, it might take a few hours before I can
           | plot something.
           | 
           | It also seems that just doing "git clone
           | JuliaRegistries/General.git" is much faster than doing "] add
           | Plots"
        
             | siproprio wrote:
             | > (@v1.6) pkg> add Plots Installing known registries into
             | `~\\.julia` Cloning registry from
             | "https://github.com/JuliaRegistries/General.git" Fetching:
             | [==> ] 3.4 %
             | 
             | I gave up because it's just too slow (more than 15 min to
             | get to 3%).
             | 
             | Maybe plotting is indeed faster, but I don't think I'll
             | actually get to that point.
        
               | 3JPLW wrote:
               | Is your home folder on a network drive?
        
               | siproprio wrote:
               | Nope.
        
               | the_duke wrote:
               | Did you try a manual git clone to rule out any network or
               | FS issues?
        
               | siproprio wrote:
               | A manual git clone is very slow for the Julia registry,
               | but it's still an order of magnitude faster...
        
             | dagw wrote:
             | Is this on Windows? I've experienced the same for the past
             | few releases in Windows. For some reason that clone step is
             | ridiculously slow.
        
               | siproprio wrote:
               | Yes.
        
               | oxinabox wrote:
               | Window registry issues have been a thing.
               | 
               | I have heard it is to do with how windows antivirus
               | works. Since the registry is like 10,000 seperate files.
               | It chokes on them.
               | 
               | I have heard there is an upcoming feature to allow the
               | package manager to work with the registry being kept
               | inside a tarball, which is specifically being added to
               | deal with this
        
       | 3JPLW wrote:
       | The feature I'm most excited about is the parallel -- and
       | automatic -- precompilation. Combined with the iterative latency
       | improvements, Julia 1.6 has far fewer coffee breaks.
        
         | shmeano wrote:
         | or sword fights https://xkcd.com/303/
        
           | yesenadam wrote:
           | Ohh, is that what the programmers were doing all through
           | _Halt and Catch Fire_? Waiting for compilation? I couldn 't
           | understand how they got away with acting like naughty 5 year
           | olds, throwing things at each other constantly.
        
       | systems wrote:
       | I know its minor, but I still hope they will fix scoping
       | 
       | not that my suggestion is good, but what they have now is bad
       | 
       | https://github.com/JuliaLang/julia/issues/37187
        
         | StefanKarpinski wrote:
         | Has been fixed since 1.5.
        
           | systems wrote:
           | no it has not, they now have different rules for repl, which
           | is part of scope awkwardness
        
           | patagurbon wrote:
           | Should that issue be closed then?
        
             | systems wrote:
             | Its a suggestion to fix the awkwardness, one that will
             | never get approved
             | 
             | "Put your code into functions, people!" .. is the reason
             | why most people dont notice the weird scoping rules
             | 
             | You will only hit the weirdness face first, if you write
             | scripts with global variables, which is usually what
             | beginners do
             | 
             | Most advanced users, and library writers, probably hardly
             | notice it
        
       | MisterBiggs wrote:
       | I've been running the 1.6 release candidates, and the compilation
       | speed improvements have been massive. There have been plenty of
       | instances in the past where I've tried to 'quickly' show off some
       | Julia code, and I end up waiting ~45 seconds for a plot to show
       | or a minute for a Pluto notebook to run, and that's not to
       | mention waiting for my imports to finish. It's still slower than
       | Matlab for the first run, but it's at least in the same ballpark
       | now.
        
         | Sukera wrote:
         | What kind of speed do you see now?
        
           | leephillips wrote:
           | I've also been running the release candidates, and I get
           | something like 6 seconds to first plot on my 2013 laptop,
           | including the time for `using Plots` and the time to actually
           | draw the first plot. A huge improvement; kudos to the
           | developers.
        
           | MisterBiggs wrote:
           | No idea if this is really a fair comparison but just to get a
           | brief idea of current speeds:                  julia> @time
           | let               using Plots               plot([sin, cos])
           | end             11.267558 seconds (17.98 M allocations: 1.114
           | GiB, 4.83% gc time)
           | 
           | Versus Matlab which probably takes about 15 seconds just to
           | open the editor but plotting is very fast.
           | >> tic        fplot( @(x) [sin(x) cos(x)])        toc
           | Elapsed time is 0.374394 seconds.
           | 
           | Julia is just about as fast as Matlab after the first run for
           | plotting.
        
             | siproprio wrote:
             | > Matlab which probably takes about 15 seconds just to open
             | the editor
             | 
             | Try this:
             | 
             | matlab -nosplash -nodesktop -r "tic; fplot( @(x) [sin(x)
             | cos(x)]); toc"
        
               | eigenspace wrote:
               | I believe that's still not going to capture the startup
               | time of Matlab itself, right?
        
               | siproprio wrote:
               | It's faster than opening the editor, though.
        
             | dan-robertson wrote:
             | I wonder how much Julia could be helped with some
             | uneval/image-saving magic. So when you run the repl you
             | instead get a pre-built binary with plot already loaded and
             | several common specialisations already compiled.
        
               | staticfloat wrote:
               | We call these "system images" and you can generate them
               | with [PackageCompiler](https://github.com/JuliaLang/Packa
               | geCompiler.jl). Unfortunately, it's still a little
               | cumbersome to create them, but this is something that
               | we're improving from release to release. One possible
               | future is where an environment can be "baked", such that
               | when you start Julia pointing to that environment (via
               | `--project`) it loads all the packages more or less
               | instantaneously.
               | 
               | The downside is that generating system images can be
               | quite slow, so we're still working on ways to generate
               | them incrementally. In any case, if you're inspired to
               | work on this kind of stuff, it's definitely something the
               | entire community is interested in!
        
         | peatmoss wrote:
         | In terms of "don't make me think about why Julia is fast but
         | feels slow for casual use" this release is going to be a game
         | changer.
         | 
         | I just did a "using Plots" in 1.6.0, and it was fast enough to
         | not care about the delta between Plots and, say, R loading
         | ggplot.
         | 
         | Huge kudos to the Julia team.
        
       | xiphias2 wrote:
       | Cool, I was thinking of downloading the RC, the demo was so
       | impressive.
       | 
       | Will there be an M1 Mac version for 1.7?
        
         | thetwentyone wrote:
         | I think so - Julia master branch (1.7 precursor) works on M1,
         | but not all the dependencies that some packages require have
         | been built for M1. Though, I understand that the wonderful
         | packaging system and the folks who work on it are working on
         | it.
         | 
         | > `git clone https://github.com/JuliaLang/julia` and `make`
         | should be enough at this point.
         | 
         | https://github.com/JuliaLang/julia/issues/36617#issuecomment...
        
           | xiphias2 wrote:
           | Cool, I'll start with 1.6, but it looks interesting of course
           | :)
        
           | staticfloat wrote:
           | Yeah, we've managed to get Julia itself running pretty well
           | on the M1, there are still a few outstanding issues such as
           | backtraces not being as high-quality as on other platforms.
           | You can see the overall tracking issue [0] for a more
           | granular status on the platform support.
           | 
           | For the package ecosystem as a whole, we will be slowly
           | increasing the number of third-party packages that are built
           | for aarch64-darwin, but this is a major undertaking, so I
           | don't expect it to be truly "finished" for 3-6 months. This
           | is due to both technical issues (packages may not build
           | cleanly on aarch64-darwin and may need some patching/updating
           | especially since some of our compilers like gfortran are
           | prerelease testing builds, building for aarch64-darwin means
           | that the packages must be marked as compatible with Julia
           | 1.6+ only--due to a limitation in Julia 1.5-, etc...) as well
           | as practical (Our packaging team is primarily volunteers and
           | they only have so much bandwidth to help fix compilation
           | issues).
           | 
           | [0] https://github.com/JuliaLang/julia/issues/36617
        
             | xiphias2 wrote:
             | That's great, releasing something that isn't yet ready
             | doesn't make sense. But when it works, it's important
             | enough to warrant a release :)
        
       | JulianMorrison wrote:
       | BTW, broken link on the documentation page, "The documentation is
       | also available in PDF format: julia-1.6.0.pdf." No it isn't.
        
         | 3JPLW wrote:
         | Thanks for the report:
         | 
         | https://github.com/JuliaLang/julia/issues/40190
         | 
         | Edit: it's now building:
         | 
         | https://github.com/JuliaLang/docs.julialang.org/runs/2196972...
        
           | JulianMorrison wrote:
           | Much appreciated.
        
       | snicker7 wrote:
       | On the package ecosystem side, 1.6 is required for JET.jl [0].
       | Despite being a dynamic language, the Julia compiler does a lot
       | of static analysis (or "abstract interpretation" in Julia lingo).
       | JET.jl exposes some of this to the user, opening a path for
       | additional static analysis tools (or maybe even custom
       | compilers).
       | 
       | [0]: https://github.com/aviatesk/JET.jl
        
         | celrod wrote:
         | > or maybe even custom compilers
         | 
         | Like for autodiff or GPUs.
        
         | akdor1154 wrote:
         | Good gracious, thanks for this. If JET goes anywhere, then
         | that+other goodies in 1.6 mean I will likely switch back from
         | Python+mypy.
        
       | wiz21c wrote:
       | Whatever improves loading times is more than welcome. It's not
       | really acceptable to wait because you import some libraries. In
       | understand Julia makes lots of things under the hood and that
       | there's a price to pay for that but being a python user, it's a
       | bit inconvenient.
       | 
       | But I'll sure give it a try because Julia hits a sweet spot
       | between expressiveness and speed (at least for the kind of stuff
       | I do : matrix, algorithms, graphs computations).
        
       | beeforpork wrote:
       | Julia is such a wonderful language. There are many design
       | decisions that I like, but most importantly to me, its ingenious
       | idea of combining multiple dispatch with JIT compilation still
       | leaves me in awe. It is such an elegant solution to achieving
       | efficient multiple dispatch.
       | 
       | Thanks to everyone who is working on this language!
        
         | skohan wrote:
         | What does it mean exactly? Or what is novel here?
        
           | ddragon wrote:
           | This video is good explaining the idea behind multiple
           | dispatch in Julia if you have time:
           | 
           | https://www.youtube.com/watch?v=kc9HwsxE1OY
        
           | JulianMorrison wrote:
           | It's like C++ template specialisation, but it happens when
           | the compiler realises you need a particular version. Which
           | may be at runtime, if you changed something.
        
             | dan-robertson wrote:
             | Except the language can choose from suitable templates (eg
             | instead of a generic matrix multiply template for floats,
             | it can use a library like LAPACK) and does so in a
             | systematic way.
             | 
             | It also has a feature (I can't recall the name) which is a
             | bit like fexprs (let's say macros who's inputs are the
             | types of the arguments of a function) that can generate
             | customised code (eg an FFT depending on the input size) on
             | the fly.
        
         | pjmlp wrote:
         | I advise you to check Common Lisp CLOS and Dylan.
        
           | dan-robertson wrote:
           | Common lisp's typesystem is just not really as useful for
           | this sort of thing. In particular it doesn't have parameter
           | used types so you can't make eg a matrix of complex numbers.
           | This breaks (1) a lot of the opportunity for optimisation by
           | inlining (because you can't assume that all the
           | multiplications in your matrix{float} multiplication are
           | regular float multiplications) or generic code (because you
           | can't have a generic matrix type and need a special float-
           | matrix); and (2) opportunities for saving memory with generic
           | data structures because the types must be associated to the
           | smallest units and not the container (eg every object in a
           | float matrix must be tagged with the fact that it is a float
           | because in theory you could put a complex number in there and
           | then you'd need to know to do a different multiplication
           | operation).
           | 
           | I guess you could try to hack together some kind of
           | templating feature to make new type-specific classes on the
           | fly, but this won't work well with subtyping. Your template
           | goes system could probably have (matrix float) as a subclass
           | of matrix, but not of (matrix real) or (matrix number). I
           | think you'd lose too much in Common Lisp's hodge-podge type
           | system.
           | 
           | A big innovation of Julia was figuring out how to make
           | generic functions and multiple dispatch work in a good way
           | with the kind of generic data structures you need for good
           | performance. And this was not a trivial problem at all.
           | Julia's system let's you write generic numeric matrix code
           | while still having float matrix multiplication done by
           | LAPACK, which seems desirable.
           | 
           | The other thing is that Julia is a language where generic
           | functions are a low-level thing all over the standard library
           | whereas Common Lisp has a mix of a few generic functions (er,
           | documentation is one; there are more in cltl2), a few "pre-
           | clos" generic functions like mathematical functions, sequence
           | functions and to some extent some array functions, and a
           | whole lot of non-generic functions.
        
           | iib wrote:
           | Wikipedia has a nice table [1] on the Multiple Dispatch page,
           | that describes one studies' findings about the use of
           | multiple dispatch in languages supporting it, in practice.
           | 
           | Although CLOS and others do support it, Julia seems to take
           | the cake by most metrics, highlighting that it is a core
           | paradigm of the language, more so than in the others.
        
           | eigenspace wrote:
           | What the OP is talking about is julia's method-based JIT
           | strategy coupling very well to multiple dispatch.
           | 
           | JIT is not new, multiple dispatch is not new, and multiple
           | dispatch + JIT also isn't new, but nmo existing langauges
           | combined them in a way that allows for the fantastic,
           | efficient devirtualization of generic methods that julia is
           | so good at.
           | 
           | This is why things like addition and multiplication are not
           | generic functions in Common Lisp, it's too slow in CL because
           | the CLOS is not able to efficiently devirtualize the
           | dispatch. In julia, everything is a generic function, and we
           | use this fact to great effect.
           | 
           | CLOS and Dylan laid a ton of important groundwork for these
           | developments, but they're also not the same.
        
             | fiddlerwoaroof wrote:
             | It's not true that CLOS generic dispatch is slow: Robert
             | Strandh and other have done a bunch of work showing that
             | it's possible to implement it efficiently without giving up
             | the dynamic redefinition features that make CLOS such a
             | nice system. There's at least one video game project
             | (Kandria) that's been funding an implementation of these
             | ideas so that generic functions can be used in a soft real-
             | time system like a video game.
             | 
             | The really nice thing about CLOS, though, is that the meta-
             | object protocol lets you choose an implementation of OOP
             | that makes sense for your use-case.
        
               | eigenspace wrote:
               | Yes, I don't doubt at all that it's _possible_ to make
               | CLOS dispatch fast. What I 'm saying is that because
               | historically people using CLOS had to pay a (often
               | negligible) runtime cost for dispatch, it limited the
               | number of places developers were willing to allow generic
               | dispatch.
               | 
               | Julia makes the runtime cost of (type stable) dispatch
               | zero, and hence does not even give julia programmers an
               | *option* to write non-generic functions (though it can be
               | hacked in like with FunctionWrappers.jl). I'm not
               | familiar with Strandh's work, but has it made the
               | overhead of generic functions low, or has it completely
               | eliminated it?
               | 
               | Another thing I'll mention is that Julia's type system is
               | parametric, and we allow values (not just types) in our
               | type parameters which is immensely useful for writing
               | generic high performance code. You can specialize methods
               | on matrices of complex integers separately from rank 5
               | arrays of rational Int8s for instance. This is not a
               | capability that CLOS or Dylan has as far as I'm aware,
               | though the common refrain is that you can do it with
               | macros, but that neglects that it's rather hard to get
               | right, and will have limited use because such macro
               | implementations of type parameters won't be ubiquitious.
               | 
               | ________________________________
               | 
               | To be clear though, I'm not hating on Common Lisp or
               | CLOS. The Common Lisp ecosystem is awesome and can do all
               | sorts of really cool things that I wish we had in julia.
               | I'm mostly just pushing back on the notion that Julia
               | doesn't do anything new or interesting.
        
           | ddragon wrote:
           | Languages with multiple dispatch aren't rare, but a language
           | having it as the core language paradigm, combined with a
           | compiler capable of completely resolving the method calls
           | during compile time, and therefore able to remove all runtime
           | costs of the dispatch, and a community that fully embraced
           | the idea of creating composable ecosystems is something
           | unique to Julia. I don't think anyone has scaled multiple
           | dispatch to the level of Julia's ecosystem before.
        
             | pjmlp wrote:
             | Depends, most use SBCL instead of paying for Allegro or
             | LispWorks, so the perception is skewed.
        
       | pjmlp wrote:
       | Love the improvements, all those little details that improve the
       | overall usability.
        
       | fermienrico wrote:
       | Are the performance claims of Julia greatly exaggerated?
       | 
       | Julia loses almost consistently to Go, Crystal, Nim, Rust,
       | Kotlin, Python (PyPy, Numpy):
       | https://github.com/kostya/benchmarks
       | 
       | Is this because of bad typing or they didn't use Julia properly
       | in idiomatic manner?
        
         | adgjlsfhk1 wrote:
         | They are measuring compile time, not runtime speed.
        
           | stabbles wrote:
           | They are measuring compile time and runtime speed, not _just_
           | runtime speed like for statically compiled langauges
        
             | stjohnswarts wrote:
             | Is that truly accurate though ? I could see them comparing
             | say load time of data files plus execution time but
             | combining compile times in there doesn't make much sense.
             | You always have to pay for it in julia but not with a
             | statically compiled file.
        
               | dklend122 wrote:
               | You only pay for it on the first run.
        
             | dunefox wrote:
             | Where does it say that?
        
               | [deleted]
        
               | ZeroCool2u wrote:
               | I'm not a huge Julia user, but typically if they don't
               | specifically mention they're segmenting runtime from
               | compilation time with Julia, that's a bit of a red flag,
               | because unlike Rust, Go, or C++ the compilation step
               | isn't separate in Julia. To the user it just looks like
               | it's running, when in reality it's compiling, then
               | running, without really letting you know in between.
        
               | cygx wrote:
               | In the matrix multiplication example, the measurement is
               | done via a simple                   t = time()
               | results = calc(n)         elapsed = time() - t
               | 
               | So startup time at least isn't included.
               | 
               | One might argue that this is still biased against Julia
               | due to its compilation strategy, but fixing that would
               | mean you'd have to figure out what the appropriate way to
               | get 'equivalent' timings for any of the other languages
               | would be as well - something far more involved than just
               | slapping a timer around a block of code in all cases...
               | 
               |  _edit:_ As pointed out below, the Julia code should
               | indeed already have been  'warmed up' due to a preceding
               | sanity check. My apologies for 'lying'...
        
               | 3JPLW wrote:
               | The problem is a minor placement issue for the `@simd`
               | macro: https://github.com/kostya/benchmarks/pull/317
        
               | komuher wrote:
               | If u cant even read code dont lie xD                   n
               | = length(ARGS) > 0 ? parse(Int, ARGS[1]) : 100
               | left = calc(101)  # <------- THIS IS COLD START JITTING
               | CALL         right = -18.67         if abs(left - right)
               | > 0.1             println(stderr, "$(left) != $(right)")
               | exit(1)         end              notify("Julia (no
               | BLAS)\t$(getpid())")         t = time()         results =
               | calc(n)         elapsed = time() - t
               | notify("stop")
        
               | stabbles wrote:
               | not sure why this was downvoted to oblivion, as it seems
               | to be correct
        
               | detaro wrote:
               | presumably because of the tone.
        
               | stabbles wrote:
               | Ah, I have to take that back, since benchmarks run in the
               | order of seconds and they use sockets to start and stop
               | the timer, which likely means compilation time is not
               | included.
        
         | StefanKarpinski wrote:
         | This appears to be a set of benchmarks of how fast a brainfuck
         | interpreter implemented in different programming languages is
         | on a small set of brainfuck programs? What a bizarre thing to
         | care about benchmarks for. Are you planning on using Julia by
         | writing brainfuck code and then running it through an
         | interpreter written in Julia?
        
           | fermienrico wrote:
           | Seems like you're the founder of Julia. Why such a knee jerk
           | reaction? Did you read the benchmark page? The table of
           | content is right at the top.
           | 
           | Optics of this type of reaction is seen everywhere in the
           | Julia community. My advice is to embrace negativity around
           | the language, try to understand if it is fabrication or
           | legitimate, and address the shortcomings.
           | 
           | Julia is a beautiful language and hope some of the warts of
           | the language gets fixed.
        
             | StefanKarpinski wrote:
             | When I wrote that I was under the impression that the
             | brainfuck interpreter implementations were the _only_
             | benchmarks in the repo. There are, however (I now realize),
             | also benchmarks for base64 decoding, JSON parsing, and
             | writing your own matmul (rather than calling a BLAS matmul,
             | which is not generally recommended), so this is more
             | reasonable than I thought but still a somewhat odd
             | collection of tasks to benchmark. Of course,
             | microbenchmarks are hard -- they are all fairly arbitrary
             | and random.
             | 
             | In a delightful twist, it seems that there is a Julia
             | implementation of a Brainfuck JIT that is much faster than
             | the fastest interpreter that is benchmarked here, so even
             | by this somewhat esoteric benchmark, Julia ends up being
             | absurdly fast.
             | 
             | https://news.ycombinator.com/item?id=26585042
        
             | CyberDildonics wrote:
             | Don't be ridiculous. If someone puts emphasis on nonsense,
             | dismissing it is reasonable.
        
             | [deleted]
        
         | [deleted]
        
         | stabbles wrote:
         | I think it's more interesting to see what people do with the
         | language instead of focusing on microbenchmarks. There's for
         | instance this great package
         | https://github.com/JuliaSIMD/LoopVectorization.jl which exports
         | a simple macro `@avx` which you can stick to loops to vectorize
         | them in ways better than the compiler (=LLVM). It's quite
         | remarkable you can implement this in the language as a package
         | as opposed to having LLVM improve or the julia compiler team
         | figure this out.
         | 
         | See the docs which kinda read like blog posts:
         | https://juliasimd.github.io/LoopVectorization.jl/stable/
         | 
         | And then replacing the matmul.jl with the following:
         | @avx for i = 1:m, j = 1:p             z = 0.0             for k
         | = 1:n                 z += a[i, k] * b[k, j]             end
         | out[i, j] = z         end
         | 
         | I get a 4x speedup from 2.72s to 0.63s. And with @avxt
         | (threaded) using 8 threads it goes town to 0.082s on my amd
         | ryzen cpu. (So this is not dispatching to MKL/OpenBLAS/etc).
         | Doing the same in native Python takes 403.781s on this system
         | -- haven't tried the others.
        
         | SatvikBeri wrote:
         | I've rewritten two major pipelines from numpy-heavy, fairly
         | optimized Python to Julia and gotten a 30x performance
         | improvement in one, and 10x in the other. It's pretty fast!
        
         | otde wrote:
         | I think this particular Julia code is pretty misleading, and
         | I'm (probably) one of the most qualified people in this
         | particular neck of the woods. I wrote a transpiler for Julia
         | that converts a Brainfuck program to a native Julia function at
         | parse time, which you can then call like you would any other
         | julia function.
         | 
         | Here's code I ran, with results:                 julia> using
         | GalaxyBrain, BenchmarkTools            julia> bench = bf"""
         | >++[<+++++++++++++>-]<[[>+>+<<-]>[<+>-]++++++++
         | [>++++++++<-]>.[-]<<>++++++++++[>++++++++++[>++
         | ++++++++[>++++++++++[>++++++++++[>++++++++++[>+
         | +++++++++[-]<-]<-]<-]<-]<-]<-]<-]++++++++++."""
         | julia> @benchmark $(bench)(; output=devnull, memory_size=100)
         | BenchmarkTools.Trial:          memory estimate:  352 bytes
         | allocs estimate:  3         --------------         minimum
         | time:     96.706 ms (0.00% GC)         median time:      97.633
         | ms (0.00% GC)         mean time:        98.347 ms (0.00% GC)
         | maximum time:     102.814 ms (0.00% GC)         --------------
         | samples:          51         evals/sample:     1
         | julia> mandel = bf"(not printing for brevity's sake)"
         | julia> @benchmark $(mandel)(; output=devnull, memory_size=500)
         | BenchmarkTools.Trial:          memory estimate:  784 bytes
         | allocs estimate:  3         --------------           minimum
         | time:     1.006 s (0.00% GC)         median time:      1.009 s
         | (0.00% GC)         mean time:        1.011 s (0.00% GC)
         | maximum time:     1.022 s (0.00% GC)           --------------
         | samples:          5  evals/sample:     1
         | 
         | Note that, conservatively, GalaxyBrain is about 8 times faster
         | than C++ on "bench.b" and 13 times faster than C on "mandel.b,"
         | with each being the fastest language for the respective
         | benchmarks. In addition, it allocates almost no memory relative
         | to the other programs, which measure memory usage in _MiB_.
         | 
         | You could argue that I might see similar speedup for other
         | languages on my machine, assuming I have a spectacularly fast
         | setup, but this person ran their benchmarks on a tenth
         | generation Intel CPU, whereas mine's an eighth generation Intel
         | CPU:                 julia> versioninfo()         Julia Version
         | 1.5.1         Commit 697e782ab8 (2020-08-25 20:08 UTC)
         | Platform Info:  OS: Linux (x86_64-pc-linux-gnu)         CPU:
         | Intel(R) Core(TM) i7-8700K CPU @ 3.70GHz           WORD_SIZE:
         | 64         LIBM: libopenlibm  LLVM: libLLVM-9.0.1 (ORCJIT,
         | skylake)
         | 
         | This package is 70 lines of Julia code. You can check it out
         | for yourself here: https://github.com/OTDE/GalaxyBrain.jl
         | 
         | I talk about this package in-depth here:
         | https://medium.com/@otde/six-months-with-julia-parse-time-tr...
        
           | Sukera wrote:
           | @btime reports the minimum execution time, since all
           | increases are attributable to noise. Use @benchmark to get
           | mean, median and maximum instead.
        
             | otde wrote:
             | Thank you! Edited to fix.
        
           | fishmaster wrote:
           | That is very cool.
        
           | eigenspace wrote:
           | Beautiful
        
           | StefanKarpinski wrote:
           | I love the Julia community
        
         | paul_milovanov wrote:
         | looks like they're just multiplying two 100x100 matrices, once?
         | (maybe I'm reading it wrong?) in Julia, runtime would be
         | dominated by compilation + startup time.
         | 
         | A fair comparison with C++ would be to _at least_ include the
         | compilation /linking time into the time reported.
         | 
         | Ditto for Java or any JVM language (you'd have JVM startup cost
         | but that doesn't count the compilation time for bytecode).
         | 
         | Generally, for stuff (scientific computing benchmarks) like
         | this you want to run a lot of computation precisely to avoid
         | stuff like this (i.e you want to fairly allow the cost of
         | compilation & startup amortize)
        
           | machineko wrote:
           | If u just look on the main page u would see they are
           | excluding jitting time (using warm start to measure jitted
           | languages) Dunno why this people cant just read few lines of
           | comments in github page before posting :D
        
       | noisy_boy wrote:
       | How easy it is to produce a compiled executable in 1.6? I took a
       | cursory look at the docs but couldn't spot the steps for doing
       | so.
        
         | triztian wrote:
         | I've also looked for this, does it mean that I have to install
         | julia on the target machine and it'll recompile when running?
         | 
         | Or are there steps to produce a binary (much like Go or C or
         | Rust)??
        
           | cbkeller wrote:
           | Currently you can make a relocatable "bundle" / "app" with
           | PackageCompiler.jl, but the bundle itself includes a Julia
           | runtime.
           | 
           | Making a nice small static binary is technically possible
           | using an approach similar to what GPUCompiler.jl does, but
           | the CPU equivalent of that isn't quite ready for primetime.
        
             | ku-man wrote:
             | You forgot to mention that a 'Hello World' standalone file
             | is about 0.5 GB!
        
             | triztian wrote:
             | Thank you for your reply! PackageCompiler looks like the
             | right way.
             | 
             | Do you happen have any links to the static binary
             | procedure? Or links to the current state of efforts for
             | this?
        
               | eigenspace wrote:
               | https://github.com/tshort/StaticCompiler.jl/pull/46
        
           | Sukera wrote:
           | You probably want to check out PackageCompiler.jl
           | (https://julialang.github.io/PackageCompiler.jl/dev/)
        
         | ced wrote:
         | We did it for production code installed at client sites, and it
         | has been very easy for us. YMMV
        
         | dklend122 wrote:
         | That's coming. Pieces are there but still need polish and
         | integration. Fib was around 44kb with no runtime required.
         | 
         | Check out staticcompiler.jl
        
           | superdimwit wrote:
           | In your experience, what are the current limitations?
        
             | eigenspace wrote:
             | There's all sorts of limitations right now. E.g. you can't
             | allocate an array right now, dynamic dispatch is
             | prohibited, there are some bugs too.
             | 
             | Most of this is just a relic from StaticCompiler.jl being a
             | very straightforward slight repurposing of GPUCompiler.jl.
             | It will take some work to make it robust on CPU code, but
             | the path to doing so it pretty strightforward. It just
             | requires dedicated work, but it's not a top priority for
             | anyone who has the know-how currently.
        
               | triztian wrote:
               | I'd love to be able to contribute to this, somewhat new
               | to Julia, but I'm sure I could help with something ...
               | 
               | Do you have any links to what has been currently done?
               | 
               | EDIT: Found this thread so far:
               | https://discourse.julialang.org/t/statically-compiled-
               | and-st...
        
               | eigenspace wrote:
               | This is the PR to look at if you want to try and help:
               | https://github.com/tshort/StaticCompiler.jl/pull/46
               | 
               | I think this isn't really a great place for beginners
               | though unfortunately. This project is tightly coupled to
               | undocumented internals of not only julia's compiler, but
               | also LLVM.jl and GPUCompiler.jl. It'll require a lot of
               | learning to be able to meaningfully contribute at this
               | stage.
        
       | ng55QPSK wrote:
       | maybe i misread this, but milestone "1.6 blockers" still has 3
       | open with "1.6 now considered feature-complete. This milestone
       | tracks release-blocking issues." - so how can 1.6 be ready?
        
         | kristofferc wrote:
         | It is simple. Those issues shouldn't have had the milestone.
        
           | ng55QPSK wrote:
           | I see. But you should work on your release process if thing
           | like this happen.
        
             | kristofferc wrote:
             | Sorry for the inconvenience and thanks for the advice.
             | We'll do our best to ensure this doesn't happen again.
        
               | icandoit wrote:
               | You guys are doing great. Julia is really taking shape.
               | Can't wait to jump ship from Python.
               | 
               | It's also nice to see that you (personally) are
               | sponsoring zig development. There is so much more room
               | for improvement in the arena of programming languages.
               | Infrastructure like this is a huge multiplier.
        
               | kristofferc wrote:
               | I'm excited about Zig and I've spent many evenings
               | looking at Andrew's streams. I haven't gotten the time to
               | try it out properly myself but I'm looking forward to it.
        
       | ghosty-discord wrote:
       | do people use Julia for machine learning model or else? is it
       | ready to go
        
       ___________________________________________________________________
       (page generated 2021-03-25 23:00 UTC)