4
ainsclark
32d

C or Go? Next language to learn.

Comments
  • 2
  • 12
    C. Used everywhere, not going away.
  • 3
    Ask Ken Thompson
  • 6
    What do you want to do with the new language?
  • 0
    @Fast-Nop I’m looking something that’s more performant, build extensions, dabble with some API’a and micro services. Perhaps a templating language is my first port of call.
  • 6
    Why not Rust though
  • 10
    @ainsclark That doesn't sound like a good fit for C. You use C if you need to go close to the hardware with only minimal assembly, or if you need shit to be really fast.

    BUT! remember Conan, the secret of steel isn't the sword, it's the hand wielding the sword.

    SImilarly, C isn't fast just because C compilers are awesome (which they are), but because C programmers breathe performance like a tuned muscle car spits fire through the exhaust.
  • 1
    Go, fits with your purpose above

    C is an old man. Should be retired for software that needs every last CPU cycle squeezed out of it
  • 0
    @Fast-Nop thanks 😀

    What example small projects can you think of the top of your head that would require to be closer to the machine level?
  • 2
    @Fast-Nop C is faster than most everything out there but it has its limitations too. Aliasing rules kill a lot of party tricks for compiler engineers etc. but it’s not as bad as c++.
  • 2
  • 0
    @FrodoSwaggins

    Let's do something Multi thread.

    Yes your code in C will outperform my C#.

    But it will take me 1 hour instead of 5 days
  • 1
    @NoToJavaScript also an old man, and not an option for OP

    Go is better that C# anyways
  • 2
    @ainsclark Either something that is on OS or driver level, or for going bare metal on embedded systems. Both of them require also quite some domain knowledge.

    A nice toy project for making it fast just on application level would be the N-queens-problem for variable board size.
  • 1
    @FrodoSwaggins Aliasing isn't as bad as it sounds because you can always switch it off, or you can move the aliasing into another translation unit and work with void pointers. That's e.g. how to write a fast memcpy.

    And yeah, C++ is good when you would like to use C, but your work is so trivial that you suffer from bore-out and need to spice it up with an insane language.
  • 4
    @NoToJavaScript Threads are easy in C if your problem is either trivial to parallise, or if mutexes won't be a performance bottleneck.
  • 0
    @Fast-Nop Ok here you go. Very trivial problem.

    You have an array of strings containing more than 10.000 ips. You need to ping them all, but not more than 420 at the time.
    (Why would some one want to ping 10.000 ips ? For the same reason some one bought 57 cabbages in your math problem at school)

    You can only use standard libraries.

    Takes 1 line in C#. (Well, 4 with full definition of method and result class)
  • 1
    @NoToJavaScript That's more about standard library functions than multi-threading.

    So to make it an 1:1 comparison, I'd also assume that some C library is available which does the whole pinging stuff as API function. I'm sure there's something on Github already.

    What remains is launching 420 worker threads, which is easy in a loop, implementing a fetch-next-IP function from the array, which works with a mutex so that all threads can just access that with no race condition, and joining the threads.

    There's no way that this would take 5 days.
  • 0
    @Fast-Nop No, it would not take 5 days. My C is rusty as hell (Last time used it was when I was homebrewing some PSP stuff, for fun).
    But I’m pretty sure, myself, I can do the whole exercise in less than a day and I count IDE choice and try/errors.
    But it is so, so easy to write c#, it’s just insane. (And I’m coming from asm, pascal, GWBasic world).
  • 1
    @NoToJavaScript Here's a real life example, just because I had that already floating around from another rant. What it does is factorise a 64 bit integer using N threads in parallel, both handed over als CLI arguments.

    https://pastebin.com/D2bYY5k6

    Took me like 2 hours to bang out, and without the optimised divider part, it would have been considerably less.
  • 1
  • 4
    Rust: A langauge that is universally loved by developers. Get the performance of C and the comfort of a modern high level language. With tight integration with the web technologies you'll be future proof and highly sought-after.
    https://www.rust-lang.org/
    Rust Programming Language
  • 1
    @Fast-Nop

    This is so much code.
    Sorry, but these kind of lines are not for me :

    @highlight
    uint64_t a = *((uint64_t *) ptr_a), b = *((uint64_t *) ptr_b);
  • 0
  • 1
    @NoToJavaScript It would be less code if the 64 bit integer and the number of threads were given in the source text instead of parsing that along with proper error messages, and if the division routine just tested every odd number instead of avoiding divisions both by 2 and 3. But that would be like 25% slower or so.

    Also, the pointer casts could be rewritten like below, and the compiler would generate the same code. But once you're familiar with pointer-heavy code, you won't need that.

    @highlight
    uint64_t *ptr_u64_a = (uint64_t *) ptr_a;
    uint64_t *ptr_u64_b = (uint64_t *) ptr_b;

    uint64_t a = *ptr_u64_a;
    uint64_t b = *ptr_u64_b;
  • 0
  • 1
    @Fast-Nop That I can understand 😊 As I said, my C is like 8 years old of “not using”
  • 2
    @NoToJavaScript I’m very productive in c/c++. I would say most problems I could solve quicker in c than the average engineer in c#.

    This only becomes less true if GUIs get involved. But the world has enough trash GUIs that suck as it is, they don’t need me making more of them.

    Being able to work fast, and not over design solutions are two factors to mention.
  • 0
    @Fast-Nop I think you’re thinking of something else. Aliasing cannot be turned off and the boundaries between translation units amplifies this problem because you can’t inline anything.

    This would not allow you to write a fast memcpy either, void* won’t help either and type punning is generally another category of problem in c.

    The aliasing problem is this:

    Int x = 1;
    func(&x);

    What is the value of x now?

    Basically any time addresses are passed to another translation unit your IR has to flush everything to memory before making the call and then reload it again afterwords. If you can inline the function and prove that it does not write to the address of x, then suddenly you can constant propagate and allow x to remain live across the calling of that function which is awesome.

    This example doesn’t demonstrate the most serious problems with this, but you can imagine how this starts to suck a shit ton more with more clever code. Basically there are too many things that are likeness barriers in c and c++ to do the most offensive (but awesome) IR reductions. And that’s because everything has side effects and those side effects are visible everywhere and aliasing and the things the language promises related to it is a big reason why.
  • 1
    @NoToJavaScript I have a library of tools that I use, other people have written networking libraries for c. You can definitely do this in a pretty small amount of code. Even if you write all the socket code yourself it’s not exactly short but I’d be done in less than 20 minutes.
  • 0
    To get a job fast, learn Go
    To learn programming and understand how everything works, from operating systems to most programming languages (php is in C, python is in C, Rust & Go were written in C before the bootstrap, ...), learn C.
    Programming in C will make you a better programmer in other languages (Rust too will make you a better dev)
  • 0
    @MagicSowap I don't know if that is low enough actually. Assembly teachers you about memory segments how it all works in from heap to stack and calling conventions. I would start there if your want an understanding. After that you will almost never make common mistakes/inefficiencies involving memory allocation and addressing.

    That is not the goal of the OP however. I think Go will suit his needs. If not Rust is more interesting but C is more relevant.
  • 1
    @Fast-Nop you rang?

    you mad man. look what you've done. you've started the cycle all over again...
  • 2
    Go, I've kinda fallen in love with it and a lot of small stuff can be done really quickly with it
  • 0
    C then Go why not just learn both? They’re both great!
  • 1
    @FrodoSwaggins Aliasing doesn't mean handing pointers around. It means that changing some *float lets the compiler assume that a *int hasn't changed.

    You can turn that off using either e.g. -fno-strict-aliasing (GCC), or bypass it by moving the aliasing into another translation unit with a *void conversion in the function parameters.

    Especially for numerics where everything is *float or *double and therefore can alias, that's a performance problem compared to Fortran where no aliasing is allowed, that's why C99 introduced the "restrict" qualifier.
  • 1
    @Fast-Nop it’s the same problem but you’re right that you can at least do damage control with no strict aliasing. And that option is why type punning is dangerous (and explaining this to people who are doing it is wildly frustrating). c guarantees everything and that’s kind of it’s weakness too.

    But generally speaking aliasing still has to do with any time a reference is taken and then something with unknown side effects is run.

    But you only have this problem if you take the address of something still. C doesn’t guarantee that out of bounds writes or clobbering the stack will do something sane because it doesn’t guarantee relative addresses for a lot of things, or that they even have addresses at all... until you pass the address of one of those things out of your translation unit, but even that I believe is more of an implementation detail. When you assign a pointer, if you want it to do something sane dereferencing it the standard requires that you assign it to an instance of something.
  • 1
    @FrodoSwaggins Aliasing is about two pointers pointing to the same memory, writing via one of them, and reading via the other. Not about side effects.

    That is guaranteed to work as intended only if the pointer types are compatible. If they are incompatible, like float and int, it's undefined behaviour.

    And that makes sense because it avoids useless reloads, which helps performance. That's also why "restrict", to avoid these useless reloads even when dealing with compatible pointer types.

    However, I agree that it's a bit dangerous because there's not necessarily a warning. I recommend to benchmark whether switching off strict aliasing really slows down the application. If it doesn't, I leave strict aliasing switched off at least for release.
  • 0
    @Fast-Nop @FrodoSwaggins

    I am a bit curious on how you filter / sort data records in C. Talking in memory sorting, not DB related. It’s not to argue “better” or “worse”, but I would be interested to seem some code
    Obviously, there is already a lib which can do equivalent of Array.Sort. But how do you implement, let’s say, sort by TimeStamp descending, then by first name and last name ?
    In c# I currently use about 3 different sorts (Personal p[reference for method 2 as it’s very readable, more than others). The 3d has advantage to NOT create new list object
  • 0
  • 0
    @NoToJavaScript See the example I linked previously, line 253. It uses the comparison function in line 191, which can do anything you like.

    That's how you do it in C if it isn't absolutely performance critical for this part because the comparison function call cannot be inlined. Otherwise, you write your own sorting function.

    C++ doesn't have this issue when using templates, of course.
  • 3
    Go with C
  • 1
    @Fast-Nop youre outlining the points I made in my first post. I don’t think we disagree here.

    Not being able to guarantee that something doesn’t have a reference to something you are working on is part of side effect modeling. Side effect modeling is generally what state of the program can change from doing a given thing and are you going to honor it. And generally speaking unless you can inline all places where references leave your translation unit you can’t guarantee it, but there is more to side effect modeling than just aliasing rules.
  • 1
    Learn Go brahh
Add Comment