4 ms·
Unrelated but related: Doing systems programming in Java actually makes me appreciate all the little things C does to ensure your program run correctly.
by marginalia_nu 3y ago
Unrelated but related: Doing systems programming in Java actually makes me appreciate all the little things C does to ensure your program run correctly.
- virgilp 3y agoLike, what? Honest question. I can think of a few things that Java does (bounds checking, for one), but very few things that C does. (also, not entirely sure what you meant. There isn't a canonical C compiler, or toolset, and the language itself really doesn't do anything to prevent you from shooting yourself in the foot)
- marginalia_nu 3y agoLike having unsigned integers and pointers. Java makes you do pointer arithmetic with all signed integers that all have the same type as every other integer in the program.
- afandian 3y agoWhat do you mean by pointer arithmetic in Java? Real pointers in FFI? Or array indexes?
- marginalia_nu 3y agoOffsets in files and mapped memory. None of this is done through Java objects or arrays, but rather by reading data directly from memory or disk and manually keeping track the data's type and structure.
- deely3 3y agoAnd how exactly C is better in these situations?
- marginalia_nu 3y agoIt has pointer types and unsigned integer types.
- shrx 3y agoIf you're using pointers in Java you're doing something wrong
- marginalia_nu 3y agoIf you're going to do this sort of low level database-adjacent work in Java, this is basically how you need to do it. It's pretty unpleasant and the language resists you in every way, but luckily in most cases it's only a small core of the program that needs to be written this way. Well, that or JNI/FFI in some C code I guess.
- mike_hearn 3y agoDoes the new Panama memory API help? There are new pointer-like classes for indexing into memory mapped files. Also, Kotlin has unsigned integers. So you could use that for the parts of your code that benefit from it.
- marginalia_nu 3y agoIt helps in the sense that it's no longer necessary to slice up the file into individual 2 GB byte buffers, though I'm not really using MemoryLayout/StructLayout much yet to do structured access. Haven't made sense of how to use that part of the API well yet.
- deleted 3y ago[deleted]
- vsnf 3y agoHearing that C has assists for program correctness is, shall I say, unexpected to say the least. What kinds of things are you referring to?
- ignoramous 3y ago> What kinds of things are you referring to? Pointer arithmetic, I imagine. Elementary math after all.
- eddd-ddde 3y agoProbably the things C does not do? No messy vtables, no exceptions, no vm, etc. If you just do less stuff it's less likely you do something wrong.
- elteto 3y agoYou trade that off by a healthy dose of foot guns and UB. And a non-existent standard library that encourages NIH write-my-own for the most common data structures. C barely does anything and it has a stark beauty of its own, agreed. And yet it is incredibly hard to write secure code with it.
- af3d 3y agoDeveloping robust programs in C just requires a clear understanding of the language itself (and of course a good overall skill set as a programmer). I have been writing (mostly) bug-free code in C for over twenty years. My only real complaint is that it forces you to write lots of "boilerplate". Beyond that, it is a fine language for systems programming (provided you know what you are doing). I have had many more issues working with scripting languages (I'm lookin' at you, Java and Ruby!) where the bugs existed not in my program, but in the VM itself. Having said that, I do enjoy working with higher-level abstractions.
- elteto 3y agoYou found one compiler bug after moving to a new version of your compiler/runtime. Not unheard of, to be honest. Now think of all the common bugs you _didn’t_ get in all these years because you wrote your code in Java instead of C.
- marginalia_nu 3y agoI'm mostly referring to the fact that half the debugging was spent on a wild goose chase combing through integer types. With unsigned integers, type aliases and pointer types this would have been a lot easier to keep track of. The limited range of primitive integers also means static analysis is basically impossible. Assing a pointer to an integer or vice versa and that's a code smell. Assign an integer to an integer and the compiler is none the wiser.
- elteto 3y agoI think you went on a wild goose chase _because_ it was a compiler bug. You never assume "it's the compiler" on the first try, so you go looking for bugs in your code that don't exist. Java's integer types maybe didn't help in this situation, agreed. And the lack of unsigned integers is harebrained, agreed too. But I think you wouldn't have had an easier time in C. You say that the lack of unsigned types in Java is in part responsible for some of your wasted time. But C has notoriously bad integer types and promotion rules, especially for interactions between signed and unsigned! If you had found this same bug in C code (a compiler bug), your first instinct as a C programmer might have been "it's probably some signed/unsigned interaction issue". And you'd also have wasted time trying to find a non-existent issue in your code.
- kragen 3y agoentirely by coincidence, i have spent a substantial part of the night finding signed/unsigned bugs in my c code by carefully reading through the disassembly, so i endorse this message
- int_19h 3y agoC# is perhaps a better example, as it does have unsigned integer types, but it also does the sensible thing by e.g. promoting mixed int/uint operands to long. If you try to assign the result of such an expression to either int or uint without casting, it's a compile-time error.
- kamov 3y agoSorry, I don't want to be that guy, but I'm curious why use Java and not something like Rust? Is it because of the Lucene ecosystem?
- marginalia_nu 3y agoThe short story is I'm productive in Java, and I enjoy its mature ecosystem and stable APIs. Systems programming is awkward, but it's also a very small part of the project and for what it is, an interesting challenge. What I'm building is what Lucene does (i.e. document indexing) and then the rest of the search engine as well including crawling and serving traffic.
- YoshiRulz 3y agoHave you ever tried Kotlin? For non-system-level stuff on the JVM, it's IMO a direct upgrade to Java. `value class` for type aliases, `when`, and better null handling. But then, modern Java is doing all that stuff too, I hear.
- int_19h 3y agoHave you tried C# for those kinds of things? It's normally the same level of abstraction as Java, and has similarly mature ecosystem with stable APIs, but it also has unsigned types, unmanaged data and function pointers (with pointer arithmetic), unions, the equivalent of alloca etc for when you need to go low-level.
- mrkeen 3y agoI did this. I previously worked at a search engine which did its index building and querying in C, with its higher-level stuff (web-apps, scheduling, tooling, etc.) in Java. Later when I built my own version, I started with C for the low-level and Haskell for the high-level. I made a few iterations in C, but eventually rewrote it in Rust, and I was pretty happy with that choice. I was more familiar with C, and it was a really good fit for what I was writing. Terms and Documents just become termIds and docIds (numbers) sitting in indexes (arrays). Memory-mapping is a really comfortable way to do things: files are just arrays; let the OS sort out when to page things in and out of disk. But where C fell down for me was in the changing the code. The meaning of the data&code were lost in nested for-loops and void-function-pointers, etc. Rust gave me a better shot at both writing and rewriting the code. Java for the low-level was a non-starter for me for a few reasons, but the biggest two were startup time and difficulty of the mmap api (31-bits of address-space for a file? c'mon!).