Hacker News new | past | comments | ask | show | jobs | submit login
A Julia Interpreter and Debugger (julialang.org)
351 points by one-more-minute on Mar 21, 2019 | hide | past | web | favorite | 96 comments

> JuliaInterpreter received numerous performance enhancements, and now can run step-wise through code at roughly 50× its original speed. These optimizations reduce—but come nowhere close to eliminating—the most serious disadvantage of running all code in the interpreter: slow performance. It is hoped that the performance gap between compiled and interpreted code, which can be many orders of magnitude, will narrow in the coming months. However, the interpreter will always be slower than compiled code.

> It’s also worth noting that there are cases where the interpreter feels faster, at least on initial execution. Julia’s JIT compiler produces excellent results, but all that code-analysis takes time; there is interest in exploring whether running more code in the interpreter could reduce latency, a.k.a. the “time to first plot” problem. JuliaInterpreter is a potential tool for exploring that trade off, and it appears that not much additional work would be needed.

Oh wow, this is great. I've really enjoyed what little toying around with Julia I've done, but it seemed just shy of feeling truly interactive to me. But I really do love the featureset of the language, so if this gets integrated into the language and it helps in time to interactivity, I'll absolutely be moving some parts of my work to Julia.

More importantly to me, Julias combination of features means code is not very self documenting and error messages are (often) terrible.

If I need to understand what subtle assumption of DifferentialEquations I violated stepping into the point of failure is God sent. And that's a well documented package.

More importantly, I now can usually reason my way around. But my students can use this to learn what goes wrong in their codes interaction.

This is a massively important step in the tooling and ecosystem. Congratulations to the developers.

That's a great news! I search for a new general use (for me) language. I come from C++ and C land. I don't like Python for bigger projects, because of it's typing regime, performance and white space significance. So far Julia seems nice and improvement in tooling is always welcome, because tooling is crucial for the language survival.

A side question: How is Julia for web development? I'm not really a web developer and my mindset is more in realms of C, shell and CGI or Go. I mean a small to mid scale operation so SQLite integration is probably enough and Julia has a package for that.

Python added 'type hints' as of 3.5 BTW https://docs.python.org/3/library/typing.html

