Java is on crack



  • @Gąska



  • @HardwareGeek It should be noted though that some have already reported success gradually rewriting things from C or C++ to Rust, module by module. Or sometimes from other languages too. Creating a module in Rust that provides interface for C, C++, Python or other languages to call is relatively easy, so you can rewrite a problematic piece in Rust, connect it back into the product and release a new version with bugs fixed in a couple of months. And then do another bit for next release. It's been happening with Firefox for last two years.


  • Banned

    @levicki said in Java is on crack:

    @Gąska said in Java is on crack:

    @levicki less bugs.

    Do you honestly believe that bugs are caused by the language and solved by using another language?

    Normally - no. But if the another language in question is Rust - yes.

    Because that's the most idiotic claim I heard in the last 35 years.

    Maybe you should update your knowledge.


  • Discourse touched me in a no-no place

    @Gąska said in Java is on crack:

    Normally - no. But if the another language in question is Rust - yes.

    That's an interesting language. It wouldn't make much impact on us as most of our developers are pretty good at C, but for one of our team it would help him a lot as his C is pretty horrible. (He's good at working out what needs to happen, but terrible at writing that as comprehensible C code.) Perhaps I ought to tell him about it. He gets to figure out how to make it work with the rest of our toolchain though. 😉

    I do worry about how large the Rust runtime is. Occupational hazard when dealing with very small systems I guess. (It's that sort of concern that is why we don't use C++, for example.)


  • BINNED

    @levicki said in Java is on crack:

    @Gąska said in Java is on crack:

    @levicki less bugs.

    Do you honestly believe that bugs are caused by the language and solved by using another language?

    Absolutely yes, they are. Not all bugs, of course, and the old "you can write FortranJS in any language" applies. But if the language is designed to prevent a certain class of bugs, well, you won’t have those.

    Because that's the most idiotic claim I heard in the last 35 years.

    YMBNH


  • Considered Harmful

    @dkf You can cut out the majority of the stdlib with #![no_std], which you'd need on an embedded target anyway.



  • @dkf said in Java is on crack:

    I do worry about how large the Rust runtime is. Occupational hazard when dealing with very small systems I guess.

    Rust runtime is split in three layers—small core with the language items, collections with the generic collections and other utilities that don't interact with outside world, but do need dynamic allocation (which was split in a separate helper library so you can replace it), and std with the full OS interface (and re-exports of the lower layers). Since very small systems usually don't have normal OS interface anyway, you can use just core and own slimmed-down support library. You have to be careful with the generics though, because they do tend to inflate the code (as they do in C++; Rust has much less implicit stuff though, so you have more control over where the costs may be).


  • Discourse touched me in a no-no place

    @Bulb One of the main reasons we gave up on C++ was how horrible it gets when you've got two memory allocators (which we do; one for fast per-core data-only memory and one for slow “global” memory). And some of our binaries run super-close to running out of space, both for instructions and data. It's fun, but super-constrained in ways that modern programmers aren't used to.

    Though things are not quite so bad as they used to be. There was stray floating point code in there, and that stuff is bloated as heck (on the target platform, which doesn't have hardware float support). And we found a way to compress the logging so that it could be left on (and that's helped a lot with most debugging, except when it doesn't).


  • Discourse touched me in a no-no place

    @pie_flavor said in Java is on crack:

    @dkf You can cut out the majority of the stdlib with #![no_std], which you'd need on an embedded target anyway.

    That's just like building C in freestanding mode. 👍



  • @dkf said in Java is on crack:

    It wouldn't make much impact on us as most of our developers are pretty good at C

    It might. Even if you are good at C, a memory error will occasionally slip you and then you need good static and dynamic analysis to catch them, and Rust basically has such static analysis built in.

    And while the borrow checker was originally designed to prevent use-after-free, with the right abstraction it can also check that you lock all memory you mutate from multiple threads and that you only touch resources from the module and thread designated for it. You have to put more care in designing your scoping, but it then results in code that is easier to refactor, because the language checks the thing you are refactoring is not used from anywhere else.



  • @levicki said in Java is on crack:

    Do you honestly believe that bugs are caused by the language and solved by using another language?

    They are not caused by the language, but they are allowed by the language. Using a different language will not make your code magically work, but it can protect you from making some mistakes or make their consequences less severe—in a strongly typed language you can't have a buffer overrun, in a managed language you can't have use-after-free, in a language without shared memory between threads you can't have data races etc. And these are the kinds of bugs that often create security vulnerabilities, so even if you still get the code wrong in the safer language, at least there will be fewer vulnerabilities (not none, because no language will save you from failing to authenticate the user—though a good framework can help with that too).



  • @dkf said in Java is on crack:

    One of the main reasons we gave up on C++ was how horrible it gets when you've got two memory allocators (which we do; one for fast per-core data-only memory and one for slow “global” memory).

    I've seen mention of a Rust framework for compiling to that kind of architecture. It built the code for each core separately and used some linker tricks to put static variables in the right pools depending on whether they were shared or not.

    It's been a couple of weeks, so I thought it might take some time to find, but my browser remembers it well, so here: μAMP. The test target is Zynq UltraScale+ EG, which has two equal cores, but it is designed for different cores (but not sure how far he got with testing in the month since that post).

    He also has other embedded-related stuff, like an abstraction for checking access to mmio ports—Brave new I/O—which is a nice showcase how good abstraction can utilize the Rust rules to catch bugs (it should be noted that that post is still using the prototype async support, but it's just about to land in stable with slightly polished syntax).


  • BINNED

    @dkf said in Java is on crack:

    One of the main reasons we gave up on C++ was how horrible it gets when you've got two memory allocators (which we do; one for fast per-core data-only memory and one for slow “global” memory).

    But that's explicitly supported by C++ (assuming you used the std lib to begin with, which I thought you don't). Granted, it's not particularly nice to use, but still easily beats C.
    You can also use C++ in freestanding mode like C and build some pretty nice zero-cost abstractions that compile to the exact same thing as the C equivalent would.

    I think I've linked to this before:

    https://www.youtube.com/watch?v=zBkNBP00wJE

    Although I guess Rust is indeed the better choice.


  • Discourse touched me in a no-no place

    @Bulb said in Java is on crack:

    It might. Even if you are good at C, a memory error will occasionally slip you and then you need good static and dynamic analysis to catch them, and Rust basically has such static analysis built in.

    And that's 99% irrelevant to us due to the weirdnesses of the platform. Most of our problems are to do with either the intricacies of instruction-level timing, or the challenges of the numerics. Occasionally we hit outright compiler bugs such as being unable to mix negation and multiplication (of fixed point numbers). Yes. :wtf:

    We also have complexities of how applications are loaded and simulation states are recorded that make how Rust handles memory safety really irrelevant. I wouldn't expect you to know those; our software isn't mainstream at all. Handling those all correctly (at the proof level) would involve extending the software checking to be defined across multiple computers connected by an unreliable network. And would involve writing maybe a few million lines of code, depending on verbosity; it'd be replacing a lot of Python code so we're talking a megaton of busywork…

    And while the borrow checker was originally designed to prevent use-after-free, with the right abstraction it can also check that you lock all memory you mutate from multiple threads and that you only touch resources from the module and thread designated for it. You have to put more care in designing your scoping, but it then results in code that is easier to refactor, because the language checks the thing you are refactoring is not used from anywhere else.

    That's entirely irrelevant to us. The application suite and hardware concerned have properties which mean that we're actively not interested in that sort of thing. (Basically, anything that's shared has a huge time penalty to use in ways where that sort of analysis would be useful. Instead, everything that you want to actively use is strongly bound to a particular CPU core.) I've said before that we're an unusual platform; that's not an idle remark…


  • Discourse touched me in a no-no place

    @topspin said in Java is on crack:

    But that's explicitly supported by C++ (assuming you used the std lib to begin with, which I thought you don't).

    We don't. It's all embedded systems work in style, and the individual cores are about the same scale as that C64. But with an entirely different set of peripherals. And an utterly different type of OS. And the application code is large enough that we've virtually out of headroom (high-quality RNGs are a bit large, as are the tables to support exponentiation and logarithms; the next-gen hardware will have specific custom accelerators for them).


  • Discourse touched me in a no-no place

    @Bulb said in Java is on crack:

    I've seen mention of a Rust framework for compiling to that kind of architecture. It built the code for each core separately and used some linker tricks to put static variables in the right pools depending on whether they were shared or not.

    Almost all variables are unshared. Shared resources usually act as either read-only resources (used to map incoming messages to descriptions of what they mean) or write-only resources (used to record traces of the simulation state). Except those are all actually unshared in practice.

    There's some real shared memory, but that's just used for messaging between application cores and the OS core. It's really small, and not available for general use.


  • Banned

    @levicki said in Java is on crack:

    @topspin said in Java is on crack:

    But if the language is designed to prevent a certain class of bugs, well, you won’t have those.

    "Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the Universe trying to produce bigger and better idiots. So far, the Universe is winning." -- Rick Cook.

    As I said, you need to update your knowledge. Also your quote list.

    In other words, you will just have a different set of bugs because it's people who are the problem, not the language.

    And this different set of bugs is very likely to be less fatal and easier to debug than, say, data races.


  • Considered Harmful

    @dkf said in Java is on crack:

    @pie_flavor said in Java is on crack:

    @dkf You can cut out the majority of the stdlib with #![no_std], which you'd need on an embedded target anyway.

    That's just like building C in freestanding mode. 👍

    Nope. You're left with core, a slimmed down version of the stdlib which still helps out in a lot of instances. Anything that doesn't require dynamic allocation, files, or OS utilities, core still has.
    Can't wait for alloc to be split out into a separate crate too for even better embedded stuff.


  • Considered Harmful

    @dkf said in Java is on crack:

    We also have complexities of how applications are loaded and simulation states are recorded that make how Rust handles memory safety really irrelevant

    I doubt that. Either you mean it heavily depends on memory fiddling, in which case Rust makes it really easy to move that into o a couple of functions and use a higher-level interface everywhere else that delegates to them, or you mean it's a much bigger concern which Rust can't address, in which case I would bet that there are applications for lifetime checking to guarantee correctness.


  • Discourse touched me in a no-no place

    @pie_flavor You've neglected to think that things might be arranged differently to what you are used to. Memory on these systems is not the same kind of resource that you have on more conventional computers, and the assumptions that a conventional OS like Windows or Linux apply are really not true. The system architecture doesn't prioritise process isolation, but rather insanely fast communication (and low power operation) provided you code it right.

    When you move to a truly different architecture, even pretty fundamental assumptions become really meaningless. Yet kicking those assumptions out is what you've got to do sometimes when working at the real bleeding edge.


  • Considered Harmful

    @dkf I didn't say anything about process isolation or Windows. :sideways_owl:


  • Discourse touched me in a no-no place

    @pie_flavor Here's the summary: Rust adds a lot of complexity to solve problems we don't have while doing nothing to help solve problems we do have.


  • Considered Harmful

    @dkf problems such as?


  • Discourse touched me in a no-no place

    @pie_flavor The problems we actually have? Oh, little things like making sure that the simulation code produces the right results. Basically it's about really hard-core numerics. Running on a tiny little CPU core. Or rather a lot of them in a constellation linked by a very unusual network (which is the other problem we have, and the one that I spend a lot of time struggling with). Ensuring that objects are accessing and writing to the correct memory is, by comparison, a trivial part of the overall task that we've little problem with; the hardware characteristics of the shared memory mean that we don't mess up accesses because doing that is brutally slow whether right or wrong (it's much faster to write the code to use techniques that don't have the access problems in the first place; those techniques strongly leverage the hardware we've got).

    As I said, the problems that Rust sets out to solve are not problems that cause us difficulties; the cost of converting to it is not justifiable given that it won't actually let us squeeze more out of the hardware on which it will run. Going to direct assembly is more likely; that would actually present a real gain to us. (It's also not got a chance of getting a look-in for the high-level control software that runs on a normal computer; that's a mix of Python and Java.)


  • Banned

    @pie_flavor there's one thing C does very well that Rust doesn't - stick close to the metal. Code will only do what you write, and do exactly what you write. No surprises to be had; near-absolute control. While on most modern embedded targets, this level of control isn't really needed, @dkf's csse sounds like they need it very much.


  • Discourse touched me in a no-no place

    @Gąska Yep. Most of our memory is more easily thought of as being like files (though it totally isn't) in terms of how it is accessed, such is the performance hit taken for touching it. The only fast way to move data in or out of it is via DMA transfers, and those have quite a bit of overhead. The remaining real memory is core-local and while Rust's techniques could work there (and could theoretically do some good, as we have interrupt-driven processing) there's not really all that much need for it given what our programs actually do.

    We explicitly don't want lots of synchronization guards (and the hardware doesn't provide synchronization support). Those take a hammer to performance as the number of threads increases, and we effectively run with very large numbers of threads. (The overall system has a design goal of running with hundreds of millions of threads. We're not quite there yet, and building programs at that scale is insanely challenging…)


  • Considered Harmful

    @Gąska how does Rust not stick close to the metal? Aside from trait objects and closures everything is bare-metal.


  • Banned

    @pie_flavor the main feature of Rust is that it provides powerful abstractions, both compile-time and run-time, to easily build big applications without worrying about low-level details all the time. Powerful abstractions mean that there's much more going on in any given function than meets the eye. Under normal circumstances, it's good; but in @dkf's case specifically, it's bad.


  • Considered Harmful

    @Gąska the majority focus is on zero-cost abstractions. I can't think of any basic features that would make an expensive abstraction.


  • Banned

    @pie_flavor it's not the cost that's the problem, it's abstraction itself. Because it abstracts away stuff. Which, unlike virtually everywhere else, is not something you want here.


  • Discourse touched me in a no-no place

    @Gąska We have our own abstractions. They're… different, and a lot better suited to our problem domain. All the things that Rust helps with are effectively irrelevant to us; we don't do much memory allocation in the first place. (Alas, what we do do a lot of is more like working with variable length arrays of variable length arrays, and is rather horrible. It's hard to do much better with it too; padding things out to constant widths blows our memory requirements up way too large.)



  • @levicki Consider yourself lucky. @ben_lubar could be evangelising Go. Or Logjam.


  • BINNED

    @HardwareGeek said in Java is on crack:

    Go. Or Logjam.

    There’s a difference? :thonking:


  • Discourse touched me in a no-no place

    @topspin Yes. One I think I can read, and the other is supposedly a language for human-like creatures made of meat.


  • BINNED

    @dkf said in Java is on crack:

    One I think I can read

    :butwhy.png:


  • Discourse touched me in a no-no place

    @topspin said in Java is on crack:

    :butwhy.png:

    Better than lodgebann.


  • Discourse touched me in a no-no place

    @levicki said in Java is on crack:

    The only real language is C.

    The only REAL language is FORTRAN. (C has float and double…)



  • @levicki If a programming language is travelling at the speed of light, then it doesn't experience the passage of time. So does its execution speed become zero? 🤔


  • Banned

    @mott555 said in Java is on crack:

    @levicki If a programming language is travelling at the speed of light, then it doesn't experience the passage of time.

    Goodbye randomness.


  • Discourse touched me in a no-no place

    @mott555 said in Java is on crack:

    So does its execution speed become zero? 🤔

    Since you can't measure any state changes or perform any computation without the passage of time, it's execution speed is “irrelevant”. 😉


  • BINNED

    @dkf said in Java is on crack:

    @levicki said in Java is on crack:

    The only real language is C.

    The only REAL language is FORTRAN. (C has float and double…)

    According to FORTRAN, both FORTRAN and C are real. Only languages starting with I-N are integer. 🏆

    Which just shows once again FORTRAN and all of its community is completely fucked up.


  • Discourse touched me in a no-no place

    @topspin GOD IS REAL (UNLESS DECLARED INTEGER).


Log in to reply