[HN Gopher] The wild world of non-C operating systems
       ___________________________________________________________________
        
       The wild world of non-C operating systems
        
       Author : dharmatech
       Score  : 249 points
       Date   : 2022-03-30 06:07 UTC (1 days ago)
        
 (HTM) web link (www.theregister.com)
 (TXT) w3m dump (www.theregister.com)
        
       | rbanffy wrote:
       | Fun to think Clearpath is the oldest operating system in
       | production, since 1962, and that's still fully supported.
       | 
       | Comes close to another one that also predates C, IBM's z/OS,
       | which has parts written in their own assembly dialect, as well as
       | PL/1 and others.
       | 
       | Next week we'll probably see a new version of it with support for
       | the new z16 (based on the Telus chip they've shown at the last
       | Hot Chips).
        
       | qubex wrote:
       | I'm delighted they mentioned TAOS and (following through) the
       | amazing Transputer architecture of the 1980s. Being a teen
       | 'interested' in computers in the early 1990s I was fascinated by
       | massively parallel architectures (Connection Machine 1/2 and
       | Connection Machine 5, IBM's SP/2 "scalable parallel" RS/6000
       | based machines, and the Transputer concept) and I'm still
       | figuring out whether GPUs are true embodiments of that concept or
       | not.
        
         | dfox wrote:
         | Massively parallel was just an marketing buzzword that was used
         | for a lot of different things. One thing to look for is wether
         | all the compute elements run from same clock or not.
         | 
         | CM1/2 is SIMD machine that is mostly nothing more than FPGA
         | turned inside out and in fact just an accelerator that cannot
         | do anything useful standalone (control flow is mostly done in
         | software on the frontend machine). In this regard it is
         | somewhat similar to today's GPUs.
         | 
         | SP/2 is more or less equivalent of the "Beowulf clusters" of
         | the turn of certury and Slashdot fame, that is bunch of
         | computers with full OS instances connected together with some
         | reasonably fast network. But done few years before on somewhat
         | specialized IBM hardware (And well, Myrinet of the early large
         | Linux based clusters was kind of funky specialized hardware,
         | with these 18pair Cat5 cables...).
         | 
         | CM5 is weird as it is cluster of more or less off the shelf
         | SPARC nodes with several independent communications networks
         | with one of the networks being capable of doing bunch of
         | "collective communications" (reduce, broadcast...) operations
         | in hardware. As with CM1/2 it does not run any kind of OS and
         | is mostly managed by some set of frontend computers than do the
         | job setup and network configuration for each new job.
         | 
         | And then transputer is not an concept, there was real hardware
         | and solar system is full of things that are directly descended
         | from that hardware. The issue with transputers as an HPC
         | platform (even for the early 90's) is that the nodes are too
         | small, slow and have too slow interconnect to be meaningfully
         | usable as general purpose HPC platform because you end up using
         | significant fraction of the potential performance for
         | housekeeping tasks (notice that above mentioned CM1/2/5 has
         | some out of band method for the frontend to manage the nodes
         | and even directly access their local memory, on transputers
         | this had to be done through the main communication network and
         | supported by software running on the nodes themselves, which
         | makes even booting the thing an interesting excercise in
         | parallel programming).
        
         | yvdriess wrote:
         | The Tilera [1] processors were a recent embodiment of the
         | Transputer. (comedy option: the TIS-100 [2])
         | 
         | Modern GPU architectures are very much their own thing. They
         | have more in common with Vector machines in how the ALUs are
         | organized, but the macro control flow is more like Dataflow
         | architectures.
         | 
         | [1] https://en.wikipedia.org/wiki/TILEPro64 [2]
         | https://en.wikipedia.org/wiki/TIS-100
        
           | mst wrote:
           | TIS-100 is my current favourite puzzle game and the plethora
           | of implementations on github plus the various community
           | resources (including a rather good subrediit) make it even
           | more fun. If it sounds interesting, I recommend
           | https://alandesmet.github.io/TIS-100-Hackers-Guide/ as a
           | starting point.
        
       | jliptzin wrote:
       | Was this written by a machine?
        
       | weare138 wrote:
       | This article misses a ton. In addition to all the ones mentioned
       | already what about all the early operating systems written in
       | assembly like Apple DOS or Commodore DOS and the Pascal family of
       | OSs like Mac OS Classic and Toro Kernel.
        
         | em3rgent0rdr wrote:
         | and MS-DOS [1] and BareMetal [2].
         | 
         | [1]
         | https://web.archive.org/web/20170506152047/http://www.paters...
         | 
         | [2] https://github.com/ReturnInfinity/BareMetal
        
       | bitwize wrote:
       | MCP (as in the Burroughs OS) stood for Master Control Program.
       | The villain in _Tron_ was named for the OS. The technical
       | consultant for _Tron_ was none other than Alan Kay -- himself a
       | huge Burroughs fan.
        
         | skadamat wrote:
         | Yeah! Also I think Alan Kay's wife (Bonnie MacBird) was the
         | writer for the movie:
         | https://en.wikipedia.org/wiki/Bonnie_MacBird
        
           | bitwize wrote:
           | Yep. They met and fell in love while working on Tron.
           | Doubtless Bonnie thought that MCP Alan was talking about made
           | a cool villain name. Also, Tron's programmer Alan Bradley is
           | named after Kay.
           | 
           | The major conflict in Tron is also themed after Kay's
           | thought: Whom should a computer serve, its users or the
           | bureaucracy that administrates it? Kay believed in user-
           | centric computing, and was profoundly influential in making
           | that happen, but it's clear that this struggle still goes on
           | today.
        
         | dboreham wrote:
         | MCP written in some version of Algol, iirc.
        
           | bitwize wrote:
           | ESPOL, a systems dialect of ALGOL.
           | 
           | Uniquely for a machine at the time, you _didn 't_ program a
           | Burroughs in assembly. The tools just weren't available.
           | Everything from the kernel to user applications was written
           | in some HLL.
        
       | p_l wrote:
       | Porting a mention from the other submission of this article:
       | 
       | It misses the big name of Multics, written in PL/I, and direct
       | inspiration (both positive and negative) for Unix
        
       | ChuckMcM wrote:
       | And Smalltalk. But this was a great article which highlighted
       | some of the creativity that got me interested in computers in the
       | first place. Building an operating system isn't "hard" but it is
       | a lot of work the more you do. That is time consuming (but in a
       | fun way, like reading books is time consuming)
       | 
       | Off and on I've experimented with a small event driven real time
       | OS for my robots that started as a Forth kernel, switched over to
       | a C kernel, and then to a Rust kernel. The experimental part has
       | been looking at "infinite asynchronous threading" and it was
       | hugely influenced by Rodney Brook's subsumption architecture. My
       | thesis being that organisms aren't driven by a single scheduler
       | and a bunch of processes, why should an OS be. (there are
       | arguments pro and con on that one :-)).
       | 
       | Anyway, not everyone is an 'OS' type. At Sun we used to joke you
       | were either an 'OS' type, 'Language' type, or a 'GUI' type. Those
       | were the core areas of investigation in the software
       | organization. I tend to be an 'OS' type with a bit of 'language'
       | thrown in :-)
        
         | MaxLeiter wrote:
         | I've been on a Smalltalk binge the last few days and have
         | really been enjoying this two hour long interview / demo with
         | Dan Ingalls on Smalltalk and the Alto:
         | https://youtu.be/uknEhXyZgsg
        
       | OnlyMortal wrote:
       | I remember the original MacOS been a mix of 68K and Pascal.
       | 
       | I tended to use MPW C and 68K in those days and recall the stack
       | sizes been different between C and Pascal.
        
       | dmtroyer wrote:
       | click-bait title for programmers if I ever saw one.
        
       | pyinstallwoes wrote:
       | DSP is a language and operating system (forth-like) made in the
       | Soviet Union. I believe it was originally crafted upon ternary
       | computation hardware but eventually transitioned to whatever was
       | being used throughout the Union.
       | 
       | http://www.euroforth.org/ef00/lyakina00.pdf
       | 
       | Apparently they came to the syntax independently of Forth.
       | However my research shows that some material about Forth may have
       | showed up in a journal around the same time DSP was made. Either
       | way the resemblance is uncanny. There is an interesting quote
       | about the interface of the design requirements that manifested as
       | the language: "DSP wasn't invented, it was discovered" - I
       | probably butchered it. But I'm pretty sure Chuck may have said it
       | too or at least agrees.
       | 
       | The point is, you reach this interface following a method of
       | reaching for something akin to "irreducible computational
       | language that makes sense between humans and machines."
        
       | ncmncm wrote:
       | The article falsely claims, "Rust is eclipsing C++". "Rust is
       | desperately chasing after C++" would be accurate.
       | 
       | It also fails to mention Apollo Aegis, coded in Apollo's extended
       | Pascal, and both at introduction and retirement was more advanced
       | than Unix. Some key features still are not seen in Linux or most
       | BSDs.
       | 
       | And, it fails to mention SerenityOS, in C++.
        
         | ModernMech wrote:
         | It depends on what they mean by popularity. If they mean % of
         | developers using Rust vs C++ they are wrong. But I teach
         | students both C++ and Rust, and by far Rust is preferred. It's
         | never even a contest.
         | 
         | C++ is long in the tooth, and if you want to talk desperation,
         | C++ is really struggling with its identity now that Rust is on
         | the scene. Before there were some pretty good arguments to use
         | it, but in light of Rust, the best argument for C++ is just
         | that it has a larger ecosystem (which says more about how old
         | C++ is than how good it is as a language). That argument
         | becomes less convincing with each passing day.
         | 
         | IMO in 2022 there's not a good reason to start a new project in
         | C++ unless that's all you know, or you have some constraint
         | tied to C++.
        
           | Koshkin wrote:
           | > _by far Rust is preferred. It's never even a contest_
           | 
           | But it is (for the most part) C++ that pays the bills.
        
             | tialaramex wrote:
             | Judging from the same Stack Overflow polling, only by about
             | 3:1 and so we might also say it's really _Javascript_
             | paying the bills since that 's what is most used rather
             | than C++. Just not to write operating systems.
             | 
             | If we're thinking about University students it's very
             | likely the ratio is even smaller by the time they graduate
             | and are looking for employment. Rust jobs grow, there are
             | lots of new Rust codebases, and they need maintenance
             | people just the same as C++. You may have fewer mysterious
             | unsafety bugs to fix but your customers still have changing
             | requirements, other people's APIs still change, so you
             | aren't going to go hungry any time soon programming in Rust
             | any more than C++
             | 
             | And if we're talking about in-house training, whatever they
             | are teaching pays the bills, the employer isn't sending
             | employees to learn how to do stuff they've no use for,
             | otherwise they'd just give you indefinite leave on full
             | pay.
        
           | pjmlp wrote:
           | Those students are up for a surprise when they get to do
           | anything graphics or HPC related.
        
             | aeonik wrote:
             | Can you explain more? I don't have any experience to infer
             | what your comment means.
        
               | pjmlp wrote:
               | HPC is all about C, C++, Fortran, Python (as scripting
               | language), and now Julia is slowly being the new kid in
               | town.
               | 
               | Stuff like OpenACC, OpenMP and MPI are expected to be in
               | the box, regardless of the language.
               | 
               | On the graphics space, Khronos, NVidia, Intel and AMD are
               | driving the adoption of standard C++ as compute language.
               | 
               | NVidia now has many key contributors to ISO C++ on their
               | payroll and as shown at GTC 2022, wants to make CUDA the
               | best GPU implementation of such features.
               | 
               | Then on game consoles, C++ is the main language on the
               | SDKs, alongside C# and Unity.
               | 
               | One can naturally use other stacks, like Embark Studios
               | is doing with Rust, but then it is on them to spend
               | development resources on making it work, and deal with
               | possible integration issues.
        
               | scythe wrote:
               | Most of the interfaces you're discussing are more-or-less
               | "purely functional", though. Interop overhead is going to
               | be a lot less when you're squaring a matrix than when
               | you're trying to write an event loop. In fact, most
               | people who use those C++ libraries never touch C++, as
               | you've pointed out yourself: they use Python or
               | (recently) Julia. The ecosystem as it exists is already a
               | hodgepodge of C[++] and Fortran, and while the interop
               | between those might be annoying if you were building a
               | video game, a NumPy user doesn't care if one subroutine
               | is in C++ and the next one is in Fortran. So, I don't see
               | why one more backend language would be a problem,
               | realistically.
        
               | tux3 wrote:
               | I think they mean that C++ has a lot of momentum in
               | graphics and HPC.
               | 
               | So in their model of the world, students who learn Rust
               | would be surprised that there are people who do not use
               | Rust.
        
               | ncmncm wrote:
               | They will find that their Rust experience is worth
               | little, because they will need to go back and learn C++
               | to make any progress in those, and indeed most areas.
        
             | stouset wrote:
             | This statement is true for literally any pair of
             | [technology] and [thing-theres-a-better-technology-for].
        
           | dan-robertson wrote:
           | If you have a very deep understanding of C++ then you are
           | potentially yourself a good reason to start a project in C++
           | and this statement is true of any language. Knowing the
           | language very well can mean more time focusing on the actual
           | goals and less time messing around with incidental language
           | things. C++ is not sufficiently bad that mastery of it
           | doesn't trump other concerns for personal projects. Even in
           | companies you are often likely to find more C++ expertise
           | than Rust expertise.
        
           | ilovecaching wrote:
           | I don't think you understand just how much of your system and
           | the libraries out there are C/C++. Popularity isn't a measure
           | of entrenchment. C/C++ will likely exist forever because the
           | industry isn't going to rewrite every single piece of the
           | system into Rust. And it isn't like you can just go to one
           | community and ask them to switch. These are huge federations
           | that talk to each other using C/C++ bindings and have hashed
           | out protocols over years and years of board meetings. I think
           | Rust has a place. We can build new things in Rust or replace
           | some things with Rust. But acting like everyone should learn
           | Rust and C/C++ has no value is dangerously ignorant.
        
             | zozbot234 wrote:
             | C library bindings can be used directly in Rust, and there
             | are facilities to improve interfacing with C++ as well.
        
               | pjmlp wrote:
               | Try to use those facilities with CUDA or Unreal.
        
           | DrBazza wrote:
           | > But I teach students both C++ and Rust, and by far Rust is
           | preferred. It's never even a contest.
           | 
           | Why is Rust preferred though? Is it "fearless concurrency"
           | (or whatever the old tag line was), a more modern stdlib, or
           | is it Rust's tooling with `cargo` rather the shitty tool-
           | scape of C++'s make/cmake/meson and vcpkg/conan and whatever
           | else.
        
             | e3bc54b2 wrote:
             | As a newbie who only learned Java and JS in bootcamp, and C
             | in EE, Rust's tooling is absolutely phenomenal.
             | 
             | Things just work, and that is a rare experience.
        
               | ModernMech wrote:
               | It's a rare experience but once you've had it, anything
               | less becomes unacceptable. Rust has ruined me for so many
               | languages, my bullshit tolerance used to be much higher.
        
           | jcelerier wrote:
           | Can you point to a Rust alternative to
           | https://doc.qt.io/qt-5/qtreeview.html ?
        
             | steveklabnik wrote:
             | https://slint-ui.com/ is an in-progress one from some ex-
             | Trolltech folks.
        
               | jcelerier wrote:
               | As much as I have an extreme confidence in the technical
               | ability of the involved folk, even TQTC did not manage to
               | replicate it in an useful enough way so far in QML, and
               | QML has been around for something like 11 years now.
        
               | steveklabnik wrote:
               | Yeah, I'm certainly not claiming it's equivalent today, I
               | haven't even tried a demo. Just a thing to watch if
               | you're interested in this space.
        
             | scoutt wrote:
             | Exactly. I think you managed to summarize all my concerns
             | in a single sentence.
             | 
             | https://www.areweguiyet.com/
        
           | kllrnohj wrote:
           | > C++ is long in the tooth
           | 
           | C++ is mature, there's a difference. It's definitely not
           | "long in the tooth" as it still has plenty of modern features
           | & niceties and is getting more all the time.
           | 
           | > C++ is really struggling with its identity now that Rust is
           | on the scene
           | 
           | C++'s identity struggles have nothing to do with Rust
           | whatsoever. It's struggling to balance ABI & historical
           | compatibility with moving the language forward, that's about
           | it. And that's just something many mature languages face at
           | some point (see Python3 for example).
           | 
           | Beyond that struggle of supporting legacy code, there's no
           | identity crisis with C++ at all.
           | 
           | > the best argument for C++ is just that it has a larger
           | ecosystem (which says more about how old C++ is than how good
           | it is as a language). That argument becomes less convincing
           | with each passing day.
           | 
           | It's still an incredibly convincing argument. Rust has decent
           | C interop, but it's not especially seamless to do safely. But
           | Rust's interop with C++ is rather complicated. So if you have
           | any C++ dependencies, you're almost certainly _far_ better
           | off to just go with C++. Even if you just have C dependencies
           | and someone else hasn 't yet made a crate for it, you might
           | still be better of with C++.
           | 
           | Particularly since many of the Rust crates that bind to
           | popular C & C++ libraries are not owned or maintained by the
           | library in question. So you're entering into a bit of a
           | sketchy maintenance world. And there's already been churn &
           | abandonware here, for example the various projects (including
           | one from Mozilla/Servo!) to bind to libpng that were then
           | later all abandoned, and you're supposed to migrate to
           | rewrites of PNG support in Rust like LodePNG. This is not
           | ignorable churn & risk.
           | 
           | It can be fun, and if it's a hobby project absolutely go for
           | it. But if you're on the clock to ship & maintain something,
           | it's a risk you must consider quite seriously.
        
             | zahllos wrote:
             | I mostly agree. C++ is mature, has standards and a whole
             | array of production ready libraries. If I wanted to build a
             | production cross platform GUI app today and not use
             | electron (vomit) I would likely use Qt for it. Rust has
             | nothing that is quite ready yet to offer there.
             | 
             | However, my overall view is that Rust is the right
             | direction. If I had to improve C++, it would look a lot
             | like Rust: move bounds checking and ownership to the
             | compiler not the template compiler, remove classes,
             | introduce traits and make C++ have concepts that don't
             | require me to type every punctuation symbol on my keyboard
             | to use, const by default.
             | 
             | Getting the compiler to do some of this checking by default
             | is exactly what I want. If we can have an Ada/Spark style
             | subset via Kani, also done at compile time to check
             | correctness, even better.
             | 
             | > It's still an incredibly convincing argument. Rust has
             | decent C interop, but it's not especially seamless to do
             | safely.
             | 
             | I would make this statement slightly stronger. If you
             | interop with C code and there are bugs in C code, all bets
             | are off. You don't get any magical protection because your
             | main routine is written in Rust. Cross-language safety,
             | e.g. C++/Javascript, for example, is a very difficult
             | problem. Here's a discussion of C++ and Rust
             | https://dl.acm.org/doi/fullHtml/10.1145/3485832.3485903 If
             | you want a tl;dr of that paper, it is that memory
             | corruptions in C or C++ code sharing the address space of
             | safe Rust code can make safe Rust code unsafe too. There
             | have been plenty of attempts to study for example the
             | interactions between browser C++ and the various runtimes a
             | browser hosts.
             | 
             | The compact you are making with the Rust compiler when you
             | type 'unsafe' is that you are saying you have verified the
             | correctness of that code: that it is in fact already safe
             | and the compiler should not (probably because it cannot)
             | check it. The same is true of any FFI code you use.
             | However, this is not how many people actually _use_ Rust.
             | Here for example is a 2 year old unfixed segfault in a Rust
             | crate caused by interfacing with non-Rust code:
             | https://rustsec.org/advisories/RUSTSEC-2020-0159. This a)
             | demonstrates the issue and b) demonstrates that random
             | crates pulled off crates.io can contain safety issues for
             | 2+ years with no fix.
        
               | hulitu wrote:
               | > I mostly agree. C++ is mature, has standards and a
               | whole array of production ready libraries. If I wanted to
               | build a production cross platform GUI app today and not
               | use electron (vomit) I would likely use Qt for it.
               | 
               | C++ is mature ? Every couple of years a new C++ standard
               | emerges which breakes old programs. Qt ? Which version ?
               | 3 ? 4 ? 5 ? 6 ?
        
             | andrewaylett wrote:
             | An "unsafe" set of calls from Rust to C are still no less
             | unsafe than calling C from other C or from C++. The biggest
             | difference is in programmer expectation, which is why it's
             | so unfortunate when a "safe" wrapper has bugs. Rust can't
             | fix bugs in the underlying C library either, of course.
             | That's one place where Mozilla's recent foray into FFI via
             | compiling to WASM then compiling the WASM to native code is
             | very interesting to me.
        
               | kllrnohj wrote:
               | But making that unsafe Rust block safe to call from safe
               | Rust isn't the most trivial of things to do. Conforming
               | to all the safety requirements is still a thing to deal
               | with, otherwise you contaminate all your safe Rust code.
               | 
               | It's not an unreasonable burden for what you get in
               | return, but it is still a burden.
        
               | stouset wrote:
               | That burden exists if you're calling into it from C, it's
               | just implicit. At least Rust gives you the tools to write
               | safe wrappers. Once you've done that consumers of your
               | library don't have to tiptoe around the possibility of
               | unsafe behavior.
        
             | notriddle wrote:
             | > C++ is mature, there's a difference. It's definitely not
             | "long in the tooth" as it still has plenty of modern
             | features & niceties and is getting more all the time.
             | 
             | C is mature. C++ drinks and sleeps around, but that hardly
             | makes it mature.
        
             | boznz wrote:
             | > C++ is long in the tooth
             | 
             | Welcome to the world of any language that the cool guys
             | dont use anymore :-)
        
           | bayindirh wrote:
           | > IMO in 2022 there's not a good reason to start a new
           | project in C++ unless that's all you know, or you have some
           | constraint tied to C++.
           | 
           | I personally don't agree. I can start with performance and
           | continue with a better compiler ecosystem, and add
           | suitability for low resource applications. I'm just not
           | scratching the surface here.
           | 
           | Rust is not bad, but it's not a replacement of C++. They
           | aspire to be different things.
        
             | [deleted]
        
             | umanwizard wrote:
             | When is C++ higher-performance than Rust?
        
               | jandrewrogers wrote:
               | I would frame the question more in terms of economy than
               | performance. In theory, I could write a database engine
               | in Rust that is as performant as C++, but it would not
               | make sense to.
               | 
               | Making Rust perform the same as C++ in database engines
               | requires marking large portions of the code base as
               | "unsafe", while requiring substantially more lines of
               | code due to being less expressive. Note that this doesn't
               | imply that the code is _actually_ unsafe, just that the
               | Rust compiler cannot reason about the safety of correct
               | and idiomatic code in database engines.
               | 
               | And this is why state-of-the-art database engines are
               | still written in C++. There is not much point in using
               | Rust if doing so requires disabling the safety features
               | and writing a lot more code to achieve the same result.
        
               | pkolaczk wrote:
               | Definitely not my experience with file io and database-
               | related software in rust. Actually two of my publically
               | available programs - fclones and latte - seem to be the
               | most efficient in their respective classes, beating a
               | wide variety of C and C++ programs, yet they contain
               | almost no unsafe code (< 0.1%).
               | 
               | The state of the art database engines are written in C++
               | (and Java) because at the time they were developed Rust
               | didn't exist.
        
               | umanwizard wrote:
               | I work at Materialize, which is writing a database in
               | Rust. We use some `unsafe` code, but it's a very small
               | proportion of the overall codebase and quite well
               | abstracted away from the rest of the non-unsafe code.
               | 
               | To be fair, we're trying to do a bit of a different thing
               | (in-memory incrementally maintained views on streaming
               | data) than most existing databases, so you could argue
               | that it is not an apples-to-apples comparison.
               | 
               | But there are plenty of other databases written in
               | non-C++ languages -- there is even TiDB which is written
               | in Rust too.
        
               | nivenkos wrote:
               | There's no placement new IIRC so you always build on the
               | stack and copy it to the heap.
               | 
               | https://users.rust-lang.org/t/how-to-create-large-
               | objects-di...
        
               | andrewaylett wrote:
               | I think that's a question of an "insufficiently smart
               | compiler" rather than _necessarily_ something the
               | programmer should be concerned about?
        
               | Koshkin wrote:
               | The programmer should certainly be concerned about the
               | compiler being insufficiently smart.
        
               | steveklabnik wrote:
               | No, it is a language semantics issue. You _can_ get the
               | compiler to optimize it away today, if you 're careful.
               | But that's a bad user experience. You should be able to
               | specifically request this semantic, and be sure it works.
        
               | umanwizard wrote:
               | Fair point.
        
               | tialaramex wrote:
               | You can do "placement new" (Rust has no new operator, but
               | in this context) unsafely with MaybeUninit --
               | https://doc.rust-
               | lang.org/stable/std/mem/union.MaybeUninit.h...
               | 
               | Make a MaybeUninit<Doodad> on the heap, initialise it,
               | and then unsafely assume_init() remembering to write your
               | safety justification ("I initialised this, so it's fine")
               | and get a Doodad, on the heap.
               | 
               | The reason it isn't mentioned in that 2019 u.r-l.o post
               | is that MaybeUninit wasn't stabilized until mid-2019.
        
               | infamouscow wrote:
               | Rust's lack of fast thread-local storage makes it a non-
               | starter for me.
               | 
               | It's really disappointing, especially when the language
               | has incorporated so many other excellent performance
               | improvements like Google's SwissTable and pattern-
               | defeating quicksort.
               | 
               | https://github.com/rust-lang/rust/issues/29594
               | 
               | https://matklad.github.io/2020/10/03/fast-thread-locals-
               | in-r...
        
               | roblabla wrote:
               | FWIW, Rust does have fast thread locals, but only in
               | nightly. https://github.com/rust-lang/rust/issues/29594
        
               | bayindirh wrote:
               | High performance and scientific computing, or more
               | generally when you transfer a lot of data structures via
               | pointers to a lot of threads. In that scenarios, a half
               | second performance difference in main loop can translate
               | to hours in long runs.
               | 
               | The code I'm developing is running with ~1.7M
               | iterations/core/second. Every one of these iterations
               | contain another set of 1000 iterations or so (the number
               | is variable, so I don't remember the exact mean, but the
               | total is a lot). Also, this number is on an 8 year old
               | system.
               | 
               | More benchmarks are here: https://benchmarksgame-
               | team.pages.debian.net/benchmarksgame/...
        
               | umanwizard wrote:
               | You haven't actually explained when Rust is slower. You
               | just described a situation where you care about
               | performance.
               | 
               | What specific operations happen slower in Rust than in
               | C++?
        
               | [deleted]
        
               | ModernMech wrote:
               | The link you provided shows C++ and Rust both performing
               | best in various benchmarks. Seems like a wash to me, and
               | to the extent one beats the other it's marginal. Which is
               | to be expected because as long as the language is
               | compiled and the compiler is good enough, you should be
               | able to get as much performance out of it as your CPU can
               | handle.
        
               | bayindirh wrote:
               | The numbers might look small, and indeed for most cases
               | it can be considered a wash, but in some cases, these
               | small differences return as hours.
               | 
               | For example, I'm using a lot of vector, matrix and array
               | accesses in my code. A lot of these are copied around for
               | computation. Moving that amount of data will trigger a
               | lot of checks in Rust, and will create a slowdown
               | inevitably.
        
               | chlorion wrote:
               | Moves don't require any runtime checks in Rust to my
               | knowledge. Moves do involve some compile time analysis to
               | make sure you aren't accessing a value that has been
               | moved, maybe that is what you are thinking of?
               | 
               | In Rust, moves are always a simple memcpy from one place
               | to another, that's it! With non `Copy` types this
               | destroys the original value which is why the compiler
               | makes sure you don't access it after it's moved.
               | 
               | There is also `Clone` which is generally a deep copy of
               | everything, but this also doesn't involve any runtime
               | checks as long as you aren't using reference counted
               | pointers or something.
               | 
               | There _are_ bounds checks when indexing into vectors and
               | whatnot though, but non checked methods are available.
        
               | ModernMech wrote:
               | Do you have a link to your code that you've benchmarked
               | in C++ and Rust? I'm also doing a lot of
               | vector/matrix/array access in my code, so I'm curious as
               | to what you'd be doing that would cause slow downs to the
               | point that C++ can beat Rust by hours. That would be very
               | enlightening to see.
        
               | bayindirh wrote:
               | I would love to, but the framework I'm developing is
               | closed source (it's my Ph.D. and postdoc work at the end
               | of the day), but we have a paper for some part of it. Let
               | me see if I can share it.
        
               | umanwizard wrote:
               | What makes you think Rust forces more "checks" when
               | moving data than C++ does? Can you give an example?
        
               | stouset wrote:
               | To wit, the Rust compiler _is_ "sufficiently smart" in an
               | extremely high number of scenarios such that it can
               | achieve optimal performance by eliding things like bounds
               | checks when it's able to determine that they would never
               | fail.
               | 
               | This is, in my experience, the overwhelming majority of
               | idiomatic Rust code. For cases where it can't, and
               | performance is absolutely critical, there are easy escape
               | hatches that let you explicitly elide the checks
               | yourself.
        
               | jcelerier wrote:
               | Rust's Vec indexing is bound-checked by default. Just
               | something like this is abysmal for performance (but
               | pretty good for consultants who get called to fix stuff
               | afterwards, so, like, keep them coming!):
               | 
               | - Rust: https://rust.godbolt.org/z/GK8WY599o
               | 
               | - CPP: https://gcc.godbolt.org/z/qvxzKfv8q
        
               | steveklabnik wrote:
               | Idiomatic Rust here would use something like this, not
               | that in this case it makes them performance identical,
               | but it is more representative of real Rust code, and is
               | slightly smaller https://rust.godbolt.org/z/brh6heEKE
               | 
               | EDIT: lol don't write code five minuets after waking, the
               | reply to this has far better code
               | 
               | (EDIT: incidentally, I was also curious about a non-
               | extern function, but the compiler is seeing through all
               | of my attempts to call a native Rust function with an
               | opaque body here...)
               | 
               | That being said this code will also be a no-op instead
               | of... something worse, if the vector is empty, so,
               | they're not directly comparable, but they weren't really
               | in the first place, as you mention, so...
        
               | umanwizard wrote:
               | Why not                 for i in &v[1..num]
               | 
               | instead of all the iter take skip stuff?
        
               | steveklabnik wrote:
               | Because I wrote this comment shortly after waking up and
               | made a mistake. That code is far far better. Thank you.
        
               | nivenkos wrote:
               | You can just use unsafe if you care in this case though.
               | 
               | It's a saner default option tbh.
        
               | amadvance wrote:
               | C is even better. One instruction less than C++ ;)
               | 
               | https://gcc.godbolt.org/z/oc19Gc4eY
        
               | 3836293648 wrote:
               | https://rust.godbolt.org/z/zM58dcPse
               | 
               | And look, putting a limit that the compiler and guarantee
               | once outside the critical loop eliminates it. You're
               | already using unsafe. If you really want to shoot
               | yourself in the foot with this nonsense you can use a get
               | unchecked or an unchecked assumption
               | 
               | https://rust.godbolt.org/z/naeaYad5T
               | 
               | On top of that, noone would write rust code like that.
               | This version has one bounds check at the beginning and is
               | a lot more idiomatic
               | 
               | https://rust.godbolt.org/z/1s9zsMx36
        
               | jcelerier wrote:
               | The point is to have some code that exhibits what happens
               | when a bound check is needed. You can also do
               | for(double v : std::span(vec).subspan(1)) { }
               | 
               | in C++ and that will be safe and not need a bound check
               | except an user-provided one at the creation of the span
               | (-1 for C++ here :-)) - and also not matter at all
               | regarding the bound checks problem which will occur as
               | soon as you don't just iterate linearly which is
               | extremely common in the kind of problems that end up
               | showing at the top of the profiler and the whole point of
               | this conversation.
        
               | froydnj wrote:
               | Just because indexing is bounds-checked by default
               | doesn't mean that the bounds-checking is necessarily in
               | your final code:
               | 
               | https://rust.godbolt.org/z/er9Phcr3c
               | 
               | Yes, you still have the bounds check when constructing
               | the slice, but that's fine.
               | 
               | And since it's probably slightly more common to iterate
               | over the length of the vector anyway:
               | 
               | https://rust.godbolt.org/z/e5sdTb7vK
        
               | umanwizard wrote:
               | Both languages let you access vector elements with or
               | without bounds checking. Stroustrup even recommends you
               | use .at by default in c++.
        
               | titzer wrote:
               | > Rust's Vec indexing is bound-checked by default. Just
               | something like this is abysmal for performance
               | 
               | Unless you can provide numbers to back this claim up,
               | I'll continue to rely on my measurements that bounds
               | checking (in Virgil) costs anywhere from 0.5% to 3% of
               | performance. It's sometimes more or less in other
               | languages, but it is by far _not_ the reason any
               | programming language has bad performance. I have no
               | reason to suspect that it costs more in Rust, other than
               | misleading microbenchmarks.
        
               | jcelerier wrote:
               | Here's a quick and dirty example:
               | https://gcc.godbolt.org/z/3WK7eYM4z
               | 
               | I observe (-Ofast -march=native -std=c++20 ; CPU is intel
               | 6900k with performance governor on Arch... blasting at
               | 4GHz) :
               | 
               | - clang 13: 8.93 ms per iteration
               | 
               | - gcc 11: 9.46 ms per iteration
               | 
               | so roughly around 9ms.
               | 
               | Replacing                   return mat[r * matrix_size +
               | c];
               | 
               | by                   return mat.at(r * matrix_size + c);
               | 
               | I observe
               | 
               | - clang 13: 20.95 ms per iteration
               | 
               | - gcc 11: 18.11 ms per iteration
               | 
               | so literally more than twice as slow. I also tried with
               | libc++ instead of libstdc++ for clang and the results did
               | not meaningfully change (around 9ms without bound-
               | checking and 21 ms with).
        
               | nybble41 wrote:
               | Part of the problem is that the multiply() function takes
               | variable-size matrices as inputs and isn't inlined
               | because it's declared as an external function and so
               | could, in theory, be called from another compilation
               | unit. If it's declared as "static" instead then the
               | compiler generates identical code (modulo register
               | selection) at -Ofast for both versions--eliminating the
               | bounds checking at compile-time:
               | 
               | https://gcc.godbolt.org/z/qqWr1xjT8
        
               | jcelerier wrote:
               | > Part of the problem is that the multiply() function
               | takes variable-size matrices as inputs
               | 
               | so does real-life code ? I don't know about you but I
               | pretty much never know the size of my data at compile
               | time.
               | 
               | > If it's declared as "static"
               | 
               | again, real-life code calls math operations defined in
               | other libraries, sometimes even proprietary.
        
               | titzer wrote:
               | In Java or other languages with bounds-checked arrays,
               | you would typically just loop from 0 to the end of the
               | array. In Java the JIT will analyze the loop, see that it
               | is bounded by the length of the array, conclude all
               | accesses are in-bounds and eliminate bounds checks.
               | Virgil does this simple type of bounds check elimination
               | as well in its static compiler, but its analysis is not
               | quite as sophisticated as Java JITs.
        
               | nybble41 wrote:
               | > I don't know about you but I pretty much never know the
               | size of my data at compile time.
               | 
               | Whole-program optimization (LTO) can deal with that.
               | Also, Rust inlines across modules much more aggressively
               | than C++ does, even without LTO, so optimization will be
               | more effective and its bounds-checking won't have as much
               | (if any) runtime overhead. Especially if you write your
               | Rust code idiomatically, as others have already
               | suggested. Your earlier Rust example was practically
               | designed to inhibit any attempt at optimization. Simply
               | iterating over a slice of the vector, rather than the
               | indices, results in a much tighter inner loop as it only
               | needs to check the bounds once.
               | 
               | That being said, in this case I think it would be better
               | to have fixed-size matrices (using const generic/template
               | arguments) so that the bounds are encoded in the types
               | and known to the compiler locally without relying on
               | whole-program optimization.
        
               | stouset wrote:
               | > Especially if you write your Rust code idiomatically,
               | as others have already suggested. Your earlier Rust
               | example was practically designed to inhibit any attempt
               | at optimization.
               | 
               | This is pretty much word-for-word what I've seen in other
               | similar disagreements. Rust Skeptic transcribes their
               | solution from its original programming language into Rust
               | line by line, producing something nobody using Rust would
               | actually write. They find that Rust performs poorly. Rust
               | Proponent writes it the way you'd expect someone who
               | actually knows Rust to write it, and performance meets or
               | exceeds the original. Sometimes they even catch a few
               | bugs.
               | 
               | Yes, if you don't know Rust, and you think it's just a
               | weird re-skin of C++ that can be gsub'd from one to
               | another, you're going to have a bad time. If you're an
               | expert in C++ and have never written Rust, you probably
               | aren't going to beat your finely-tuned C++ program with a
               | ten minute Rust translation. But someone with a year of
               | experience in Rust is probably going to be able to
               | rewrite it in half an hour and come within spitting
               | distance of the thing you've optimized by hand over the
               | course of a few years.
               | 
               | I've written Rust for half a decade and I'm not sure I've
               | ever actually explicitly indexed into a Vec or slice in
               | production code. If I needed to, and it was in a hot
               | loop, and it wasn't a fixed-size array whose size is
               | known at compile time... there's always `get_unchecked()`
               | which is functionally identical to indexing into a C++
               | vec without `at`.
        
               | titzer wrote:
               | From the godbolt link, it looked like most of the vector
               | operations were not getting inlined. You'll need -O2 or
               | higher to have representative results.
               | 
               | I could counter by just writing a Virgil program and
               | turning off bounds check with a compiler flag. We could
               | stare at the machine code together; it's literally an
               | additional load, compare, and branch. The Virgil compiler
               | loves eliminating bounds checks when it can. I know your
               | original comment was in the context of the STL, but it
               | really muddies the waters to see huge piles of code get
               | inlined or not depending on compiler flags. Machine code
               | is what matters.
               | 
               | Regardless, this is still microbenchmarking. Maybe matrix
               | multiply is an important kernel, but we need to benchmark
               | whole programs. If I turn off bounds checks in a big
               | program like the Virgil compiler, I cannot measure more
               | than about 1.5% performance difference.
        
               | jcelerier wrote:
               | > From the godbolt link,
               | 
               | I just used godbolt to quickly share the code. On my
               | computer I tried with -Ofast -march=native (broadwell)
               | 
               | > I could counter by just writing a Virgil program and
               | turning off bounds check with a compiler flag. We could
               | stare at the machine code together; it's literally an
               | additional load, compare, and branch.
               | 
               | This sounds like Virgil is not vectorizing, which makes
               | the comparison much less useful.
               | 
               | I see much more than a couple instructions changed there:
               | https://gcc.godbolt.org/z/8jPMb734x
        
               | titzer wrote:
               | > Virgil is not vectorizing
               | 
               | That's just even more confounding variables. We are,
               | after all, not even doing experiments with Rust vectors,
               | which is what your original comment was about. You wrote
               | examples in C++ and we went down a wormhole already, but
               | I let it slip since at least it was empirical. But I
               | think we shouldn't get distracted with even more side
               | alleys now. Bounds checks are literally just a couple
               | machine instructions, and often eliminated by the
               | compiler anyway, which enables vectorization.
        
               | steveklabnik wrote:
               | I think you're confusing two different senses of
               | "vector", there is the contiguous series of items
               | "vector" data structure that both C++ and Rust have in
               | their standard libraries that's used in the code example,
               | and there's "vectorizing" which is an optimization to use
               | things like SIMD to operate on multiple things at the
               | same time.
        
               | titzer wrote:
               | I understood what was meant by these terms.
        
               | steveklabnik wrote:
               | Okay, then I got lost reading your comment, my apologies.
        
               | titzer wrote:
               | No worries. It's too late for me to edit it now, though,
               | but I meant vectorizing="compiler introduces SIMD".
        
               | jcelerier wrote:
               | > We are, after all, not even doing experiments with Rust
               | vectors,
               | 
               | they are very close to C++ ones, down to the stack
               | unwinding to report the panic in case of bound error if
               | I'm not mistaken.
               | 
               | > That's just even more confounding variables.
               | 
               | No they are not. We are trying to see how much bound
               | checks costs. If you compare between suboptimal programs
               | the comparison is meaningless (or rather not interesting
               | to anyone) - the starting point has to be the absolute
               | best performance that it is possible to get, and add the
               | worst-case bound-checking (I'm happy for you if you never
               | have to worry about the worst case though!)
               | 
               | > Bounds checks are literally just a couple machine
               | instructions, and often eliminated by the compiler anyway
               | 
               | please provide a source for this ? sure, if you use spans
               | as other commenters mentioned, that moves the checking at
               | the span creation time but that only works for the
               | simplest cases where you are going to access linearily -
               | and I would say that it's a library feature rather than a
               | compiler one.                  for(double v : vec) { } //
               | or any sub-span you can take from it
               | 
               | in C++ also does not need bound-checks by design but this
               | kind of construct also utterly does not matter for so HPC
               | workloads.
               | 
               | I can look into my pdfs folders and bring out dozens of
               | papers where the core algorithms all use funky non-linear
               | indexing schemes where you cannot just iterate a range
               | (algorithms based on accessing i, i-1, i+1, or accessing
               | i and N-i, or accessing even / odd values, etc etc) - how
               | would you implement an FFT for instance ? This is the
               | code that matters !
        
               | titzer wrote:
               | > accessing i, i-1, i+1, or accessing i and N-i,
               | 
               | A compiler can do loop versioning for that. And they do.
               | Hotspot C2 (and Graal, too) does a _ton_ of loop
               | optimizations, partitioning the index space into in-
               | bounds and potentially out-of-bounds ranges, unrolling
               | loops, peeling the first iteration off a loop, generating
               | code before a loop to dispatch to a customized version if
               | everything will be in bounds.
               | 
               | When a compiler is doing that sophisticated of loop
               | transforms, you are _not_ measuring the cost of bounds
               | checks anymore, you are measuring a whole host of other
               | things. And sometimes if a loop is just a little
               | different, the results can be disastrously bad or
               | miraculously good. Which is why microbenchmarking is so
               | fraught with peril. A microbenchmark might be written
               | assuming a simple model of the computation and then a
               | sophisticated compiler with analyses never dreamed of
               | comes along and completely reorganizes the code. And it
               | cuts both ways; a C++ compiler might do some unrolling,
               | fusion, tiling, vectorization, software pipelining or
               | interchange on your loops and suddenly you aren 't
               | measuring bounds check cost anymore, but loop
               | optimization heuristics that have been perturbed by their
               | presence. You end up studying second-order effects and
               | not realizing it. And it keeps running away from you the
               | more you try to study it.
               | 
               | >> That's just even more confounding variables.
               | 
               | > No they are not. We are trying to see how much bound
               | checks costs. If you compare between suboptimal programs
               | the comparison is meaningless (or rather not interesting
               | to anyone) - the starting point has to be the absolute
               | best performance that it is possible to get, and add the
               | worst-case bound-checking (I'm happy for you if you never
               | have to worry about the worst
               | 
               | We are always comparing suboptimal programs. No compiler
               | is producing optimal code, otherwise they would dead-code
               | eliminate everything not explicitly intertwined into
               | program output, statically evaluate half of our
               | microbenchmarks, and replace them with table lookups.
               | 
               | You're going down a linear algebra rabbit hole trying to
               | come up with a result that paints bounds checks in the
               | worst possible light. If this is the real problem you
               | have, maybe your linear algebra kernels would be better
               | off just using pointers, or you could even try Fortran or
               | handwritten assembly instead, if it is so important.
               | Unsafe by default is bad IMHO. For real programs bounds
               | checks really don't matter that much. Where this thread
               | is going is all about loop optimizers, and they don't
               | really get a chance to go nuts on most code, so I think
               | we're way off in the weeds.
        
               | tialaramex wrote:
               | Note that Rust _has_ unchecked index, you just have to
               | explicitly ask for that if you want it. You can even - if
               | you just insist on writing cursed code - which it seems
               | jcelerier is, write your own type in which the index is
               | always unchecked and it is Undefined Behaviour when you
               | inevitably make a mistake. Just implement std::ops::Index
               | and if you also want to _mutate_ these probably invalid
               | indices, std::ops::IndexMut and in your implementation
               | say you 're unsafe and just don't bother doing bounds
               | checks.
               | 
               | You can shoot yourself in the foot with Rust, it's just
               | that you need to explicitly point a loaded gun at your
               | foot and pull the trigger, whereas C++ feels like any
               | excuse to shoot you in the foot is just too tempting to
               | ignore even if you were trying pretty hard not to have
               | that happen.
        
               | colejohnson66 wrote:
               | If you were using std::vector::at (the proper way), you'd
               | have bounds checking as well. One should only direct
               | index if they _really_ know that they are inside the
               | bounds. And in Rust, there 's
               | std::vec::Vec::get_unchecked: https://doc.rust-
               | lang.org/std/vec/struct.Vec.html#method.get...
        
               | jcelerier wrote:
               | > If you were using std::vector::at (the proper way),
               | 
               | it is absolutely not the proper way and a complete anti-
               | pattern
        
               | umanwizard wrote:
               | That depends on the project. Anyway, it's irrelevant,
               | because you can do it either way in either language.
        
               | gavinray wrote:
               | This is the Ossia Score lead dev FYI, he's no stranger to
               | either language
        
               | umanwizard wrote:
               | I don't know what Ossia Score is. Regardless, I didn't
               | mean to imply anything negative about the competence of
               | the person I was replying to.
        
           | zozbot234 wrote:
           | C++ is really struggling with whether or not to break their
           | ABI. But their "identity" is clear enough - much like C, they
           | want to support their existing code, while still opening up
           | support for newer features if possible. Rust could actually
           | benefit from cribbing a few things that are now getting
           | defined in C++, such as their support for heterogenous
           | executors.
        
             | zabzonk wrote:
             | C++ doesn't have a standardised ABI. I'm not aware of any
             | languages that do, but I would be interested in any more
             | information on this.
        
               | seoaeu wrote:
               | There's the widely used Itanium C++ ABI [0], which
               | contrary to the name is actually the one used on x86-64.
               | Without a standard ABI it wouldn't be possible to
               | dynamically link C++ libraries (which includes the
               | standard library!), especially if they weren't compiled
               | with identical compiler versions.
               | 
               | [0]: https://itanium-cxx-abi.github.io/cxx-abi/abi.html
        
               | kllrnohj wrote:
               | C doesn't have a standardized ABI, either, and yet it's
               | the most widely used ABI in the world anyway.
               | 
               | Just because it isn't standardized doesn't mean it isn't
               | stable & relied upon anyway. Clang & G++ are ABI
               | compatible with each other, for example, and more
               | importantly (and relevantly) both libstd++ & libcxx
               | strive to maintain ABI compatibility (
               | https://gcc.gnu.org/onlinedocs/libstdc++/manual/abi.html
               | & https://libcxx.llvm.org/DesignDocs/ABIVersioning.html )
        
               | tambre wrote:
               | > both libstd++ & libcxx strive to maintain ABI
               | compatibility
               | 
               | They don't, but they do keep it stable.
        
               | mst wrote:
               | Alternative phrasing: they strive to maintain "backwards
               | compatibility" rather than "compatibility with each
               | other".
        
               | kllrnohj wrote:
               | For libcxx & libstdc++ yes correct.
               | 
               | Clang, however, does strive to maintain compatibility
               | with G++. So you can build a library with clang & use it
               | from g++. It strives, and for the most part achieves, to
               | be a drop-in replacement for GCC, which includes ABI
               | compatibility.
        
               | legalcorrection wrote:
               | COM and Windows Runtime (WinRT) provide standardized ABIs
               | across multiple languages. With the WinRT language
               | projections, it's just like writing 'normal' code.
        
               | pjmlp wrote:
               | And with C++/WinRT you even get back the experience of
               | how it was like to do ATL development.
        
               | legalcorrection wrote:
               | So I gather that, much more than previous COM projections
               | and templating libraries, C++/WinRT is much nicer to work
               | with. And you can target the WinRT ABI with Rust, .NET
               | (C#, F#, etc.), Python, and JS too.
        
               | pjmlp wrote:
               | I completely disagree, C++/CX was the best that Microsoft
               | ever had closer to C++ Builder and they killed with their
               | office politics.
               | 
               | On top of that, the C++/WinRT folks are adamant to push
               | their east const preference into every Microsoft
               | customer.
               | 
               | If you enjoy editing IDL files without tooling support
               | and merging generated files by hand, please do.
        
               | asveikau wrote:
               | I really didn't like C++/CX from the perspective of the
               | fact that it added weird stuff to the existing syntax of
               | the language, and it had no other compiler onboard other
               | than Microsoft. These two probably killed it more than
               | "office politics".
        
               | pjmlp wrote:
               | It is a framework for doing Windows development on Visual
               | Studio, follows the same syntax as C++/CLI, in use since
               | 2003, it doesn't matter if anyone else is on board.
               | 
               | Even today no other compiler can fit into WinUI/UWP
               | workflows no matter what, unless one is willing to do
               | lots of under the hood workarounds.
               | 
               | Office politics driven by people without any
               | consideration for paying customers.
        
         | Decabytes wrote:
         | > In terms of popularity, depending on which survey you look
         | at, Rust is stalking or eclipsing C++
         | 
         | The full quote is in reference to popularity. Which if you look
         | at the stack overflow developer survey is definitely true
        
         | creatonez wrote:
         | Rust is absolutely _dominating_ the very tiny domain of
         | greenfield OS development.
        
           | Gigachad wrote:
           | It's also made keys steps in to Linux. I haven't checked the
           | latest state, but as of last year it was pretty much approved
           | as the way to write new drivers on Linux.
        
             | tialaramex wrote:
             | Rust for Linux is not landed, and so you can't write Linux
             | drivers in Rust even on Linux Next (the git branch where
             | in-progress work lives before Linus might ship it in an
             | actual Linux kernel)
             | 
             | It's probably of the order of a year out.
        
           | ncmncm wrote:
           | Rust is anyway making a better showing there than other
           | places.
        
         | jwatt wrote:
         | I'm not sure it's "desperately" chasing; its trajectory looks
         | positive. For example, in the 2019 Stack Overflow developer
         | survey[1] only 3% of professional developers reported using
         | Rust. A year later[2] it was 4.8% and a year after that[3] it
         | was 6.4%. So based on that metric (of debatable value),
         | professional developer use may have doubled in two years. For
         | reference, in the SO surveys C++ and C use was about 20% and
         | 16%, respectively and, if anything, slowly declining (as a
         | percentage of respondents, of course).
         | 
         | 1.
         | https://insights.stackoverflow.com/survey/2019#technology-_-...
         | 
         | 2. https://insights.stackoverflow.com/survey/2020#technology-
         | pr...
         | 
         | 3. https://insights.stackoverflow.com/survey/2021#technology-
         | mo...
        
           | kevin_thibedeau wrote:
           | PHP had a positive trajectory too. Rust is riding a wave of
           | interest but most are going to revolt against its complexity.
        
             | [deleted]
        
             | wk_end wrote:
             | That sounds plausible in the general case...but we're
             | putting it up against C++ here, which is at least as
             | (probably more) complex.
        
             | stouset wrote:
             | Rust is literally the most beloved language in SO's
             | developer survey and has been for several years running.
             | 
             | In my own experience, it's allowed me to write software
             | that pretty much _doesn 't have bugs_, and I say this as a
             | 25 year veteran of being an engineer. The extra bits of
             | complexity that are in the language allow me, the
             | developer, to not have to write code to deal with that
             | complexity in my own projects. It's handled for me.
             | 
             | Rust's primary competition is C and C++. It compares
             | favorable on the overwhelming majority of axes against
             | either. Not every one, but most.
        
       | stevefan1999 wrote:
       | BeOS/Haiku and Redox comes to mind
        
         | paride5745 wrote:
         | BeOS and Haiku are mentioned in the article.
        
       | mike_hearn wrote:
       | The article didn't list JNode, but it's also a pure Java OS.
       | 
       | I noticed in another thread that a few people seem to think you
       | can't implement an entire operating system in a GCd language like
       | Java or C#, but that isn't true. You can do it like this:
       | 
       | 1. Use an ahead of time compiler to compile the base
       | runtime/kernel image to static machine code. In managed language
       | operating systems like JNode or Singularity there isn't a strong
       | distinction between kernel and language runtime, so this is the
       | same thing. This base needs to contain at least a GC and probably
       | a JITC, as well as some basic support services. This can itself
       | be written in the managed language.
       | 
       | 2. Write a very short bootstrap loader in assembly like every OS
       | has, which sets things up enough to jump into the entry point of
       | that runtime.
       | 
       | 3. Writing a compiler in a managed language is easy enough but
       | what about a GC? To do this you teach the compiler that some
       | methods are 'magic' and shouldn't be treated as normal method
       | calls. Instead they become either compiler intrinsics that are
       | translated to pure assembly e.g. to read/write raw memory
       | locations, or they are compiled in special ways for example to
       | remove GC safe points.
       | 
       | The current best example of this in action is the GC in
       | SubstrateVM, which is the "VM" compiled into any program AOT
       | compiled with the GraalVM native image tool:
       | 
       | https://github.com/oracle/graal/tree/master/substratevm/src/...
       | 
       | If you flick through it you'll see various annotations and types
       | you wouldn't normally see in Java, like `Pointer` and
       | `@Uninterruptible`. These are recognized by the compiler and
       | affects how the machine code is generated. The language is the
       | same, so all existing tools continue to work - it's not a dialect
       | or subset of Java, it's the full thing, just with slightly
       | modified rules for how the final generated code behaves.
       | 
       | SubstrateVM has one more trick up its sleeve to break the
       | circularity: some objects can be initialized and persisted to an
       | "image heap" at build time. In other words, the GC code can use
       | Java classes to structure itself, despite being unable to
       | allocate.
       | 
       | And that's all it needs.
       | 
       | There have been efforts to do things like this in the past for
       | full operating systems. They have nice properties: for example
       | you can sandbox drivers, IPC overheads goes away because it's all
       | in a single address space, capabilities actually work and are
       | pervasive, and it's quite easy to keep ABIs stable. There are
       | usually a few sticking points that prevent them taking off:
       | 
       | 1. Historically, GCs have either been good at latency _or_
       | throughput but not both simultaneously. Some of them also had
       | trouble with large heaps. That 's a problem because virtually all
       | reasonable computing requires a mix of programs with wildly
       | different sensitivity, most obviously, developers want latency to
       | be prioritized for editing in their IDE but throughput to be
       | prioritized for their build system. If you have one GCd heap for
       | the entire computer then you have two options:
       | 
       | 1a. Pick one algorithm to manage it.
       | 
       | 1b. Do what Singularity did and come up with a quasi-process
       | notion in which each unit has its own GCd heap. Singularity had a
       | nice concept called an 'exchange heap' which allowed objects to
       | be passed between these quasi-processes very fast and cheaply,
       | whilst ensuring that object graph could only be pointed to by one
       | unit at once. This made IPC tremendously cheap, allowed one unit
       | to be paused for GC whilst other units ran, and let them use IPC
       | all over the place. However it did reduce the benefits of using
       | managed languages somewhat as it reintroduced complex data
       | ownership rules.
       | 
       | NB: This is changing now with tech like HotSpot ZGC and
       | Shenandoah (which are written in C++ though). They drive
       | latencies through the floor, it's basically pauseless, and the
       | new not yet released fully generational variants have very good
       | throughput too. Also, G1 GC has monstrous throughput even with
       | low pause times, they just aren't quite as low as ZGC/Shenandoah.
       | 
       | 2. Overheads of managed languages are higher. The successor at MS
       | Research to Singularity was codenamed Midori and not much was
       | ever published about it publicly, but from what was written (by
       | Joe Duffy) it seemed apparent that they went down a rabbithole of
       | trying to make Midori have the same raw efficiency and overhead
       | as C++ based Windows. They got a long way but ended up not having
       | any interesting enough new features to justify the investment and
       | the project was eventually canned.
       | 
       | 3. All the same problems new operating systems always have: no
       | apps, drivers etc.
       | 
       | 4. Spectre attacks make single address space operating systems
       | more complex. The new support for memory protection keys in Intel
       | CPUs could re-awaken this area of OS research however because
       | MPKs let you block speculation attacks within a single address
       | space.
        
         | maxloh wrote:
         | Which was the another thread you read?
        
         | Yhippa wrote:
         | Mike, this is very well-written. Thank you. I grok maybe 40% of
         | what you are saying which is a testament to what you typed out.
         | 
         | Is there a situation where if your sticking points could. E
         | addressed or tolerated where using a GC'd language could shine
         | vs a non one?
        
           | mike_hearn wrote:
           | Sorry it's only 40% :) If you like I can elaborate.
           | 
           | I think there are many cases where GC'd languages can benefit
           | tasks traditionally thought of as 'systems' tasks (I don't
           | personally recognize much distinction between systems
           | programming and non-systems programming). The Graal project
           | is probably the most successful in this area. Like Midori it
           | came out of long term corporate R&D, but unlike Midori it
           | successfully shipped impactful software. They also published
           | papers which the Midori guys never did.
           | 
           | Graal is an implementation of a JIT and AOT compiler for many
           | languages, both source code and byte code based. It can run
           | not only JVM bytecode but e.g. Python, Ruby, LLVM bitcode,
           | WASM, and a whole bunch more, which makes a JVM powered by it
           | easily the most polyglot compiler and runtime systems in
           | history. Languages aren't translated to JVM bytecode, which
           | would introduce impedance mismatches, but rather input to the
           | compiler via a rather interesting technique called partial
           | evaluation of interpreters.
           | 
           | Graal came out of asking the question, what if we wrote a JVM
           | in Java? How can we do that, and if we can, are there
           | benefits? Well, just rewriting something in Java doesn't give
           | any benefits to the end users, just the developers, so to
           | justify this you really have to find ways to really boost
           | productivity a lot and then use that to yield interesting
           | end-user features as well. Midori seems to have failed at
           | this, Graal succeeded.
           | 
           | IMO the primary benefits Graal gets out of being written in a
           | high level statically typed managed language are:
           | 
           | 1. All the usual benefits like GC, great libraries, rock
           | solid refactoring IDEs.
           | 
           | 2. Annotations and the associated annotation
           | processing/reflection infrastructure. The part that makes
           | Graal polyglot is called Truffle and Truffle relies on this
           | feature extensively.
           | 
           | 3. Medium-level program input representation. One thing the
           | Java world got really right is the clean separation between
           | frontend and backend compilers via a stable bytecode format.
           | Bytecode is not too high level, so you don't have to think
           | about the complexities of evolving syntax when reading it,
           | but also not too low level. Graal is of course itself
           | expressed using bytecode and the compiler exploits this all
           | over the place, for instance, it can parse bits of itself
           | into compiler graphs at runtime and then use them as
           | templates. They call this snippets and they use it as a way
           | to lower high level constructs into lower level ones. It's
           | really neat and a boost to compiler development productivity.
           | 
           | 4. Related to that, Truffle relies heavily on that sort of
           | meta-circular reflection capability. Truffle is the way Graal
           | can compile languages that aren't JVM bytecode based. You
           | write an AST interpreter for the language in any language
           | that can produce bytecode (but in reality it's always Java
           | because you need fairly precise control over the output;
           | Kotlin might also work). The interpreter uses the Truffle API
           | to express the AST, in particular it uses lots of
           | annotations. The resulting interpreter is a normal Java
           | program that can run on anything that can interpret bytecode,
           | but the Graal compiler has plugins that recognize when it's
           | compiling a Truffle program and handle it in special ways.
           | 
           | This ability to construct large, complex API surfaces that
           | trigger special compiler behavior is one of the huge
           | productivity wins that allowed the Graal team to add so many
           | languages with such high runtime performance, so fast and so
           | cheaply. It's like compiler intrinsics but taken to the next
           | level, and then the next level again. And the end result is
           | real benefits delivered to end users, for instance, Shopify
           | uses TruffleRuby to get better performance for components of
           | their web app.
        
             | yvdriess wrote:
             | Truffle/Graal sounded almost like magic when we first
             | looked at it. Its partial evaluation was one of the best
             | efforts we've seen for speeding up R, which is notoriously
             | averse to being compiled. (https://www.graalvm.org/r/)
        
         | titzer wrote:
         | > 4. Spectre attacks make single address space operating
         | systems more complex.
         | 
         | I will say, unequivocally, that Spectre actually makes process
         | isolation in single address space operating systems impossible
         | on modern hardware. There is too much speculation and too many
         | leaks, and it's not just branches. We wrote a whole paper about
         | it a few years back.
         | 
         | https://arxiv.org/abs/1902.05178
        
           | mike_hearn wrote:
           | I believe that paper predates the introduction of
           | speculation-blocking MPKs. Could you build a single-address
           | space OS out of those, without hitting problems with Spectre
           | attacks? It's an open research question but my gut says yes.
           | MPKs are limited so you may need an equivalent of swapping
           | with fallback to page table based isolation, but it's worth
           | noting that in a SASOS the notion of a process is unpacked,
           | so you can then add on top newly defined hardware enforced
           | privacy domains that don't cleanly map to any existing notion
           | of a process.
           | 
           | For example all code from a particular vendor (origin) could
           | share a single MPK whilst running, even if the failure domain
           | for things like fault isolation is finer grained.
        
             | titzer wrote:
             | > I believe that paper predates the introduction of
             | speculation-blocking MPKs
             | 
             | That isn't enough, because you can induce misspeculation
             | through paths that _do_ (or would) have access to
             | appropriate MPKs and do almost anything you want, including
             | disclosing information through sidechannels you do have
             | access to. Loading an MPK is akin to changing address space
             | protections; it has to be a hard barrier that cannot be
             | speculated through. You cannot even have code _mapped_ that
             | would have access to those MPKs, as you can induce
             | misspeculation into this code.
             | 
             | > It's an open research question but my gut says yes.
             | 
             | My gut says no. There is just too much dark stuff going on
             | in hardware. Sidechannels are outside of models. You can't
             | verify anything until you have not the model, but the whole
             | design of the chip.
             | 
             | Also, variant 4 is not addressed much in the literature. I
             | couldn't write what I wanted to write because of NDAs, but
             | I have personally written PoCs that basically say hardware
             | has to turn off memory speculation or you end up with a
             | universal read gadget again. There is no software solution
             | for variant 4.
        
               | mike_hearn wrote:
               | I'm told, but haven't verified, that in older Intel CPUs
               | loading an MPK wasn't a speculation barrier, but in newer
               | CPUs it is. In other words changing your current MPK is
               | like changing address spaces but much faster because
               | there's no TLB flush or actual context switch.
               | 
               | I think there are also other caveats to consider. A lot
               | of Spectre research (like your paper) is implicitly
               | focused on the web renderer/V8 use case but here we're
               | discussing theoretical operating system designs. Let's
               | say you sandbox an image decoder library in-process,
               | using type security and without using MPKs. Is this
               | useless? No, because even if the image decoder is:
               | 
               | a. Maliciously doing speculation attacks.
               | 
               | b. Somehow this doesn't get noticed during development.
               | 
               | ... the sandbox means it won't have any ability to make
               | architectural-level changes. It can spy on you but its
               | mouth is sealed; it doesn't have the ability to do any IO
               | due to the architectural sandbox. To abuse Spectre in
               | this context would require something really crazy, like
               | trying to speculatively walk the heap, find the data
               | you're looking for, encrypt it, steganographically encode
               | the result into the images it decodes, and then hope that
               | somehow those images make it back to the attackers even
               | though the destination is probably just the screen. This
               | isn't even NSA-level stuff, it's more like Hollywood at
               | that point.
               | 
               | Compare to the situation today: the image decoder (or
               | whatever) is a buggy C library running in a process with
               | network access because it's a web origin. Game over.
               | 
               | I worry that the consequence of Spectre research has been
               | that people conclude "in-process sandboxing is useless,
               | cross-process is too hard, oh well, too bad so sad".
               | Whereas in reality in-process sandboxing even without
               | MPKs or equivalent would still be a massive win for
               | computer security in many contexts where Spectre is
               | hardly your biggest problem.
        
               | titzer wrote:
               | > I worry that the consequence of Spectre research has
               | been that people conclude "in-process sandboxing is
               | useless, cross-process is too hard, oh well, too bad so
               | sad". Whereas in reality in-process sandboxing even
               | without MPKs or equivalent would still be a massive win
               | for computer security in many contexts where Spectre is
               | hardly your biggest problem.
               | 
               | Well, I agree that in-process sandboxing is still quite
               | useful; it at least closes the barn door. But the rest of
               | the conclusion is not what we made in Chrome; we had to
               | go whole-hog multi-process for site isolation. That and
               | just moving as much as possible out of the renderer
               | process so that there aren't many secrets left to steal.
               | 
               | It's really an issue for situations where a process (or
               | platform) is _required_ to run untrusted code from lots
               | of different sources. There isn 't a software solution
               | that is robust to side channels yet. They can still spy
               | on each other. Clearly, two import cases that Google
               | cares about are Cloud and the web.
        
         | mprovost wrote:
         | > I noticed in another thread that a few people seem to think
         | you can't implement an entire operating system in a GCd
         | language like Java or C#, but that isn't true.
         | 
         | Both Smalltalk and LISP were used to write operating systems
         | decades ago.
        
         | sigzero wrote:
         | jOS was another Java OS.
         | 
         | http://jos.sourceforge.net/
        
         | pjmlp wrote:
         | Regarding Midori, besides the blog posts, Joe Duffy did two
         | talks about the subject,
         | 
         | "RustConf 2017 - Closing Keynote: Safe Systems Software and the
         | Future of Computing by Joe Duffy"
         | 
         | https://www.youtube.com/watch?v=CuD7SCqHB7k
         | 
         | "Safe Systems Programming in C# and .NET"
         | 
         | https://www.infoq.com/presentations/csharp-systems-programmi...
         | 
         | In one of them, he mentions that even with Midori proving its
         | value to the Windows team, they were quite dimissive of it.
         | 
         | It appears to have also been yet another victim of the usual
         | DevDiv vs WinDev politics.
        
         | zozbot234 wrote:
         | > you can sandbox drivers, IPC overheads goes away because it's
         | all in a single address space, capabilities actually work and
         | are pervasive, and it's quite easy to keep ABIs stable.
         | 
         | You can do these things with WASM, which has no GC and simply
         | manages memory segments on a per-module basis.
        
           | mike_hearn wrote:
           | The point of a single address space OS is that you can pass
           | pointers/references between modules without requiring any
           | form of marshalling, nor introducing memory safety problems.
           | 
           | WASM cannot do this because it's meant to be a target for C
           | and C-like languages. Either you have to make one WASM
           | address space contain all your software, in which case it can
           | easily corrupt itself internally (the sandbox is useless
           | because it contains everything), or, you have to re-introduce
           | a process-like concept that gives you isolated memory spaces,
           | at which point it's not a single address space OS anymore.
        
             | zozbot234 wrote:
             | Address space is entirely orthogonal to memory protection.
             | You can have multiple protected tasks in a single address
             | space, or multiple address spaces sharing blocks of
             | physical memory among themselves with different virtual
             | addresses, or any combination.
        
               | mike_hearn wrote:
               | Yes, you could configure your memory maps so they never
               | overlap and then call it a single address space, but if
               | passing pointers between realms doesn't work then why
               | bother? You didn't get any real benefit. The point of
               | using a unified GC is that you can actually do this: just
               | call a method in another protection domain, pass a
               | pointer to a huge object graph, and you're done. There's
               | no need for concepts like SHM segments or IPC
               | marshalling. Even if you segmented your address space and
               | then used classical process-like context switching, you'd
               | still need all those things.
        
               | zozbot234 wrote:
               | > but if passing pointers between realms doesn't work
               | then why bother?
               | 
               | Because then it can work? It's a matter of what virtual
               | addresses each "realm" has access to, either reading,
               | writing or both.
        
               | mike_hearn wrote:
               | I don't think I quite follow what you have in mind.
               | 
               | If there are two realms or protection domains or whatever
               | we want to call them, but there is memory protection in
               | place to prevent reading/writing of others when one is
               | active, you can pass a pointer from one to the other and
               | the other knows it's not belonging to itself. But the
               | moment that receiver tries to read it, it'll segfault. Or
               | what are you imagining happens here?
               | 
               | It seems to me like to solve that you have to copy data,
               | not pointers. Now you have marshalling.
               | 
               | There's a second problem with trying to solve this with
               | WASM - C and the associated ABIs don't handle evolution
               | all that well. But part of what you need in a single
               | address space OS is the ability for components to evolve
               | independently, or semi-independently. In particular you
               | need the ability to add fields to structures/objects
               | without needing to recompile the world. Ideally, you'd
               | even be able to modify structures in memory without even
               | restarting the software. Higher level VMs than WASM can
               | do this because they provide higher level semantics for
               | memory layouts and linkage. You can evolve a JAR in much
               | more flexible ways than you can evolve a binary C/rust
               | module, or at least it's a lot less painful, which is why
               | Win32 is full of reserved fields, and most attempts at
               | long-term stable C APIs are full of OO-style APIs like
               | GObject or COM in which structs are always opaque and
               | everything has to be modified via slow inter-DLL calls to
               | setters.
        
               | legalcorrection wrote:
               | I think the piece you're missing is the continuing role
               | of the page tables or similar functionality in such
               | systems. You can have a single address space, i.e. a
               | particular address can only ever refer to the same
               | memory, while still determining that only certain
               | processes are allowed to access that address. In such a
               | system, the page tables would always have the same
               | mapping to physical addresses no matter what process
               | you're in, but the read/write/execute bits on the page
               | table would still change as you context switch.
        
               | mike_hearn wrote:
               | That's exactly what I understood from the proposal too,
               | but I don't see why that is useful, nor why it'd be worth
               | implementing with WASM.
               | 
               | Perhaps it's worth stepping back. The reason SASOSs are
               | always written in managed languages like C# or Java
               | [dialects] is that they're trying to solve several
               | problems simultaneously:
               | 
               | 1. IPC is slow due to all the copying and context
               | switching.
               | 
               | 2. Beyond slow it's also awkward to share data structures
               | across processes. You need SHM segments, special
               | negotiations, custom allocators that let you control
               | precisely where data goes and which are thread safe
               | across processes etc. Even if you do it, you need a lot
               | of protocols to get memory management right like
               | IUnknown. So in practice it's rarely done outside of
               | simple and special cases like shared pixel buffers.
               | 
               | 3. Hardware processes conflate several different things
               | together that we'd like to unpack, such as fault
               | isolation, privacy, permissions etc.
               | 
               | 4. Hard to evolve data structures when code is compiled
               | using C ABIs.
               | 
               | and so on.
               | 
               | Simply creating non-overlapping address spaces doesn't
               | help with any of these things. Even if all you do on a
               | context switch is twiddle permission bits, it doesn't
               | matter: you still need to do a TLB flush and that's the
               | bulk of the cost of the context switch, and at any rate,
               | you can't just call a function in another address space.
               | Even if you know its address, and can allocate some
               | memory to hold the arguments and pointers, you can't jump
               | there because the target is mapped with zero permissions.
               | And even if you go via a trampoline, so what, the stack
               | holding your arguments also isn't readable. If you fix
               | that with more hacks, now any structures the arguments
               | point to aren't readable and so on recursively.
               | 
               | So you end up having to introduce RPC to copy the data
               | structures across. Well, now what if you want a genuinely
               | shared bit of state? You need some notion of handles,
               | proxies, stubs, and that in turn means you need a way to
               | coordinate lifetime management so different quasi-
               | processes don't try to access memory another process
               | freed. That's COM IUnknown::AddRef. Then you need ways to
               | handle loosely coupled components that can be upgraded
               | independently. That's COM IUnknown::QueryInterface and
               | friends. And so on and so forth.
               | 
               | In a SASOS all that goes away because the compiler and GC
               | are tightly integrated, and they don't let you
               | manufacture arbitrary pointers. You don't have to do
               | refcounting or marshalling as a consequence, you can
               | evolve the ABIs of components without breaking things,
               | you can create capabilities easily and cheaply, and so
               | on.
               | 
               | As discussed above, speculation is a pain because it lets
               | you break the rule of not crafting arbitrary pointers,
               | but there are caveats to that caveat. I'm not actually
               | convinced Spectre kills SASOS though you do need to do
               | things differently.
        
               | legalcorrection wrote:
               | Why can't it be that whatever procedure you use to
               | give/get a pointer into another process also makes the
               | necessary modifications to the page table? As you point
               | out, this would become very tedious to the programmer if
               | you just tried to bolt it on to current languages as a
               | library, but I can imagine, e.g., a version of Java or C#
               | that makes this all mostly seamless.
               | 
               | As for what the benefit is, I think you can at the very
               | least get rid of needing to copy data back and forth.
               | 
               | Not that I'm an advocate for single address space OS's.
               | I'd have to think about this more. You might be right.
               | I'm playing devil's advocate to think it through, not to
               | defend a position, if that makes sense.
        
               | mike_hearn wrote:
               | Sure.
               | 
               | Well, pages are coarse grained so you'd end up giving the
               | other quasi-process access to more stuff than it should
               | have. And you'd have to flush the TLB so you pay the
               | context switch cost anyway, at which point why bother?
               | The reason operating systems make overlapping mappings is
               | (classically) to enable better memory sharing due to not
               | needing relocations or GOT/PLTs. That's all irrelevant
               | these days due to ASLR (which doesn't even work that well
               | anymore) but that was the idea.
               | 
               | You can do some tricks with using special allocators for
               | the stuff you want to reveal that places the data in SHM
               | segments, then blit the stack across to the other process
               | and it can work. I know this because I built such a
               | system as my undergrad thesis project :)
               | 
               | https://web.archive.org/web/20160331135050/plan99.net/~mi
               | ke/...
               | 
               | It's very ugly though. And again, you need to coordinate
               | memory management. For FastRPC it didn't matter because
               | it was used mostly for holding stuff temporarily whilst
               | you called into a library, so the 'outer' process owned
               | the memory and the 'inner' process just used it
               | temporarily. I never did anything with complex lifetimes.
               | 
               | One way of thinking about it is to study the issues that
               | cause people to write large JVM apps instead of large C
               | apps. It's not any different at the systems level. They
               | want GC that works across all the libraries they use,
               | they want to be able to upgrade the backend compiler
               | without frontend-recompiling everything, they want to be
               | able to upgrade a library or change a memory layout
               | without recompiling the world, and they don't want all
               | the goop that is triggered by allowing libraries to use
               | arbitrary compilers and memory management subsystems.
               | Forcing a unified compiler and GC simplifies the inter-
               | module protocols so drastically, the wins are enormous.
        
               | legalcorrection wrote:
               | > _Well, pages are coarse grained so you 'd end up giving
               | the other quasi-process access to more stuff than it
               | should have._
               | 
               | Good point. Embarrassing oversight on my part. My whole
               | mental model of how this would work has come crashing
               | down. Now obvious to me that to have it work the way I
               | envisioned, you would need a managed-code only
               | environment that supervises all memory accesses.
               | 
               | > _I know this because I built such a system as my
               | undergrad thesis project_
               | 
               | Very cool!
        
         | rev_d wrote:
         | There's a USENIX article from a year or two ago about the
         | "Biscuit" research OS, which was written in golang.
         | 
         | There were clear compromises & performance degradations related
         | to using a GC'ed language, but it definitely was interesting
         | enough that you hope for more.
        
       | [deleted]
        
       | [deleted]
        
       | jleyank wrote:
       | If they're discussing historical OS's, which I think they were, I
       | thought VMS was written in BLISS. That one was sorta important,
       | and I recall "Ignorance is BLISS, BLISS is ignorance" T-shirts.
        
         | lproven wrote:
         | Hi. Author here.
         | 
         | It's not all historical stuff by any means; in fact, I tried to
         | skew it towards stuff from the recent or modern era and things
         | that are still in maintenance, still being worked on, or
         | actively sold.
         | 
         | And, yes, I did consider VMS, but the article was getting too
         | long already and while BLISS does qualify, it's also relatively
         | obscure. Maybe I made the wrong call there: it's in current
         | use, on sale, and about to become generally available on
         | x86-64. Ah, well.
        
           | jleyank wrote:
           | Google sea that openvms is still used. Talk about inertia...
        
             | lproven wrote:
             | "Google sea"?
             | 
             | VMS is alive, well, and about to ship a new version.
             | 
             | https://vmssoftware.com/about/openvmsv9-1/
             | 
             | It is exceptionally solid, it has the best clustering ever
             | invented for any OS in history, and above all: if it ain't
             | broke, _don 't fix it._
        
       | namdnay wrote:
       | I wouldn't say Symbian was C++ - I remember it being a sort of
       | intermediate step between C and C++. There were no exceptions, no
       | STL, and many other weird quirks
        
         | t43562 wrote:
         | C is still C without libc and python is still python even if
         | you can't "import os, sys" so why does lack of the STL matter
         | to C++ ? Symbian used a standard C++ compiler and mandated a
         | certain style of programming because C++ with STL and
         | exceptions wasn't actually safe on small machines with limited
         | memory. No exceptions were allowed in the kernel IIRC and new
         | had to return an error code rather than throw an exception
         | because handling an out of memory exception required....spare
         | memory.
        
       | ok123456 wrote:
       | Very big omission of TempleOS. It was written in HolyC.
        
       | trashburger wrote:
       | Hmm, they didn't list SerenityOS[0] under the C++-based operating
       | systems for some reason... maybe it's still too under the radar?
       | 
       | [0]: https://serenityos.org/
        
         | eatonphil wrote:
         | I don't think it's any more under the radar than Redox or Tock
         | listed in the article.
        
         | dang wrote:
         | Discussed yesterday:
         | 
         |  _SerenityOS Browser now passes the Acid3 test_ -
         | https://news.ycombinator.com/item?id=30853392 - March 2022 (141
         | comments)
         | 
         | Lots more at https://news.ycombinator.com/item?id=30858768
        
         | LordDragonfang wrote:
         | Nor do they mention Google's upcoming Fuchsia OS, whose Zircon
         | Kernel is written almost entirely in C++. While not quite
         | "beloved" yet, it generates substantial buzz every time it hit
         | the HN front page.
        
       | [deleted]
        
       | mal10c wrote:
       | This took me down memory lane but in a weird way. One of the
       | first languages I really took to was vb6. I was absolutely
       | convinced I could write an OS with that language... I tried and
       | tried - really not knowing what I was doing and finally realized
       | its limitations. Such a good lesson on using the right tool for
       | the job.
        
       | Tozen wrote:
       | Article forgot to mention that Niklaus Wirth was a consultant for
       | the team at Apple that created Object Pascal. Apple had used
       | variations of Pascal and Object Pascal for early Macs. This was
       | in addition to companies using Wirth's Modula-2 and Oberon.
       | 
       | Part of the reason why C became so prevalent is it being created
       | within and backed by AT&T (one of the largest companies in the
       | world back then). They pushed C and Unix everywhere, it took
       | hold, and here we are today.
        
         | glouwbug wrote:
         | We could have as easily lived in a world where we all
         | programmed Go because Google pushed gUnix should they have been
         | the industry leaders in 80s, or something like that.
        
       | tremon wrote:
       | Do these operating systems also use a non-C calling convention
       | for libraries?
        
         | ncmncm wrote:
         | It is common for an OS to use a non-C protocol for actual
         | system-call traps, but also unfortunately common not to
         | document, support, or maintain those, so users are obliged to
         | call a provided C library for to use them.
        
         | steveklabnik wrote:
         | Hubris, the Rust OS I work on, is... aggressively static and
         | doesn't have dynamic linking (or loading, in fact), but the
         | kernel ABI is non-C, yes:
         | https://hubris.oxide.computer/reference/#_syscall_abi
         | 
         | (We use it in Rust via inline assembly stubs.)
        
       | jnxx wrote:
       | I think Modula-2 was also quite influential in one of the main
       | programming languages for modern industrial PLCs, called
       | Structured Text. One of its features are lightning fast compile
       | times compared to C++.
        
       | Decabytes wrote:
       | It would be fun to try and make a scheme based Kernel/OS. My
       | reasoning is that older revised reports document a much smaller
       | Scheme language than r6rs and r7rs so would be easier to
       | implement in asm. Then once you have a working Scheme you can
       | build on top of it
        
         | wglb wrote:
         | And start bootstrapping with sector lisp
         | https://justine.lol/sectorlisp/
        
       | greenyoda wrote:
       | The article notably omits Multics, which was written in PL/I:
       | https://en.wikipedia.org/wiki/Multics
       | 
       | Multics, first released in 1969, was a major influence on Unix.
       | From the Wikipedia article:
       | 
       | > _Multics was the first operating system to provide a
       | hierarchical file system, and file names could be of almost
       | arbitrary length and syntax. A given file or directory could have
       | multiple names (typically a long and short form), and symbolic
       | links between directories were also supported. ... It was also
       | the first to have a command processor implemented as ordinary
       | user code - an idea later used in the Unix shell. It was also one
       | of the first written in a high-level language (Multics PL /I),
       | after the Burroughs MCP system written in ALGOL._
        
       | Koshkin wrote:
       | > _Wirth a go_
       | 
       | They should rename Oberon to Wirth.
        
       | butlerm wrote:
       | > C fans tend to regard BCPL as an unimportant transitional step,
       | but it was used in two celebrated OSes. One was the TRIPOS
       | operating system, later used as the original basis of AmigaOS.
       | 
       | The latter is a bit of an exaggeration. Tripos related code
       | written in BCPL was used for "AmigaDOS" - meaning the filesystem
       | driver, the command line shell, a few bits of process control,
       | and a variety of generic command line utilities. It was not used
       | for the kernel (Exec), or graphics support, or the gui library
       | (Intuition), or the graphical shell (Workbench), or lower level
       | device drivers, which were all written in C or 68K assembly.
       | 
       | The Tripos derived parts were nice though, generally nicer than
       | the MSDOS equivalent and somewhat friendlier than the Unix
       | command line, if the filesystem was a little slow, comparatively
       | speaking.
        
       | hulitu wrote:
       | As far as i know MS windows was written in C++. DomainOS (Aegis)
       | was written in Pascal.
        
       | abnercoimbre wrote:
       | We asked Walter Bright at Handmade Seattle [0] what he thinks of
       | a future with non-C ABIs. He makes the case we must all accept: C
       | is deeply entrenched and all-encompassing.
       | 
       | That's not to discourage creative efforts -- it's more like "be
       | aware this is 10x bigger than Mt. Everest"
       | 
       | [0] https://vimeo.com/652821195#t=10m52s
        
       | skissane wrote:
       | Also z/OS (formerly known as MVS) -large chunks of it are written
       | in an IBM-internal-use-only PL/I dialect called PL/X.
       | 
       | The core of the AS/400 operating system, OS/400, the Licensed
       | Internal Code (LIC), used to be written in another IBM-only PL/I
       | dialect, PL/MP. In, the 1990s, while porting the AS/400 from CISC
       | to RISC, they rewrote all the PL/MP code into C++. But IBM has
       | another private dialect of PL/I called PL/MI, which was used to
       | write the higher level part of OS/400, the XPF - basically PL/MI
       | compiled to the virtual machine bytecode but PL/MP compiled to
       | the machine code of the physical hardware. From what I
       | understand, parts of the XPF are still written in PL/MP even in
       | the latest versions of OS/400 (now called IBM i OS), although
       | newer components tend to be developed in C/C++ instead. Other
       | parts of the XPF were written in Modula 2, and I believe there is
       | still some Modula 2 code surviving in the most recent versions as
       | well.
       | 
       | IBM has had even more secret proprietary PL/I variants. The long
       | defunct IBM 8100 line's DPPX operating system was a written in
       | PL/DS. Another dialect, PL.8, used to be used to write IBM's
       | compilers (although I believe it has now been replaced by C++)
       | and also some of the firmware for the mainframes. IBM even wrote
       | a GCC front-end for PL.8, although it appears they never released
       | it.
        
         | deepspace wrote:
         | Speaking of PL/I, Intel made a few operating systems in the
         | late 70s / early 80s written in their dialect of PL/I called
         | PL/M. There was ISIS, which ran on their microprocessor
         | development stations, and iRMX, the real time O/S running on
         | the target microprocessors.
         | 
         | Having used both, ISIS was quite a bit more advanced than
         | 'competitors' like DOS and CP/M at the time.
        
           | skissane wrote:
           | > Speaking of PL/I, Intel made a few operating systems in the
           | late 70s / early 80s written in their dialect of PL/I called
           | PL/M
           | 
           | PL/M was created by Gary Kildall, creator of CP/M, and CP/M
           | 1.x was written in PL/M. In CP/M-80 2.x, they rewrote the
           | kernel (BDOS) and command processor (CCP) in 8080 assembly to
           | improve performance, but utility programs were still written
           | in PL/M. Some later CP/M ports, such as CP/M-68K and
           | CP/M-8000, were written in C instead.
           | 
           | Wikipedia says that IBM used PL/M too - to write some of the
           | firmware for the CISC AS/400s (the Service Processor).
        
         | wglb wrote:
         | Here is a trivia question for you. What language was the first
         | optimizing compiler written in?
        
           | pinewurst wrote:
           | It was the initial IBM FORTRAN written in 704 assembler. Very
           | much an optimizing compiler.
        
             | wglb wrote:
             | Not quite.
             | 
             | The idea of "basic blocks", key to optimizing compiler, was
             | invented by the team that wrote the Fortran I compiler in
             | Fortran I. See https://ucla-
             | biostat-257-2020spring.github.io/readings/fortr...
        
               | rst wrote:
               | The first Fortran I compiler is the one pinewurst was
               | referring to, and it was written for the 704 -- in 704
               | assembly. Source code is here -- this is Fortran II
               | (basically Fortran I plus provision for separately
               | compiled subprograms), but obviously still assembly: http
               | ://www.softwarepreservation.org/projects/FORTRAN/index.h.
               | ..
               | 
               | (The article in the course reading you cited also
               | correctly states that the compiler was written in
               | assembly, for the 704.)
        
           | Tao331 wrote:
           | IIRC this is the punchline of a story about Seymour Cray
           | programming a BIOS in octal via front switches and
           | blinkenlights. Or somewhere in that ballpark. It's a person,
           | so the answer is DNA.
        
             | wglb wrote:
             | Nope. This happened before Seymour was at Control Data.
        
             | javajosh wrote:
             | Surely a more accurate answer would be "Cray's bookshelf".
        
         | the_only_law wrote:
         | I actually don't mind PL/I. Always wondered one they needed a
         | ton of derivative proprietary languages. I think I'd almost
         | prefer language bloat.
        
           | zozbot234 wrote:
           | PL/I is a kitchen sink language already.
           | 
           | Modern languages tend to minimize the amount of features that
           | they provide in the language itself, and do as much as
           | possible in their standard libraries.
           | 
           | (This also goes together with simplified syntax, because
           | user-defined complex syntax is hard, slow and potentially
           | ambiguous, whereas limiting verbose, "readable" syntax to
           | just a handful of language-provided features is just silly.)
        
             | nobody9999 wrote:
             | >PL/I is a kitchen sink language already.
             | Speaking as someone who has delved into the
             | intricacies of PL/I, I am sure that only Real Men
             | could have written such a machine-hogging,        cycle-
             | grabbing, all-encompassing monster.              Allocate
             | an array and free the middle third? Sure!         Why not?
             | Multiply a character string times a bit string and
             | assign the result to a float decimal? Go ahead!
             | Free a controlled variable procedure parameter and
             | reallocate it before  passing it back?              Overlay
             | three different types of variable on the         same
             | memory location? Anything you say!              Write a
             | recursive macro? Well, no, but Real Men use         rescan.
             | How could a language so obviously designed and
             | written by Real Men not be intended for Real Man
             | use?
             | 
             | Heh. Heh. Heh.
             | 
             | [Source: http://www.anvari.org/fortune/Miscellaneous_Collec
             | tions/3620... ]
        
               | Koshkin wrote:
               | Looks like a perfect language to write an OS in!
        
               | kps wrote:
               | The design criteria are as follows:              1.
               | Anything goes. If a particular combination of symbols
               | has a reasonably sensible meaning, that meaning will be
               | made official.
               | 
               | https://dl.acm.org/doi/10.1145/363707.363708
        
         | shakna wrote:
         | > IBM even wrote a GCC front-end for PL.8, although it appears
         | they never released it.
         | 
         | Oh, how I had hoped I had scrubbed PL.8 from my memory.
         | 
         | "80% of PL/I." Only missing everything that made it bearable to
         | use PL/I. No interrupts. You get ITERATE but no LEAVE
         | statement. No STATIC, EXPORT or PACKAGE. You do get DEFINE...
         | But not the one in other IBM PL/? langs. Incompatible.
         | 
         | The two weeks I spent debugging an interbank transferring
         | program IBM wrote for them decades ago was one of the least
         | pleasant experiences I've had when actually having access to
         | the source code (albeit printed on five reams of paper, rather
         | than digital). Give me pre-standard COBOL or FORTRAN over PL.8,
         | any day.
         | 
         | Though, to be fair, the version of PL.8 I was granted access to
         | was the original compiler, only. Not the updated one used for
         | z/Arch firmware, today. Which I think solves a lot of those
         | things. And I do mean the original compiler. The very, very
         | first version.
         | 
         | I said no interrupts? Most of IBM's PL/? langs will signal when
         | they run out of memory, so you can do something intelligent to
         | kick the never-allowed-to-go-down mainframe into gracefully
         | continuing to crunch endlessly (like clearing up part of a
         | queue, and re-requesting it from a previous point). That signal
         | is missing. So instead, you have developers build their own
         | systems of heuristics to guess if a memory allocation had
         | failed. Heuristics that had begun to fail, after an old network
         | card burned out and was replaced with a similar one... But a
         | faster, more modern, one. Faster hardware is the bane of old,
         | hard-coded software.                   DCL IntVar INTEGER BASED
         | (Cursed)
        
           | skissane wrote:
           | > The two weeks I spent debugging an interbank transferring
           | program IBM wrote for them decades ago was one of the least
           | pleasant experiences I've had when actually having access to
           | the source code (albeit printed on five reams of paper,
           | rather than digital). Give me pre-standard COBOL or FORTRAN
           | over PL.8, any day.
           | 
           | Interesting. I didn't realise PL.8 was used to write
           | application software. I knew about it being used to write
           | compilers, firmware, etc. If customer applications were
           | written in it, did this mean they actually shipped PL.8
           | development tools to customers? I thought it was always IBM-
           | internal-only.
        
       ___________________________________________________________________
       (page generated 2022-03-31 23:00 UTC)