Julia has a web framework called Genie (https://github.com/essenciary/Genie.jl) which seems decent enough (probably useful for data visualizations but I don't know of many people using it (I haven't used it for anything worth mentioning)

One of the neatest things I found when I was messing around with Julia was UnicodePlots, which lets you make nice plots right in the terminal. I love that little library and used it to build a little live orderbook of GDAX right in the terminal. I wish there were more terminal-based applications for non-sysadmin/engineering tasks, I feel like its such a useful medium.

Certainly not as mature as most languages that focus on web (since it was not the priority), but it shouldn't be hard to create simple services. For example with:



Julia's main focus is on scientific computing. Basically think of it as a Matlab or Python + Numpy or even a C++ replacement for numeric computing.

A lot of the libraries are focused on optimization, differential equations, statistics, matrix operations...those sorts of things. It doesn't have classes in the way you would probably think (not really an OO language).

Go and C do not have classes either. If it's a bit comparable it would be a plus for me. I'm mainly a C++ programmer by trade by I don't enjoy it and in my free time I use mainly C with some shell glue and some Go.

I read that their focus is on scientific computing, but I feel that there is a growing effort to expand Julia's use cases. Also I think that some end user applications could gain a bit from optimized statistics or matrix operations.

As far as the language goes, Julia is absolutely awesome for general purpose work, including web development, scripting, glue language, etc.

The associated libraries are, unfortunately but understandably, less well developed than counterparts in other languages. E.g. right now I'm happily using AWS[Core/SQS/S3], which are highly functional community developed AWS packages, but they're definitely less full featured than boto3. My impression is this situation is common for a variety of web and database packages.

Ah, yea if you're ok with that then great. I like it myself. A lot of folks are dismayed by that though. I find that the language itself has the ease of Python with the performance of a language with static (or is it strong?) types, JIT, and a design focused on performance. The REPL functionality and package manager are pretty good too.

I'm not sure if you're suggesting that an "OO language" is a better match for web development, but in case you love some of the OO features like inheritance of fields, you can check out https://github.com/rjplevin/Classes.jl

I think OO or FP probably works best for enterprise apps. I don't see it as necessary for a lot of scientific apps though.

Multimethods are OO.

Polymorphism yes, but there is no class structure to combine state and behavior. I suppose OO is pretty subjective and I should say most folks wouldn't consider Julia to be OO in nature.

Sure there is, by changing struct fields content upon a multmethod dispatch.

There are many ways to do OOP.

I advise to read the "The Art of Metaobject Protocol".

I respect your lisp skills, but isn't what you're saying that "sure a tank can fly...you just need really big wings and and a giant rocket engine strapped on the back"? I'll agree that you can hack on your own object system, but aren't you essentially towing a yacht with a Honda Fit? Or do I misunderstand?

You misunderstand.

There are many ways to do OOP from CS point of view, be curious, learn them.

About Python and performance, have you tried pypy runtime? It is an alternative to the default, cpython.


In addition to this. About Python and typing, have you tried mypy (statically typed Python)? I find the typing story quite decent since Python 3.6. I use it on every project that goes above ~1000 LOC.


I’ve just finished building a REST api with it that was fairly painless and seems pretty fast (after first compile).

If you need more features the Genie.jl library is aiming to be a full featured web framework.

I must agree Genie.jl is great!

This awesome! I just created a Julia Debugger playground on Repl.it: https://repl.it/@amasad/julia-debug (it's a bit slow to start but then runs smoothly)

Here is a quick screencast: https://imgur.com/a/PXTRgHp

It's really great to be able to just click a link and start playing with Julia without installing anything! While there are other platforms offering a similar experience, I'm glad Repl.it added Julia to its tool belt.

Just a quick note for the inattentive like me: you have to click the "Run" button before executing the `@enter foo(20)` command.

They are participating in Google Summer of Code and there are many interesting projects in the ideas[1] list.

[1] https://julialang.org/soc/ideas-page

Debuggers are one of those things that I almost never use, and have a completely unearned distaste for. Literally every single time I've used a debugger it's been useful, but it's never something I think about using off the cuff. Maybe I'm just an incompetent goober who spends too much time on IRC :)

I've been getting into Julia a bit for personal projects, since I like it better than Python, so maybe this will be a good excuse to learn how to use debuggers more effectively.

I have been using debuggers since Turbo Pascal 5.0.

My experience regarding people around me that don't use them is that they never actually bothered to learn how to use them.

Same applies to other development tools like profilers and static analysers.

I guess I was quite lucky with some of the teachers and professors that crossed my path.

I know how to use a debugger, at least how to set a breakpoint and step through stuff. I'm sure there are features I'm not familiar with, but I at least understand the fundamentals.

I think part of it is that for the last 5 years , every single language I've used with any kind of professional capacity (JavaScript, Haskell, Erlang, F#, Clojure, Scheme) has had a REPL, so I can quickly play with and reload code, making debuggers a bit less necessary than if I were to do a purely-compiled language.

I definitely would benefit from learning more about performance profilers though. You've given me an idea of reading material for the weekend.

> I guess I was quite lucky with some of the teachers and professors that crossed my path.

Debuggers aren't exactly self-explanatory so the role of good teachers should not be underestimated

Sorta. I feel I was taught to program by basically being taught how to be my own debugger/stepper. That was literally a term's worth of tests. "Write down the state of the variables in this function when it is called with these inputs." was a common test question.

So, yeah, learning the keyboard shortcuts for how to step through something takes effort. However, it is doing basically what I was taught to reason about programming.

Functional idioms throw a lot of this a giant curve ball. Heaven help the person that was used to stepping through a for loop that steps over a map call. Oops. Worse if it is lazy.

That said, they are not competing ways of thinking. Just different ways. If you are having trouble with one, try the other.

(I do note that the difficulty of working in a debugger is ironically one of the major criticisms of macros in lisps.)

> Turbo Pascal 5.0 Is important to note how MUCH better some debuggers are than others. Pascal was amazing, specially if you compare to C.

Good debuggers:

- Pascal - Delphi - FoxPro /VisualFoxPro (the best of all, IMHO)

