Rust Is Surprisingly Good as a Server Language
stu2b50.dev
stu2b50.dev
I keep reading in Rust surveys that Rustaceans just don't care that much about compile times enough to prioritize improving them. I've often wondered how this can be possible, given that to me it's such an obvious glaring issue that all the other cited problems are distant distant seconds at best. I have a theory: there must be two groups of engineers. One group loves fast compile times and quickly validating hypotheses. The other group must value thinking about their code a lot more than running it, and so compile times aren't that important. My guess is that, while the second group hangs around and loves Rust, Rust has completely driven away the first group (including myself) to the degree that they don't use the language enough to even fill out the surveys.
Anyways, I know it has a wide swath of use cases, mostly in systems programming. I'm just bummed that if I ever do any of them, I won't really enjoy it. :-(
[EDIT:] Gotta go to sleep, it's far too late here. I really appreciate all the thoughtful replies. Rust's amazing community is another reason it annoys me that I can't fully get into the language as I'd like to.
I much prefer working from a logical and thoughtful approach rather than iteration. At the point where I start a build I am already reasonably confident that it will do what I want it to.
There are some bugs where I will need to re-build several times consecutively but these are relatively rare for me (I work on REST API systems - so nothing too crazy).
The main thing that I use compiling for is to validate little off-by-one things. Like, is substring() exclusive on the second parameter? What about range syntax and the slice operator? What if I wrote + 1 instead of - 1 somewhere, or did < instead of <=? I could spend a few minutes combing documentation, or just compile it and check immediately. Well, assuming compilation is fast anyways.
Maybe it's time to switch to an interpreter ? :-)
Only one of them says anything and it an empty statement like
> F#'s compile times also seem to err on the long side but not very much so, my impression goes.
However it is quite easy to validate write the same algorithm in F# and Rust and then compare.
Ah but Rust is AOT compiled, easy, use NGEN, .NET Native, or Mono AOT for the F# compile time measurements.
People should be educated on the huge bias introduced by personalized services like google.
That being said, C# is clever enough to only need to recompile the assemblies affected by your code change, so often you can get away with 10 second compile times even for large solutions.
So you had to work in individual projects at a time, slowly going through and changing stuff project by project.
VS wouldn't even build it either, really. YOu had to build via batch file that did various ms build magic. I would make changes, set of a build and go to lunch, then come back and fix the errors.
Once you checked the code into source control it would trigger a build which would sometimes take upwards of an hour :( I hated that code base.
It got even worse when they added Coded UI tests. Wait an hour for a build and then a random Coded UI test would fail and the advice from the people who wrote the Coded UI was "just run another build!", yeah, flakey tests on a code bases that tests an hour to run...
I'd love a REPL that could somehow load the state of my entire app so I could test stuff out, but I've never found a language that could do that and also had reasonable type safety guarantees.
Clojure spec is great at system boundaries but it's hard to describe it is a type system, it's a predicate system it can define very arbitrary constraints mostly at runtime
But god it's slow... Some static analysis support would also be hugely appreciated. Not being able to check everything doesn't meen you shouldn't attempt to check something! Many specs are type predicates anyway.
I'm a really big fan of reading the docs (or, where the docs are insufficient, the source), and will always have docs.rs open alongside my editor. While the examples you provide are easily validated by testing (and I'd probably use `evalr` in `##rust`, or some similar thing, for them), many subtleties can exist in more complex functions, so not reading the docs/source for unfamiliar functions feels like programming-by-guessing to me.
(OK, you could read preferences from a file, but then you'd have to optimistically write every value you'd ever want to recompile to a file. I've tried this, but it's far too much overhead.)
I know exactly what you mean. Front-end development can be this way, too.
I think it's OK (and probably true) to say that you shouldn't use Rust for cases like this right now.
I think that's true, but only because of the slow compile times. Which is why they're so frustrating. Rust would otherwise be an excellent language for these use-cases.
But I work on network protocols and file formats and parsers and video transformers and user interfaces (often command line or web) and a long time ago games ;P... I make a small change and then I want to see the behavior difference. I almost always type code that compiles, but that doesn't mean it did what I want when interacting over the network: rust doesn't provide anywhere near powerful enough type abstractions to actually prove my code is correct... it only is proving that my code can't crash and will avoid undefined behavior.
What is so frustrating is that there is nothing about Rust that makes it impossible to make fast. With C++ I get to manually make tradeoff in my code on a file-by-file basis with an assumption that my project will be built out of thousands of mostly-independent fragments that I am able to compile incrementally or in parallel. I can very rapidly isolate individual functions I am working on for fast iteration without having to restructure my project, I can tell the compiler to instantiate templates in different ways to reduce dependencies, and I have designed a system to let me do parallel compiles on AWS Lambda (I haven't yet gotten my build environment to be ready for a -j1000 parallel build, but I am somewhat close).
I have been integrating some rust libraries into my codebase (I haven't even gotten to the point of really coding in it omg) and Rust is just so painful and frustrating to work with... and it really does just seem to be, as you pointed out, a matter of priorities and interest: there is this myth that it is some kind of tradeoff on the type system, but it isn't; it is just that the people who work on rust seem to not work on the same kind of projects that we do, at least in the same way, and so have made a bunch of trade offs like "I would rather never have to type a prototype than save any time compiling" and "I would rather my build system never have to consider dependency management than save any time compiling" and "I would rather provide the highest possible quality resulting binary than save any time compiling" (which is at least one I can appreciate, but only once a month when you cut a release... not the hundreds of times a day that I recompile my C++).
Rust outputs prototype information in .rmeta artifacts that are generated as one of the first steps in compilation, so this is not a compile-time issue. AFAICT, dependencies are also tracked, and debug vs. release switches are provided that also control things like binary optimization.
The real "problem" for compile times in Rust is that Rust makes it idiomatic to write code that's slower to compile. That's really all there is to it. If you were to literally write Rust like it's C, you'd find that there's no real overhead introduced by Rust per se.
(This is not to say that improvement is not possible, of course. Even what's "idiomatic" can be tweaked over time to reduce the amount of excessive, duplicated work that the build system has to do. Newer features like const generics will probably make this feasible in the future, and improvements in the compile workflow itself will do the rest.)
I am quite curious how usable Rust/WinRT will turn out to be for WinUI work.
• The Azul GUI toolkit uses CSS for styling of its widgets, and hot-reloads stylesheets.
• The Mun programming language is designed for the sort of niche Lua is often used, with hot-reloading scripting-like functionality to augment your Rust code. (Well, Rust is the main host language at present, anyway.)
I'd also recommend getting used to serialisation/deserialisation. Serde for Rust makes this remarkably easy. Writing every setting to a file is simple if the compiler can do it for you, rather than you walking the long way around.
Also there are also a shit-ton of minor logic-changing modifications when you're writing prototype gamedev code, (for example, moving an if statement here or there to tweak the physics of your platforming). These cannot be easily represented in config files, and this is why people attach lightweight scripting languages like Lua to their game engines (so that you don't have to wait for those atrocious C++ compile times when tweaking your gameplay code).
(Ironically, serde is known for its atrocious compile times, which really makes the situation even worse. Because of this some frustrated Rust gamedevs wrote their own serialization libraries such as nanoserde (https://github.com/not-fl3/nanoserde)... but you get the point.)
Rust has a testing facility that can be used for these things. By default, all "example" code that's included as part of a doc comment ends up in the test suite. And because test cases are small and self-contained, they're also very quick to compile.
I think the main reason why I dislike working with dynamically typed languages is that most of them make the reasoning of code a lot harder. If you're able to reason about the code at hand, then there's a lot less need to run the code for every small change.
I can’t imagine not looking up the documentation to do this.
If a language had a REPL I may then confirm it in the REPL, but almost certainly would pull up the docs first.
Definitely a leftover from when I was a kid, in the early 90s, without ready access to computers. I remember lying at a hospital bed and filling pages and pages with C64 programs, using pen and paper.
This kinda forced me into the paradigm of "think through invariants and structure first". To this day, typing code out on a computer (incl. compilation) is almost mechanical, not a vital part of the design process.
I also use assertions and unit tests, because the type system still has its limitations (or some things would be too awkward to express), but I can move forward a long way without actually compiling a project.
I mostly work with C#, and occasionally I might only end up compiling the project a couple of times in a day, but I'll probably be building a test project several times in the meantime (e.g. after adding each test).
Alternatively, if I'm building a web GUI, I'll probably be building quite frequently, making sure that data is bound correctly and that the UI looks as expected.
I don't think typed vs untyped languages really makes a huge difference if you're designing code this way. The difference comes when the compiler can actually verify your design, if you don't compile it doesn't really matter what the compiler can check.
It is easy to let a project slowly slide into a state where this workflow is no longer possible, especially in high-level languages like modern C++ or Rust, when even incremental builds take so long that it throws you out of "flow".
But anyway, I think this sort of working style doesn't have to do with a language's type system, but is a personal choice and one isn't necessarily better than the other, but certain personalities might be attracted to certain language communities, and thus directly influence priorities (e.g. a large part of the 'modern C++' community seems to think that compilation time and good runtime performance in debug builds are not high priorities, which from my point-of-view is entirely irrational).
So, for my workflow relatively fast compile times are mandatory.
(Altough, I really wanna get out of desktop dev.)
(I know that compilation speed is a Hard Problem, I know that I'm comparing apples to oranges, I know that Rust does fancy magic that other languages could only dream of. But everything that slow compiles buy me won't get bring me back flow state.)
One think that’s helped me stay “in the flow” is switching to rust-analyzer instead of the current official RLS. Much faster, I leave format on save turned on, so `cargo check` output is usually ready in about a quarter of a second after save.
I LOVE rust-analyzer. It's actually what got me to reconsider Rust after I tried a year or two ago, and it is SO good.
I am less sure, but I would think that's expected, given that it has to link everything together into the final binary. You're gonna end up giving the linker more work to do, as you suspected.
https://github.com/rust-lang/rust/issues/39915#issuecomment-...
https://doc.rust-lang.org/1.22.0/unstable-book/compiler-flag...
If installed, you can run
RUSTFLAGS="-Clink-arg=-fuse-ld=lld" cargo build --releaseWhy compile again after adding a comment?
The most common trivial change would be to add a dbg! statement.
But if their use case is twice a day or similar it makes sense. Why care about compilation time at all if its seen as that rare?
Other opinions exist.
I used to be the same way, but the more I practiced holding the state in my head while I worked, the better I got at it.
> One group loves fast compile times and quickly validating hypotheses.
You just don't need it. As you make changes, the delta between expected behavior and actual behavior continues to grow. You begin to develop an intuition for what kind of things might not work as expected, and you can conceptually model around those things and continue to build your logic and make your changes.
An IDE helps immensely with type error minutiae. I'm using CLion and it's pretty great. For the few cases it can't figure out the types for you, you can run "cargo check".
I'm confident that Rust has made me a better engineer. I don't need to continually save and evaluate and I can do deeper work with more uninterrupted flow.
Give it a try! I think you'll start to acclimate.
Edit: Why the downvotes? I stated my personal experience as it relates to OP's observations. I improved in how I approach problems after exposure to Rust.
Doesn't that partially defeat the point of having a powerful compiler? The more work the compiler does, the less we have to keep track of in our head (and conversely, much of the pain of coding in a language like Python is the amount of stuff we need to mentally keep track of).
I think this is somewhat orthogonal.
There’s two sides to this: on the one hand, you don’t have to keep as much info in your head because the compiler will tell you if you ask it. On the other hand, when you do try to keep state in your head, the compiler is able to double-check that for you so that you don’t have to do it perfectly.
With a language like Python, you’re working without a safety net, so you make small, cautious, steps in order to not fall. A strongly-typed language like Rust enables you to make larger, bolder, changes in one go, confident that the little mistakes will get caught.
Unexpected behaviour and errors can be caught by means other than constant recompilation, and tools exists to do just that. In IDEs, these tools tend to become invisible, seamless, and can be relied upon without much configuration; for those accustomed to less integrated environments, the manual configuration required to get these tools up and running becomes a hassle.
I suppose using those tools efficiently and constant recompiling are different ways to solve the same problem, but I wouldn't say it's solely the compiler's job even in the latter case. For languages that aren't super-fast for compiling like Rust, Swift, etc. there may be much more reliance on those other tools.
Still, I appreciate your optimism. I'll give it a shot! Especially for things that aren't graphical.
For a contrast, I don't notice compile times at all in just about any language for the most part: when you reach the "few million lines of code" size, there's no language that is going to be instant; and for embedded/systems work, committing a change can involve things like creating builds for N different architectures and running a test suite that may have to control hardware [run times of the test suite are measured in hours to days]. At this scale, anything that the compiler catches, even if it takes an hour to compile, saves an order of magnitude more time later in the process.
It's legitimately a hard problem to design a language that works well for both projects in the few tens of thousands of lines of code size -- i.e. tossing together a quick prototype -- and scales to millions of lines of code or larger.
I get that there're some differences in the games domain, but I don't quite get your examples, because changing the position or color of objects seems like a data and not a code change. If you have these properties as data you might be even able to change them on the fly, in the running game, which will increase your iteration times quite a bit more than any faster compile times.
Well, there's a simple answer... https://xkcd.com/303/
This honestly is a bad habit. Thought it does depend quite a bit on the type of work you are doing. For some things it is necessary especially if it is inherently fibbly.
Rust is a language to which the programmer must adapt his way of working and thinking. If the programmer is too set in his way, his Rust journey will be unsuccessful. If the programmer is adaptable, he will come out in the end a better programmer, because the Rust way is actually the right way.
I think I actually went a couple of weeks once before trying out my program for the first time and there was no big deal to get it to actually work in the end.
[Citation needed]
I'd like to hear some justification for this rather than a blanket assertion. Just because our work styles differ doesn't mean that my style is necessarily wrong.
> Rust is a language to which the programmer must adapt his way of working and thinking.
I mean, Rust is actively attempting to improve compile times. It's not like devs made them intentionally long to cultivate good programming habits or something. So I'm not sure how this is relevant.
So while adding hardware helps (up to a point), Rust is definitely an outlier when it comes to compilation speed.
That's hardly the only other AOT language competing with Rust though, and while some of them are simpler on a language level (i.e. C) the compilers do a fair share of work in the optimizing stage of those simpler languages. There's also several languages that do quite a bit of heavy lifting during compilation, like Zig and Nim have extensive compile time features for example. And Nim does two passes since it compiles to C first (by default) and then that's compiled to machine code.
On balance, I don't think you can wriggle out from the fact that Rust compiles slowly compared to its competitors.
Even the Rust team admits this and are working on improving it.
The OP sounded like they wanted to use rust except for this one issue of compilation being too slow for their development style.
How fast is fast enough and is that achievable just by throwing some money at the machine?
Perfect is the enemy of good enough as they say.
Once you get your cache warm, it's pretty much instant. If not, run `cargo check` instead of `cargo run`. You can also use rust-analyser for an in-editor <1s feedback loop.
That's why you should use `cargo check` instead : it will only run the rust compiler frontend, but not the LLVM linker.
It can't catch many logic bugs, eg forgetting to update a variable's value. The type system can't help without non-straightforward techniques, and at that point it is diminishing returns.
A powerful type system shouldn't be an excuse for not being able to iterate fast.
Rerunning your code continually is no longer necessary in a language like Rust, because the compiler already does that for you.
People complaining about slow compile times in static languages like Rust, Haskell, Scala miss the forest from the trees, which is that the compiler eliminates entire bug categories, logic you'd otherwise need to check at runtime, either via unit tests or at least by running the code locally. Compiler times can always be better, but the compiler works as a theorem prover and the slowness is entirely justified, overall yielding a better ROI.
N.B. I'm not saying that with Rust you don't need to run your code or have unit tests. There's only so much a compiler can prove. But you no longer need to do it as often.
You can't switch to a language like Rust and expect Python and if you do, then the experience is going to be horrible, because Rust is a very different language.
No it's not. It's just preferable to do your work in smaller batches so that your feedback loop is fast and you know exactly which change broke things, rather than making 10 changes and then having to figure out which of those changes 4 bugs relate to. And it's better to discover a flaw in your implementation early rather than late, which is also easier when working in small increments.
Getting feedback quickly can be useful (especially when trying something new), but not needing it is liberating (especially when trying something new).
The reason I hate Spring for example (not that I've worked with it extensively) is that the documentation gives you zero feel for what you expect the behaviour to be. It will compile, but until you run it and check what it's doing, very often you'll be developing with no idea of what you're actually building.
Especially if you're trying to get specific behaviour of what you want to see (e.g: figuring out why it won't send mail, or why it doesn't ignore a certain json key or whatever), it still needs many runs to get right.
The elegance is free.
Type checking and Parsing isn't bottleneck in Rust compilation. Code generation is. LLVM is particularly heavy and while it generates optimized code, it is quite slow.
Go Authors didn't pick LLVM because of compile speed reasons (as well as complexity), and that turned out to be worthwhile tradeoff.
Anyway in C++ land massive compile times are just as much of a problem. Fast code is expensive. Go’s a lot of things, but being good at generating fast code ain’t one of them (looking holistically anyway).
Indeed, because all bigtech can invest on is LLVM and C++.
The research on compilers and optimizations has not been getting the attention because of LLVM monoculture and the monstrosity that is C++.
Even if you count the size of ode after monomorphization, I am pretty sure the Go compiler compiles it much faster. Because the compiler is not in the benchmarks rat race of adding one optimization pass from every academic paper in the world for diminishing returns. That would be unnecessary for a development compiler.
Go compiler could have an optimized slow build option, in ideal world, but that's a different matter altogether.
The parent comment was insinuating that, when developing in Rust, one can leverage its type system to replace this trial-and-error with static verification. And, indeed, if what you're worried about is a dangling or null reference error, the Rust type system has a rich language for specifying expected behavior so you don't have to run your code to check it.
If, on the other hand, your job description includes the nebulous mandate to "make it look right," there isn't any feasible way to design your types so that Rust can check that. For example, sometimes I have to do something like "make sure the dialog box is wide enough that it doesn't truncate the title string on any relevant platform." The Rust type system has no way for me to query several versions of macOS and Windows about when they start truncating dialog-box title strings and size my dialog that way, so here I am, still performing this task by trial-and-error, waiting forever to compile my code each time.
Nothing about this is Rust-specific by the way. I'm similarly bearish on statically-verified cross-platform dialog boxen in Haskell. And that's one of my dumber "make it look right" tasks - I work on CAD software so most of them involve 3-D graphics and/or computational geometry.
And, returning to the parent comment, waiting for C++ to compile in order to test things is a giant fucking time-sink and drain on my productivity. It can't really be automated, or, if it can, it's way beyond the reach of this organization's know-how.
In summary, I call bullshit on static verification replacing snappy trial-and-error in the UI / Graphics space. In practice, you're left shifting UI / Graphics customization out of the host language and into "content" so that you can tweak it without re-compiling. But this is another massive fucking time and complexity sink that only exists because at some point you let your compile-times get so far out of control that your people couldn't do their job ("make it look right") in a reasonable amount of time.
I used to be the kind of dev who compiles every tens minutes. The thing is, on Android compilation time are just getting larger and larger. Anecdotally, this is not because the tooling team is not interested in build performances, on the contrary they continuously work on it. However they are currently losing the battle : the median app complexity is growing way faster than they are improving the build times.
I mostly got used to it. I can write code for a whole day and only compile once or twice. The more I am accustomed to our ecosystem and codebase, the less I feel the need to compile frequently.
The only exception is for graphics code. The only way to know if something looks correct and good is often to compile. For that reason, while I still love writing polished animations, I dread having to compile 10 times in a row to get it just right.
The latter. Validation/type checking is super quick. It might slow down a little bit if you do a lot of compile-time processing via macros, etc. IDE support is also improving a lot, and many Rust devs use an experimental component known as rust-analyzer to do the IDE-based validation you're talking about.
And if you can write program in very fast language, why not? There doesn’t have to be need. Just no reason not to
I just don't agree with statements about memory safety and speed. The thing is much more complex. I think simply stating "Use the best tool for the job" is much better than showing bad examples.
Because everybody needs memory safety and wants speed. Nobody wants to write unsafe slow programs (Well, I HOPE). Nobody wants to drops either of those requirements. When you drop those requirements, it's because of tradeoffs (I think memory safety shouldn't ever be dropped, yes use GC lang if you want to, but in 2020 memory safety should be a very hard requirement)
I am interested in how you got that impression, because at least in our official surveys, it's often one of the most-requested improvements to Rust, and it's something that we're constantly working on improving. Still a ton of work to do though!
For what it's worth, my workflow is closer to yours than "compile twice a day." And if you're using rust-analyzer, by default, it compiles the code every save!
I hear you can get this working with vim/neovim but I haven’t done it myself.
I have therefore developed a reflex where I hit Cmd-S every time I finish typing. I actually have to put conscious effort in to stop this when using software where saving is slow.
I love rust-analyzer! But I'm not sure what you mean by "it compiles the code every save." I love how fast it can type-check my code, but I was unaware it could actually compile my code into something I can run? I thought it was just a LSP provider.
Before we get into that, to answer the other question:
> But I'm not sure what you mean by "it compiles the code every save."
Rust-analyzer (by default) will run "cargo check" on save. cargo check does everything except codegen, so it won't give you something you can run, but it does invoke the full set of compiler analyses and everything else.
Now, what it does with the type-check stuff is the key to understanding what you're missing from the compiler team roadmap, funny enough. So rust-analyzer is actually going to end up merging with the rustc codebase eventually, if all things go to plan. Basically, rust-analyzer is slowly re-implementing the compiler from the outside in. It's doing this because the best way to get the largest win on compile times is to completely re-architect the compiler. This comment is too long, so I won't get into too many details, other than to say that it's going to be less like the Dragon Book and more like C#'s Roslyn, if that means anything to you.
It's doing this by taking advantage of a process called "librarification," which is extracting stuff from the compiler into re-usable libraries. You can see this on the notes when they talk about chalk; chalk is the next-generation trait resolution system. This is integrated into rust-analyzer, and into the compiler. So slowly, bit by bit, things are being re-architected and integrated in a way that will be much, much better in the future.
So this is a massive, massive project that touches everything, and so there's nothing spelled out in the minutes that says "this is for compile times" because the folks involved already have this context, basically.
And so yeah, that's the big project. There are also contributors who, while this larger work is going on, are working on individual PRs to make things faster. See https://blog.mozilla.org/nnethercote/ for one of the largest contributors in this regard, that talks about the work he's doing. But that doesn't appear on this either; there's no need for a plan or coordination here.
... does that all make sense? I am thinking maybe it would be good for us (to be clear, I mean the Rust project, I am not on the compiler team and am not doing this work) to like, actually write a blog post on all of this...
If rust-analyzer will eventually introduce those gains to rustc, that is fantastic news, and I'll be watching it with great interest! The improvement from RLS to rust-analyzer is exactly the type of improvement that brought Rust from the "fascinating tech demo" to "I could actually see myself using this day-to-day."
And yeah, I'd love to read a blog that went into more detail.
> working on individual PRs to make things faster. See https://blog.mozilla.org/nnethercote/ for one of the largest contributors in this regard
Yeah, I read through that too. He's my hero! :-) But the feeling I got when reading it was: "fast compile times" really need to be part of the DNA of a language. Let me explain what I mean. Some languages, like Go and TypeScript, have this in their DNA, and that means that every design decision and every addition to the language is considered seriously through the lens of compile time speed, and vetoed if it were too costly. But with Rust, the fact that there's one guy writing a blog post about some incremental wins he managed to chalk up just... doesn't seem like it's part of the DNA. If it is, why is it just one guy, and why do a lot of his changes seem more like incremental wins than the big sweeping changes I'd expect to be necessary? I could definitely be wrong here (sounds like I am and rust-analyzer is that big sweeping change).
Thanks for all your great responses, by the way. I really appreciate it!
Any time. :D
A couple more brief comments:
> rust-analyzer seems to me to be a LSP
Remember that LSP is a protocol, something/someone has to actually figure out the answers. Like, the LSP says "please draw the squiggles here", but something has to actually say "line 1, column 10, please". Doing that involves semantic analysis, which is what a compiler does.
> And I thought that codegen and linking was the slow part in Rust
It is the slowest part of the current architecture, but that doesn't mean that the current architecture is the best possible one.
The RLS invoked the compiler, and then examined its output to say "line 1, column 10, please". And you said you saw the improvement with the architectural switch to rust-analyzer. Same thing.
> "fast compile times" really need to be part of the DNA of a language.
You are correct that, when push comes to shove, if there's a tension between, say, runtime speed and compile-time speed, Rust will choose runtime speed. Rust will not have compile speed as high up on the list of concerns as Go does. But it is important enough that we don't let major regressions happen, and actively pursue improvements where possible. https://perf.rust-lang.org/ for example, tracks this data over time for this kind of reason.
> why do a lot of his changes seem more like incremental wins than the big sweeping changes I'd expect to be necessary?
Well, again, it's not always either or. He's doing the incremental thing, and others are doing the big sweeping changes thing. His improvements land nearly every release, but the bigger projects take a lot longer. They work in tandem to make things better than they were before.
Confusing since this is, to my knowledge, a top 3 issue just about every year.
That said, I think Rust programmers dislike compromise (maybe to a fault). Rust is naturally a 'have your cake and eat it to' language and the community very much likes to be best-in-class, so compromises on runtime performance to improve compile time (which is one way you can go today) are often not seen as viable by a large part of the community.
For what it's worth, I think I've called out compile times as probably one of my top issues with Rust, working on a fairly large and quite dependency heavy codebase. It isn't a deal breaker for me by any means, but it's a pain.
Typically this tension would be resolved with o-level flags (O1, O2, O3...).
Sometimes, non-release builds are too slow to meaningfully run. It is not uncommon for release builds to be extremely faster than debug builds.
That being said, I'm not aware of it making any meaningful difference.
O1 vs O3 is probably a fair way to do things. Some people will do that for debug builds, to get a mix of reasonable performance (for tests) and reasonable compile times. I'm not sure how meaningful the difference is going to be between O2 and O3, it's been a long time since I'd looked into it, and back then O3 wasn't really a thing people did.
> I've often wondered how this can be possible, given that to me it's such an obvious glaring issue that all the other cited problems are distant distant seconds at best.
It's amazing how little I understand your point of view. And I'm being genuine and not critical of you at all.
To me, all of the features of the language, from move semantics, to ergonomic sum types, to nicer error handling (to me. I know it's debatable), and great runtime performance are so important, and bring me so much more peace and joy while working that compile times are literally not even on my radar. I simply don't care if they ever get better (assuming that effort is being put elsewhere. I guess if the language is "done" then work on the compile times is appreciated).
And I've certainly done real work in languages that compile fast (Go, Java) and languages that don't even compile. They always made me so much less happy because of the languages themselves just not clicking with my mental model of problem solving. Again, compile-run feedback loop just had nothing to do with it.
All that said, I use Rust Analyzer for code completion and it's generally fast enough. But it's still sometimes has a noticeable stall. That's not my favorite and it's kinda related to compile times.
Just really amazing how different people using the same tool have such wildly different modes of interaction and perceptions. Cool stuff. Cheers!
I think our difference is I spend a lot of time on graphics and games, where there's a lot of manual tweaking that you have to do. (Is 20px far enough? 25px? Is 1 second long enough for the explosion? Maybe 0.5s instead?) There's just no way to test it outside of rerunning the app.
> One group loves fast compile times and quickly validating hypotheses
In Rust, it’s sufficient to type check (if it type/borrow checks, it will probably work) and Rust can type check in real time via rust-analyzer. This is much faster feedback than running your program or even its tests.
Of course, Rust’s type/borrow checker is also choosier than many others, and you still spend more time fighting with errors that don’t actually improve your code’s correctness (e.g., borrow checker errors are rarely indicative of a bug in a single-threaded context). So Rust’s iteration loop is quite fast but it’s development velocity is still relatively low (even when adjusting for quality), but it’s improving all the time.
```
[target.x86_64-unknown-linux-gnu]
rustflags = [ "-C", "link-arg=-fuse-ld=lld" ]
```
`-Clinker=clang` also works. I think you need a recent `gcc` (8 or newer) for `-fuse-ld=lld`. For `linker=clang` you probably need `clang` installed.
Permalink: https://reddit.com/r/rust/comments/dsfi5m/rust_2020_are_we_c...
Does Rust have anything that prevents it from being run interpreted?
You can find how to install and use it here: https://github.com/mozilla/sccache
The project i'm working on now takes ~8s to compile. Perhaps too slow, but i guess it just doesn't bother me. Though i definitely want to see it improve for wider adoption, as it's clearly an issue for many people - I just have difficulty feeling the pain in this case, i guess.
edit: I imagine i compile once every 5 min of code writing. Varies by problem solving of course.
Interestingly, my case is the exact opposite. When I am coding in Typescript or Python I'm out of place, since I got used to first write the types to make sure everything is aligned, _and then_, start writing logic...
Even in Typescript this workflow is not easy to do, since its compiler is nowhere as powerful.
I see comments a lot about "this is too slow" but rarely are numbers provided, neither the actual times nor the expected times.
You may have something setup wrong and are seeing unusually long compile times. Or your expectations may not be realistic. Or you're just an outlier whos work triggers some pathological compile issues.
But without data, we can't know what's going on.
10 seconds is basically as slow as I'd accept. I wouldn't love it, but I'd suffer through it if I had to. But what I really didn't like was that my feeling was it wasn't the bottom - adding more deps or more lines of code looked like it would continue to increase the time without bounds.
I like doing a lot of game dev and graphical work, and it often requires really rapid iteration to test small changes. (How fast should the AI walk? Should he turn around at this point? Does this logic "feel right" like this, or do I need to trigger it conditionally?)
On the technical side, there are definitely some learning curves among Rocket, Diesel, and other tools. A typical example is that different crates have their own implementations of concepts such as a UUID, and the developer must handle conversions, and also ensure that various dependency versions all align, and also can't (yet) easily use the current UUID crate, and also can't (yet) build using stable Rust. All of these aspects will be fixed soon, likely within a month or so as the crates stabilize.
If you try Rust, I highly recommend trying rust-analyzer, which provides near-real-time code advice as a plugin to most major editors.
So far we've seen about 2/3 of nights fail for our code. The failure is totally obvious. So we revert to the previous night that we know works.
Also, for the love all that is holy do not publish a crate relying on that flag to enable the nightly features, it breaks the languages stability assurances and by extension the ecosystem.
I believe Diesel has been on stable for a long time now, so for this use case I don't think anyone will need to worry about using the nightly releases.
Rustup makes having nightly and stable in the same machine painless, and I got in the habit of running cargo +stable build and cargo +nightly test. BTW, you don't have to do this, it just makes my experience a bit nicer.
However thus far we have never had to push a release due to a bug found in nightly. We also have never had a build break because of nightly, or even upgrading.
The only breakage i'm aware of was, oddly, a semi-recent Rustup change. Our CI was not pinning the Rustup version, and the argument defaults changed so the downloaded Rustup did not have the components needed for our CI setup.
We will however migrate to stable once Rocket becomes stable. Thus far however, we've not had any trouble on nightly. I can only assume this is a result of the Rust teams excellent QA/tests/care/etc, combined with the language itself being very easy to write error-free code.
While I am not a huge fan of Typescript, at least libraries are readily available and generally easy to use. On the other hand, being able to show that we are able to do monitoring, user auditing, ORM, opentracing, gRPC-web with Rust is non trivial.
Now that I think of it, being able to do a "hello world" on any language is pretty simple. But having all the tools around it to build a production level service is a different story.
1. C#'s AsyncLocal has made a few things simpler to trace SQL queries to a request.
2. We chose to use hapi.js some 2 years ago, because we found the interface superior to Express, but I did not expect the sole developer of hapi.js to decide stop working on the project [1], and left my head scratching on what I am going to do about that.
3. TypeScript's interface sometimes feels too much like just "suggestions", and every once in a while run across scenarios that are not fully supported. One that I really dislike is that Sequelize's "where" options has no type support for the model. [2]
4. Sometimes libraries does not use async correctly, and breaks stack traces.
5. Sometimes TypeScript's generic errors can be as bad as C++.
My favorite feature of TypeScript is being able to just define types/objects in-line, but I actually like to stay on the side of caution and stability on a large project with many people.[1] https://github.com/hapijs/hapi/issues/4111 [2] (GitHub is down, or I would grab the link)
For example we used SOHU-Co/kafka-node for a while as a kafka client, until we hit some bugs that made us dig through its internals and we realised it had some deep issues. We then switched to kafkajs which turned out to be much more mature and polished, even though it was less "popular".
Sequalize in particular I think was developed in an era before TypeScript was a thing so it follows the ideals of that time, more in line with Ruby and being easy to use and malleable. We switched to using slonik for our query needs, with a more declarative and static approach, skipping ORMs and query builders altogether - just raw strictly typed queries. I think in the end its a better approach for our needs.
I guess what I'm trying to say is that TypeScript was built to be able to handle _all_ of the weird and wonderful world of JS from its most amateurish and fun, to its most solemn and strict. And it's just a matter of picking up where on the spectrum you want to operate and make your dependencies match that vibe. It's limiting and freeing at the same time.
I feel like I have been to hell and back with ORMs, between Sequelize, Entity Framework, Hibernate, SQLAlchemy, etc.. and frankly, I think they just cause more headaches than solve problems.
I would love to have strongly typed SQL queries, but I have found that Dapper [1] fills a special place in my heart.
Even if you later on decide that the Rust implementation is not production-ready, you can draw conclusions from the project, and the next time someone considers Rust for a bigger project, there is a member on the team who can provide insight into potential issues. Of course, the project would have to be sufficiently small to not waste too much time.
I don't think a strong enough argument can be made. I'm sure you CAN write web services in Rust, and that in very specific cases it'll have some benefits over Node, but honestly very few people work in an area like that.
Disclaimer: I've settled on using Go to rewrite an existing application. The original app was written in PHP; nothing wrong with PHP per se, but the existing codebase is a mess and the PHP version is hard to keep up to date because of LTS versions of operating systems + very slow and careful updates at our customers (it's network infrastructure). For me, switching to a compiled language that produces a self-contained executable was a compelling argument. I have to admit that I do kinda pine for something like Java again though.
The over-engineering in the Java ecosystem has wasted more of my time than saved it.
Having worked with Spring for years (and still working with it, unfortunately), I have found exactly the opposite.
It does way too much dynamically, making debugging hard and rendering the type-system almost useless.
Sure, it comes with a lot of libraries for handling a large varieties of tasks, but they all seem to be half-assed, and much of the time I either have to work around their limitations or write something myself anyway.
I really don't see why the same thing couldn't have been achieved by writing a bunch of useful libraries that don't depend on a dependency injection framework (which I also don't find much value in).
Finally, it takes forever to startup, making testing a pain. It even means that JUnit tests are slow.
That over-engineering is what save us from clunky solutions that are good for hello world applications and HN like posts, but fail when doing deployments across heterogeneous platforms on Fortune 500 IT departments with endless number of external contractors and technology stacks hardly seen elsewhere.
And if I have to pick between managing WebSphere containers and taking care of k8s, I will rather pick WebSphere.
As such, I'd describe it as a good combination of highly dynamic architecture with lots of manual control. Of course, all of this is enabled with copious amounts of magic, which is usually why people don't like Spring.
I would prefer languages that don't dictate what hardware/software to use for writing them.
On Windows with luck 5.3 will be the first version that the compiler actually works, let alone existing libraries that barely work on Linux.
If you have some interest in Rust, that’s what I’d personally recommend instead of migrating an existing service to a different language.
Personally I don't see the point to implement a typical web application in Rust - the performance improvements you get will be lost on IO-bound applications, but you'll still be saddled with the complexity of the memory management. I'd rather suggest to rewrite VS Code or the Slack client in Rust (i.e. apps which currently use Web technologies on the desktop) - those would definitely benefit more from increased performance and reduced memory footprint...
Performance starts mattering even in IO-bound applications as soon as you're trying to seriously scale out. Especially when running on a cloud-based platform. As for "the complexity of memory management", people like to bring this up about Rust but OP suggests that it's not a huge concern with the language.
I do agree that rewriting stuff like Electron-based apps should be a priority, and that Rust can help this via easy bindings to native OS and GUI platforms.
It is not a trivial problem to solve (as you claim), otherwise we would have never needed the borrow checker to avoid memory bugs, nor higher level languages to speed up development by avoiding the problem altogether.
If you are going to end up sprinkling clones, heap allocating and reference counting, then you could have used C#, Java or JS to begin with which are plenty fast with their JIT/VMs and not think about memory at all.
Finally, comparing against Python is a very, very low bar for performance.
The memory management system isn't Rust's only good feature. I and others enjoy Rust's type system and functional features, for example.
Using Rust also makes it easy to get performance for when writing the parts for which you need it.
Regardless, there are other languages with better type systems and functional features.
> what other features would make me pick rust over golang Generics, iterators, pattern matching, etc. There's lots of features Rust has that golang doesn't; that's not necessarily a good thing but for what I do it is. IMO the only good thing about golang's featurelessness is the compile times and the standard library.
As for interpreted languages, IMO it's just better to be able to catch errors at compile time.
Fair enough. But I'm not advocating using C here either.
> As for interpreted languages, IMO it's just better to be able to catch errors at compile time.
There are type checked and interpreted languages.
I am going to disagree here, because I've run into my share of memory issues in Python and C#/F#, and I'm sure by this point, everyone is well acquainted with Java's memory issues.
> It is not a trivial problem to solve (as you claim), otherwise we would have never needed the borrow checker to avoid memory bugs, nor higher level languages to speed up development by avoiding the problem altogether.
I'm not claiming that memory management is a trivial problem, I'm saying the borrow checker takes care of enough and the compiler/clippy hints when I do something wrong help me fix it easily enough. I write code slightly slower than I would in Python, but at the end, what I get from the Rust code is something that is more robust and more hardware efficient.
> If you are going to end up sprinkling clones, heap allocating and reference counting, then you could have used C#, Java or JS to begin with which are plenty fast with their JIT/VMs and not think about memory at all.
Rusts type system is enough to make me want to use it over dotnet, JS is a language with...some issues...that is fortunate enough to have a nice JIT, I consider it a serious choice for doing anything except web front-ends. I find C# needlessly convoluted and I dislike all the implicit mutability, but those complaints are very subjective.
The difference is that even if I have some clones and ref counts, they're rare, and the resulting binary is still outrageously fast, and has clear indicators of where to come back to and improve so as to not need the clone/reference counting/etc.
> Finally, comparing against Python is a very, very low bar for performance.
I compare against Python because that's the other language I do most of my work in.
In Python, C#, Java, JS... you are memory safe without dealing with memory management nor a borrow checker.
There are many languages running on top of those VMs for all kinds of tastes (OOP, functional, strict type systems, loose ones...). Claiming Rust leads to more robust software than any of those is an exceptional claim, but even if that were true, the key is the development cost.
Whatever language you're using, you probably should care a little bit about your memory patterns.
.NET Core just recently last month that gRPC-web is stable [1]. It would remove a huge amount of boilerplate in setting up services on both client and server side.
Some people also recommend to use Envoy [2], but usually the less cogs the better.
[1] https://devblogs.microsoft.com/aspnet/grpc-web-for-net-now-a... [2] https://grpc.io/docs/languages/web/basics/
If you're doing image processing, you may want to have node.js do the user interaction bits, and have the sophisticated image processing in Rust.
But I don't really see Rust as the go-to platform for crud APPS with DB access etc..
https://rust-lang.github.io/async-book/01_getting_started/05...
My server processes JSON requests and returns JSON and also serves a couple of static files that I simply read with
include_bytes!("../files/index.html")
Once you understand Rust async model (which I recommend as a mental exercise for any programmer), it's all very simple.Remember the mantra from the 2010's when the dynamic typing craze? Rust is not about optimizing developer time, it's about guaranteeing safety for base sysstems software.
All this permanent reasoning about ownership, borrowing and so on makes it the greatest contender against C++ (hence Mozilla and Microsoft support) but in terms of productivity you'd be best served with a higher level, GC-collected platform for an application.
Yes, but it's a papercut. How many other papercuts are there, compared to more developed ecosystems for this domain? That's not an easy question to address.
Granted, it's more than enough for a lot of use cases but it wouldn't seem to me like the most appropriate approach for, say, and e-commerce platform in terms of maintainability and time to market. Of course, the performance speedup would be huge on the other hand.
But then you have also stated the point: systems language, which is the perfect use case for Rust. The original article talks about a "server language", as in application server, and my whole point was that for building business applications this is a weakness, not a strength.
Honest question: how many hours would you say it took you to grok the ownership/borrowing stuff and then reason about it in a natural way so you were as productive as with the language you were coming from?
I’m not saying having to reason about ownership is bad, I’m just saying that this is not a good test for whether ownership reasoning is difficult or not.
So I wouldn't describe Rust as a language that fits all domains and/or programmers well.
Rust is a language for memory management. There is no way to write code in Rust without thinking about memory.
You don't have to think about this with Rust - and you don't need a GC either. The borrow checker will make sure that your closure doesn't outlive the variables it captures, which is what you need for correctness in this case.
No, the borrow checker will merely give you an error when your closure may outlive the captured variables. This is often not useful, and is an impediment to being productive. As a programmer you don't want to be solving the same boring problem of memory management over and over again, unless perhaps when you're doing really low-level stuff and there is no other option.
How is it "not useful"? It's generally quite easy to resolve the ensuing lifetime problems: either use .clone() to copy the underlying values, or use Rc<>/Arc<> to provide shared control of the lifetimes involved. And it's far from a "boring problem"; quite often, being aware of how and why lifetime and mutability interact at a "low" level can inform higher-level design as well.
And yes, in probably 99% of cases you can actually find a way out of a memory management problem in Rust if you think hard enough.
But my point is that quite often you don't want to think about memory management. Rust doesn't help here. Rust advertises that it solves memory management problems, but in reality that only holds up to a point. So use Rust for your OS or your low-level server, but don't think it is a panacea.
In that case, you can manually lift the data object involved into a function argument, as opposed to a variable capture - with its ownership being thus managed explicitly. This is generally an improvement in design.
Of course, Rust does only solve memory management problems "to a point"; there are cases where fully general GC is pretty much a necessity. But even most uses of closures - a fairly high-level language feature, all things considered - don't require this in many cases.
Discussion of this article on /r/rust: https://old.reddit.com/r/rust/comments/hpzmeu/rust_is_surpri...
Async/await is a huge improvement over callback hell, but this doesn't fix everything. The "function color" problem still exists [1], and seems to be more than binary in rust. This quote from the article is incredibly sad: "each async library, comes its own ecosystem of libraries, which only work with that async library".
Rust is ground breaking in some areas, but also completely lacks innovation in others.
But is it actually _necessary_ to resort to async I/O in Rust, given that the type system appears to make thread-based concurrency safe ?
[1] https://journal.stuffwithstuff.com/2015/02/01/what-color-is-...
Already in Rust many libraries can be written completely agnostic of the underyling executor. Some cannot; we have a bit more interface work to do, but there's nothing inherent about this, it's solely a standardization issue that's being worked on. Sounds like they ran into the latter more than the former, which is unfortunate, but should be better in the future.
> But is it actually _necessary_ to resort to async I/O in Rust, given that the type system appears to make thread-based concurrency safe ?
It is not!
As strongly suspect it will perform "well enough" (hopefully much better than async in Python, and hopefull javascript too), which is good enough for me to be able to escape async.
Having to write async versions of the sync APIs doesn't need to be the case: https://docs.rs/smol/0.1.18/smol/ lets you use blocking APIs in async contexts without blocking (by dispatching them to different threads). What the ecosystem is seeing is a few different projects trying things out in different ways to explore the design space. This is not necessarily a bad thing.
> Rust is ground breaking in some areas, but also completely lacks innovation in others.
Other than the borrow checker Rust is a very boring language for language designers. That is intentional :)
> But is it actually _necessary_ to resort to async I/O in Rust, given that the type system appears to make thread-based concurrency safe ?
async/await lets the compiler perform some extra inferences on how you're using your data, which makes writing an `async fn foo();` much easier than `fn foo() -> impl Future;` if you are dealing with borrowed data. Of course, the same underlying threading primitives are still available to use.
> The project is simple enough that I can't imagine being too limited by any language's ecosystem. And I've been itching to write something substansive [sic] in Rust...
Rust has the advantage that when compiled to WASM it won't require a runtime library. So the prospect of Rust as a fast, low overhead, use anywhere language is tempting.
Since Rust is a relatively new language it's worth checking to see how it's maturing over time against small low risk projects exactly as the author has done.
Rust may not be a perfect fit right now but that may change. So it's very valid to test one's assumptions from time to time.
Or to put it another way, working in one of the languages you've mentioned wouldn't answer the question "how suitable is Rust for web server work right now?"
Nevertheless, WASM is not ideal for server work. It is intended for the frontend.
I'm not suggesting that you would use WASM for server work at all.
I'm suggesting that Rust would be interesting for WASM on the frontend because it doesn't depend on a runtime.
Given that you might want to use Rust for WASM you may also want to use it on the backend (that's without using WASM on the backend).
The assessment of Rust via small projects says nothing about the suitability or not of C or any other language.
It's just about the suitability of Rust right now and how it's changed from the last time you assessed it.
In particular, even having a relatively small set of feature requirements it has been difficult finding a web framework that supports: Middleware, Websockets, easy routing, and async handlers.
Actix probably supports all of those, but I don't much like development in it and prefer to avoid the drama of Actix. Surprisingly, none of the other libraries I've looked at support all of those (except possibly Gotham, but I ran into other issues with it).
I'm not sure what my takeaway is, other than that web frameworks still have a ways to go, and development on each of these web frameworks seems slow, I think because of the lack of companies picking them up. I also get the impression that people are somewhat obsessed with doing it the "Rust way", rather than just getting a simple completed web framework out the door.
However, I love working in Rust, and think I may reach a point where I'm actually more productive in it than something like Typescript. There's just a large learning curve. But it's fun.
on tag page it’s possible to see drafts :)
1. You don't need CPU performance for most web stuff. It's all IO bound.
2. Related to #1, garbage collectors are fine and you don't need the Rust model.
3. Rust is so hard to learn that it isn't worth it unless you need the performance.
There's so much more to Rust than the performance. It hits a really nice sweet spot between being expressive and letting you take as much control as you want/need.
Sometimes GC'd languages are a pain in the butt because I just want a damned destructor and I would like to be able to guess when/if it's gonna run.
And, frankly, Rust isn't that hard. It's an imperative language. It's not Haskell.
Sometimes, it's convenient and easier to reason about stuff when you can predict when something is actually dropped from memory.
And in Rust, you wouldn't create those memory bugs you're worried about. (Well, you can, but you have to go out of your way to take the safety off :)) That's kind of Rust's whole "shtick"
That's a bigger problem for server applications than CPU / Memory performance issues, because the latter can be traced more easily.
As a (mediocre) dev and head of a team (some are great, and some are as bad as me), I'm far more worried about bugs than performance.
[1] https://stackoverflow.com/questions/55553048/is-it-possible-...
A reference cycle with `Arc`s can happen though.
But if you're talking about Java and mediocre devs (I'm in the club- don't worry), I feel like there are no shortage of ways to make bugs with null, concurrency issues, etc, that Rust completely eliminates. You can make reference cycles in Rust, though.
Also, in Rust code you often don't have references to references to references the way you do in Java, so it's just not an issue that I'm aware of having had yet.
It's an alternative to a myriad of small, unaudited libraries. Rust does have some projects going to audit those small libraries, though.
His last example could be improved a lot with the "?" keyword. That would remove lots of wrapping and simplify the code greatly. So it's not that bad really.
Pick one you are familiar with, the language the toolchain and the overall ecosystem, it should just work.
https://vo.codes is a text to speech service written in Rust and it performs really well. Any service failures are simply my poor proxy implementation - the core TTS service itself scales very predictably.
A bunch of mostly static blogs can be hand-edited HTML, or some ancient perl script, or any of the existing static site generators.
If it absolutely needs to involve server-side logic, it could be completely accomplished within a single call to ```rails init```, and the resulting project would incorporate a few $billion worth of collective experience commonly refered to as "best practice". It would be far easier to modify and far less likely to contain vulnerabilities. Performance would be worse by a factor of maybe x100, or "why are you asking these weird questions?" when converted to the real world, according to a representative survey of end users.
There's a good argument for replacing individual components on, say, the critical path for rendering people's twitter feed with lower-level implementations.
But it strikes me as unlikely that such endeavours would care about the ability of their ORM to quickly generate the migration scripts to drop or add some database columns.
So I can't quite see the benefit of cramming the rails model into Rust? Rails is spectacular in how it allows you to quickly iterate, adapt your data model, try some ideas, and so on. Those are qualities that just logically do not transfer to a world of static typing and manual memory management.
But if I ever have to write a small (in terms of requirements and potential LOC, not load), atomic, CPU-bound microservice that will probably not require a lot of maintenance work, Rust will be my first choice.
In Rust, you can define such boundaries, and manipulate things like configuration when you’ve decided you want them to be modifiable, perhaps within a debugger, or more likely via some exposed API (maybe a web API).
To be sure, Rust is less flexible: all such extension points must be designed in, rather than often working by accident (though the Python way is very likely to blow up in your face from time to time).
But in the end I don’t think it’s such a big difference.
(On reflection, I suppose I have seen a debugger used in the scope of a particular request within Django, to give you a pdb prompt instead of just the 500 error page. But that’s then just used for inspecting what’s broken, and most such brokennesses would have been caught by the Rust compiler. Still, something equivalent to that could be nice to have in a Rust development web server; I don’t believe any such thing exists at present, but it could in theory and might be interesting to make. It would still definitely be more limited than pdb. Maybe when we have a Miri-powered REPL something interesting will happen in this space. It’s not a fundamentally impossible space.)
¹ If that works, by the way, you should set up the cached template loader, as it’ll speed template rendering up a lot. That used to be something you’d have to do manually, but now the default template loaders configuration includes caching if debug is False.
why restarting ? when you can reload the new code of the app while it's running ? no service interruption worked for us for years ! but yeah, I agree, better having 4 eyes while patching on prod :)
One major issue with Ada is that commercial grade compilers are not cheap and for the most part the language was unable to get rid of the stereotype of being an Aerospace/Defense language only.
Some discussion on the topic:
https://www.quora.com/How-secure-is-Ada-the-programming-lang...?
https://en.wikibooks.org/wiki/Ada_Programming/Types/access
More importantly the previous discussion on Ada SPARK 2014 'safe pointers' may also be an interesting read for proponents of a Substructural Type System:
Its production ready.
[1] https://marvinblum.de/blog/how-i-built-my-website-using-emvi...
So that's one answer: forcing yourself to learn more about a languages environment and ecosystem.
Another answer might be: "I already know/prefer rust."
I'd be surprised if there were much/any performance benefit.