Others more common debuggers (Visual Studio, Xcode, IntelliJ, maybe others I don't remember), have issues, like the amazing "feature" of show opaque values, not allow to inspect stuff or requiere extra steps.

But the worse of all? Them are SLOW. Do "step" is slow. Waiting to see if evaluating values? slow.

Python have almost good, but mostly because python allow to see a lot. GDB sucks as is, but python make it look good.

Step being slow? How long you don't use debuggers?

Plus it is not like one needs to single step all the way, there are plenty of ways to control execution flow.

Stepping can be slow if you setup a lot of watches that get evaluated every time

That is what trace points like IntelliTrace are for, no need to single step.

> How long you don't use debuggers?

Like 7h ago?

Then what about learning their advanced features for tracing and scripting instead of always single stepping?

That is a snarky way to answer.

But here, I was talking how other debugger have not the same problems.

Maybe you just don't write bugs ;)

But really, what do you use in their place? Do you work in an environment that is "debugger by default" (as opposed to a separate step where you need to "debug" instead of "run")?

"println debugging" is a tried and true strategy. Debuggers' firehose of information can start to get really hairy when you have multiple threads of execution, for example. "println debugging" (if you have the right tools) can get you 98% of the way there and show you exactly only the relevant information.

A lot of debuggers have a feature where you can stop the execution of threads you don't want to bother with, which I find to actually be more useful than println debugging.

It's not a satisfying answer really, but I use a bunch of log statements. It's definitely not as good as a debugger, but 9 times out of 10, it's sufficient.

This is one of the main things which has driven the development of julia's logging system; it seems that some people just don't like debuggers very much (I'm one of them) and find staring at logs and attempting to run the code in their head to be a productive alternative.

I think it's the difference between inspecting local vs global program behavior. A debugger gives a very local view of the program but the most difficult bugs are ones where the local behavior is (or seems) correct but the global behavior is wrong. In that case it can be much more useful to run the program to completion with plenty of logging and then to carefully inspect the record of how the state changed.

Have you tried using a debugger as a "dynamic print statement"?

Yeah, and when I did node.js programming, the one time I ever got node-inspector working, I even would inject code in while paused on a breakpoint, which is undeniably useful.

Could be because you've never used a good one. I could see how that distaste would form if all you've ever used was the likes of gdb, lldb, of (if you work in Python) pdb. But when I was switching away from Windows entirely 15 years ago, giving up windbg and Visual Studio debugger was HARD. It's so convenient when you can just _see_ what your program is doing without a lot of extra friction. The downside is, this very much disincentives the writing of tests, because you can get non-trivial pieces of code working without any tests. But with a little self-discipline, I think having a great debugger was a net positive for me, both code quality and productivity-wise.

Throughout my career, I have never met anyone who used MS tools that did not find them excellent and productivity enhancing. In fact I could probably add to MS any of the language vendors from years ago. I remember using Borlands terminal based C++ environment back in the early 90's. That's about 30 years ago and that environment is better than what I use programming on Linux today.

I have often thought that programmers posture over their tool independence to signal their excellence. Before the current generation of programmers, many programmers would proclaim how they didn't need to use higher level languages to assist them in programming because assembly language was sufficient given their reasoning powers. Today programmers proclaim they don't need types to insure data invariants as their reasoning powers are sufficient. They proclaim they don't get any value from unit testing because they can maintain correctness across all development phases using their reasoning powers alone. They proclaim they don't need automatic garbage collection because they can insure correct memory usage using their reasoning powers. They have no use for IDEs, debuggers, or profilers because they believe none of these tools could augment their reasoning powers.

Excellent programmers can indeed compensate for poor tooling through their reasoning powers alone. But if history is a guide, people who don't use the best tools, practices and technologies to produce the best work, at some point, wont produce the best work.

I think the situation on the FOSS side is compounded by the fact that gdb, while it's unquestionably not in any way "state of the art", is also not totally useless, so there's less of a reason to create something that's truly excellent. Moreover, there are whole generations of programmers now who think that tooth extraction compares favorably to using a debugger.

If there wasn't gdb/lldb at all, I'm pretty sure Linux/BSD would have a debugger that's far better than any closed source counterpart.

> But if history is a guide, ...

Well, cite, please.

I think the main problem with debuggers is that I've seen people crippled by the need of them. Literally unable to simply stop and ask what could possibly have caused the outcome they saw. Having to use a program to step through with the required values to reproduce what they should already know will happen when those values are present.

Which isn't to say that live coding and debuggers are bad. However, they are usually much more useful to find out either how something got to where it is, or to augment what you have until it is ready to send for review.

Which languages have you tried to use a debugger with? Debuggers like gdb look awful (at least without a GUI). On the other hand, Chrome's JavaScript debugger is a joy to work with.

I've used Chrome's JS debugger, which I agree isn't so bad (though I don't really do frontend work, and I only managed to get node-inspector working once).

I've also used the Visual Studio debugger for F#, and I think I did gdb with Eclipse a couple years ago when I did C.

GDB is very useable with the TUI mode or the Emacs integration.

This should be a game changer. I had tried Julia before and was disappointed by the interactivity of the REPL because redefinition of code at runtime was anything but easy to achieve. If it works as stated Julia REPL now should be on par with CL's one. I'll give Julia another try!

> Revise.jl allows you to modify code and use the changes without restarting Julia.

Might be helpful :) https://timholy.github.io/Revise.jl/stable/

I tried Revise and the fact that it doesn't require you to restart Julia doesn't mean that it allows you to change code on the fly. It means that you don't have to close the REPL and restart it and that you don't have to explicitly reload code. To see the effects of a change to a function invoked in a loop you have to wait for the loop to complete and return back to the REPL. This is not really SO interactive. In CL you see the effect of any change immediatly at the next iteration of the loop. What Revise does is to automatically recompile updated code by detecting changes automatically. I hope that this interpreter brings the same level of interactivity as CL. I'll try it for sure.

>In CL you see the effect of any change immediatly at the next iteration of the loop.

This. I just did this today on CL, because I needed it. I was running a long process and can't afford to stop it.

And note that i'm using a CL compiler that compiles down to machine language, not an interpreter.

> In CL you see the effect of any change immediatly at the next iteration of the loop.

unless the code has been inlined

Is CL Common Lisp?

Don't know much about Julia, but it seems like this debugger works by running the code in an interpreter? Is there tooling around debugging compiled Julia code as well, or is this the only way to feasibly debug Julia? It any of this tooling standardized so it could work in say GDB or LLDB (taking advantage of their command syntax, Python API, etc.)?

Even newer... so early days, but you might also be intereting `MagneticReadHead.jl`. The debugging instrumentation gets compiled into the code.


Author of MagneticReadHead.jl here. Hit me up with any questions.

It is a a bit less polished than Debugger.jl right now.

Iirc the first attempt, Gallium, did that. I believe it was technically super ambitious and a bit brittle maybe. It worked with Julia version 0.5. Maybe one time Keno or someone else very capable has time to revive it, I don't know.

Yup, Gallium used DWARF debug info like gdb/lldb and could debug optimized, compiled Julia code. It's named Gallium because the DWARF standard constant for the Julia language is 31 and gallium is the 31st element in the periodic table :) Unfortunately, compilers generate horrible debug info and it was very hard to get even basic stuff like knowing the values of all in-scope local variables to work reliably and making breakpointing work was very much a work in progress.

Debugger.jl on the other hand is slow, being interpreter-based, but very reliable. The down side is that it's really slow, so if you need to debug performance intensive code, you might be in trouble. In the future, the plan is to steal tech from Gallium [1] and MagneticReadHead [2] and use them to create a hybrid interpreted/compiled debugger that is as reliable as Debugger.jl is now but which can run code fast enough to debug even compute-intensive workloads effectively.

[1] https://github.com/JuliaDebug/Gallium.jl

[2] https://github.com/oxinabox/MagneticReadHead.jl

The history here is a bit as follows. Back about four years ago, I set out to write a debugger for Julia and while I was at it, I figured I might as well fix all of the other things that have always bothered me about debugging. As an example of that, it had the following features:

  - Being completely written from scratch in Julia
  - Mixed debugging between Julia and C/C++ code
  - Integration with https://github.com/mozilla/rr for time traveling debugging
  - Debugging windows programs running on a linux host under wine (and in particular even as an rr replay).
  - Zero overhead debugging by using mixed modes (DWARF based debugging generally, a much more accurate interpreter based one when possible).
  - Very precise location tracking, on an expression basis, not just a line-by-line basis
  - Multi-process debugging by riding along RPC calls, even across machine and even as separate rr recordings across machines
As you can tell from this feature list, that project was a bit over ambitious and in the end failed to be a particularly useful debugger for Julia. It was useable for a bunch of basic cases, but fairly brittle. Also, then 0.6 came around and all of Julia's internal APIs changed and porting over the entirety of Gallium would have been quite hard.

After 0.6 was released, I decided this wasn't working out for a Julia debugging story and pulled out just the interpreter and UI parts from Gallium (that package was called ASTInterpreter2.jl). This worked ok, but was lacking a bunch of features that I never got around to implementing, because the lead up to 1.0 required a whole bunch of compiler work that nobody else was available to do. This work now is based on that work from 0.6, but actually making it work nicely and paying a whole lot of attention to it that I was never able to. I'm very happy that Tim, Kristoffer and Sebastian decided to take this on, because I feel like my workload has only increased over the past year ;).

I still very much want all the ambitious features from above, and we do still have the code (and much of it is actually in use, just not for debugging) and I'm fully expecting them to make a recurrence. However, this time around, we'll start with a stable, usable system and gradually make it faster and add features, rather than building an unstable system with all the features and trying to fix it. The former approach is much better for getting usable tools out (though sometimes the latter can lead to more interesting results in a research setting). The other thing to note is that Julia is much more stable now, so it's easier to keep things running without breaking every few months.

The history of this makes me think of Gall's Law [1] which was on HN just the other day. It will be truly awesome when we do get all of these features you originally wanted into a standard, stable, usable Julia debugger—and I have no doubt that we will eventually :D

[1] https://news.ycombinator.com/item?id=19430948

This effort is effectively the revival of half of Gallium. At the end Gallium was a combination of two debugging techniques — it was both a "native" gdb/lldb-style compiled debugger as well as an interpreter. The native debugging was fast but indeed challenging and rather limited — most Julia code gets optimized away when it gets compiled leaving you with a rather unhelpful stack frame that's challenging to line back up with your original code. So there was also a rudimentary interpreter (the ancestor of this interpreter) for other cases.

Is there no way to compile Julia with debugging symbols and frame pointers?

If you want to debug Julia itself, you can use gdb/lldb on it. That plus using the `jl_` function to dump values gets you a pretty decent debugger if you're comfortable in gdb/lldb, but it's not an experience that most Julia users would be happy with and you cannot evaluate code in the current stack frame's context or set breakpoints with Julia expressions as conditions. Debugger.jl lets you do all of that.

It does by default so you can use gdb/lldb and perf on Julia code.

Something like this is currently being attempted with MagneticReadHead.jl[1] which also just saw its first beta release. It's a pretty cool tool, using Cassette to essentially do an extra compiler pass, descending into code from other modules and inject the appropriate debugging tools.

[1] https://github.com/oxinabox/MagneticReadHead.jl

MagneticReadHead is a bit different than what I think your parent post was asking about—that's more what Gallium was. The breakdown of approach is:

1. Gallium was a traditional gdb/lldb-style debugger

2. Debugger.jl is a pure interpreting debugger

3. MagneticReadHead works by compiling a modified version of the code you want to debug that is instrumented to add debugging hooks (this is different from how gdb/lldb work).

Oh I misread the parent. My bad.

Yes, the original attempt was a bit brittle. So this attempt addresses things from the other end and having something robust but slow. From here on, the plan is to keep adding features from Gallium that improve performance.

I wouldn't be surprised if it wasn't so much "brittle" as that Julia internals were too much of a moving target before reaching 1.0 to make it worth the effort of keeping it working between releases.

It was a bit of both but by far the bigger issue was that compilers emit terrible debug info. It's barely good enough to debug C/C++ code and for Julia code it was impossible to reliably get values of local variables and set breakpoints.

I don’t know enough to answer your question about hooking into gdb/etc, but are you familiar with with the code_lowered macros? They will output a given function/scope in whatever lowered form you request (lowered Julia, LLVM, and something else).

Also there is currently early plans for Debugger.jl to incorperate compilation at some point.

I've been meaning to get into julia for quite some time, but I always feel like the community is always like, "this version still needs X, when that comes out, it'll be ready." Is this it? I guess if I had applied that logic to anything else I would never have started on those either. Meh, maybe it's just me.

Yes, after this, we're done, there are no more things to do! You should start using Julia now :)

Just kidding, there are many cool things that are in the works, including Go-style multithreading and effortless automatic differentiation of arbitrary code, allowing you to "machine learn" any algorithm without a complex framework.

But that's all stuff that's not even available in most languages—now is a great time to start using Julia:

1. The latest stable release is 1.1—code you write now will keep working on all 1.x releases

2. There's excellent editor and IDE support for Julia in pretty much every imaginable configuration

3. There's a solid debugger with interfaces from the terminal and IDEs (and I'm sure soon there will be many more)

Just as a nudge for something not really of practical importance but something I'd like to see for other reasons: self-hosting.

Self-hosting leads to pain. Compiling Rust these days requires building 14 versions of Rust after building from OCAML.

I think that is worth it for Rust because I think it has good features for building compilers. And really low level runtime-y bits.

Julia has less good features for building compilers.

But still the vast majority of the language is in Julia. Including a lot of the code lowering.

Yeah, believe me, I understand the reasons for self-hosting in something like Rust versus not self-hosting in Julia. Also the fact that Julia is almost all Julia.

Still, the fact that it's almost all Julia suggests to me it could be all Julia, although maybe that's changed with 1.0+ releases.

Trying to think about why it matters to me, I think what it is a sense that if you can get what Julia offers from another language that does more, it probably is better to use that other language. So I want to see it pushed to be more general-use. Not just for the principle, but because I think in general there are gains to languages in doing so. E.g., my guess is that getting Julia to be self-hosting would require certain efforts that might pay off in other ways, or set the stage for such things.

I sure hope there will always be exciting new improvements just around the corner. The Julia community prides itself in being greedy, so we're often looking forward to those things.

It's worth noting that this entire effort is done in external packages that work on both Julia 1.0 and 1.1. One of the biggest things Julia previously needed was stability, and we now have that.

The main problem with Juno is Atom . I really hope julia come up with better VSCode support. Atom editor is essentially broken. They should choose VSCode as their main editor.

There is no main editor, you chose your own. Some who like VSCode made [1], which you could use and contribute to.

[1] https://github.com/JuliaEditorSupport/julia-vscode

My guess would be: 40% julia users use Atom, 40% julia users use JuPyTer, 30% julia users use VSCode 30% julia users use something else (Vim, Emacs, Sublime, IntelliJ).

And it adds up to over 100% because many people use many things. I use all of the above

Both Julia-VSCode and Juno are open source projects. As are plugins for like a dozen other editors.

I'm not sure who the "they" you speak of is. that "should choose VSCode as their main editor."

I’m curious why you think this. I use Atom often and for many things so I don’t consider it broken at all.

One thing that outsiders miss when considering MATLAB is the incredible debugging workflow. With this release and the Juno integration, we finally have the same experience for Julia! As a developer who used to use MATLAB and now uses Julia every day I am very excited to make use of this tool.

This is super cool and I’m really looking forward to giving this a go, great work Julia team!

Sweet. I have been slowly learning Julia - this should help!

When can we expect integration with VScode. Atom is too slow on my computer.

I tried julia three years ago, but version skew was a huge drag. Has the situtation improved on that front?

Yes, the language was (intentionally) stabilized with 1.0. So version 1.1 (the current one) is fully compatible with that, and this will remain so for the whole 1.x series. And I expect that even 2.x won't be as bad (if at all) as the major changes that were made during the early evolution of the language.

Amazingly, even packages have started to stablize. Even though a great many of them are on there own v0.x, they are both moving towards theire 1.0 releases, and being more careful about not breaking there v0.x releases.

It has since gone 1.0, so I assume it's better. I am just dipping my toes in right now though.

Yes. The language is much more stable since 1.0 (intentionally).

However some packages are still being updated.

Does this mean for loops would now be slower than vectorized ops? Excuse me if that’s a stupid question

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact