Live data from Hacker News

SectorC: A C Compiler in 512 bytes

xorvoid.com

61–70 of 82 posts

Re: SectorC: A C Compiler in 512 bytes

#61
post #57
post #48

Earlier quoted context omitted.

An interpreter with a JIT compiler is able to do more optimizations because it has the runtime context to make decisions, while a AOT (ahead of time) compiler will not know anything about what happens at runtime. This is why some JIT'd languages (like Javascript) can be sometimes faster than C.

Can you give some simple example for the folks in the back of how JIT'd languages can be faster than C? I think most people are under the impression that statically compiled languages are "always faster."

Honestly it always depends on what "faster" means for you. For one crowd faster means "fast number crunching" (e.g. anything AI these days). There statically compiled code reigns supreme because it is mostly about how fast your very specialized code (e.g. matrix multiplications) runs and it does not hurt if you just ship a specialized, statically compiled version for all possible targets. (iirc GCC does something like that when building generic code that will utilize different code sets (SSE,AVX,etc) when they are available at runtime.

For another crowd "fast" means that the code they haphazardly thrown together in an interpreted language runs fast enough that nobody is negatively affected (which is a completely valid usecase, not judging here).

And to answer your question for examples:

An interpreter with JIT compiler might for example notice that you have a for loop that always gets run with the same number of arguments, unroll the loop and at the same time vectorize the instructions for an immediate 4x gain in execution speed.

Otoh Javas Hotspot JIT compiler tracked how often code was called and once a "hotspot" was identified compiled that part of the program.

Last example: if you are using an interpreted language (say Python) every roundtrip through "python-land" costs you ... A simple for loop that just runs a simple instruction (say: acc = 0; for x in xs: acc += x) will be orders of magnitudes slower that calling a dedicated function (numly.sum(xs)), JITing that code (e.g. with numba) will remove the roundtrip through python and achieve similar speeds.

Re: SectorC: A C Compiler in 512 bytes

#62
Amazing!

I think this, from the conclusion, is the real takeaway:

> Things that seem impossible often aren’t and we should Just Do It anyway

I certainly would never have tried to get a C compiler (even a subset) so small since it my instinct would have been that it was not possible.

Re: SectorC: A C Compiler in 512 bytes

#63
post #57
post #48

Earlier quoted context omitted.

An interpreter with a JIT compiler is able to do more optimizations because it has the runtime context to make decisions, while a AOT (ahead of time) compiler will not know anything about what happens at runtime. This is why some JIT'd languages (like Javascript) can be sometimes faster than C.

Can you give some simple example for the folks in the back of how JIT'd languages can be faster than C? I think most people are under the impression that statically compiled languages are "always faster."

The sufficiently smart JS compiler might be faster.

Re: SectorC: A C Compiler in 512 bytes

#64
post #57
post #48

Earlier quoted context omitted.

An interpreter with a JIT compiler is able to do more optimizations because it has the runtime context to make decisions, while a AOT (ahead of time) compiler will not know anything about what happens at runtime. This is why some JIT'd languages (like Javascript) can be sometimes faster than C.

Can you give some simple example for the folks in the back of how JIT'd languages can be faster than C? I think most people are under the impression that statically compiled languages are "always faster."

This is all in theory. Everyone says this like it's already here but it's really not (in the sense that these fast jits are still mostly worse than well-written C).

But what it is is mostly choosing optimizations based on runtime characteristics. It's a dynamic analogue to profile-guided optimization. Like you might have an optimization that trades code size for CPU cycles, which you could choose not to do at runtime if you're low on memory bandwidth instead of CPU time. Stuff like that.

Re: SectorC: A C Compiler in 512 bytes

#65
post #57
post #48

Earlier quoted context omitted.

An interpreter with a JIT compiler is able to do more optimizations because it has the runtime context to make decisions, while a AOT (ahead of time) compiler will not know anything about what happens at runtime. This is why some JIT'd languages (like Javascript) can be sometimes faster than C.

Can you give some simple example for the folks in the back of how JIT'd languages can be faster than C? I think most people are under the impression that statically compiled languages are "always faster."

https://www.youtube.com/watch?v=WLwTlC1R2sY -- How slow is Javascript really? Javascript vs C++ (Data Structures & Optimization)

Re: SectorC: A C Compiler in 512 bytes

#66
post #45
post #18

Earlier quoted context omitted.

The TCC step seems unnecessary. If you've got a SectorC C compiler sufficient to compile TCC, it can probably compile the bootstrap compiler used in GCC's 3 stage build process. The bigger issue is probably getting the ancillary tools up and running (a shell, make, coreutils, ...) https://gcc.gnu.org/install/build.html

The method described in the page you reference, does not exclude the possibility that the compiler you start with, contains malicious code, and recognizes that it is compiling the GCC code base. It is not true bootstrapping as described in [0]. If you read through [1] you will see that even getting a fairly recent version of TCC to compile is not that simple. [0] https://bootstrappable.org/ [1] https://bootstrapping.…

At that level of a paranoia, there's no guarantee that the CPU doesn't contain a malicious method for detecting and modifying compiler builds, so you better build your own CPU out of TTL chips ;)

Re: SectorC: A C Compiler in 512 bytes

#67
post #10

Earlier quoted context omitted.

wonder how many extra bytes for structs?

In my experience, probably at least a 200-400 lines of C (another 512 bytes minimum? I don't know the conversion). The problem is not just declaring structs but accessing them, referencing them, accessing/referencing fields and subfields, etc. That has to all be in the syntax. For such a minimal project you can ignore initialization. I did all this while adding maybe 500 lines of C to GitHub.com/vitiral/fngi. Never t…

Once upon a time, when += was spelled =+, struct members in C were global names whose "values" were the offsets from the beginning of the struct[1]; a.b is simply a[ptrtab[b]] and a->b is a[0][ptrtab[b]].

[1]: This is why all of the names of struct members in unix are "needlessly" prefixed; i.e. struct stat.st_mode is not struct stat.mode because that could conflict with struct foo.mode until the early 1980s.

Re: SectorC: A C Compiler in 512 bytes

#68
post #57
post #48

Earlier quoted context omitted.

An interpreter with a JIT compiler is able to do more optimizations because it has the runtime context to make decisions, while a AOT (ahead of time) compiler will not know anything about what happens at runtime. This is why some JIT'd languages (like Javascript) can be sometimes faster than C.

Can you give some simple example for the folks in the back of how JIT'd languages can be faster than C? I think most people are under the impression that statically compiled languages are "always faster."

In theory, some execution sequences are not knowable except at runtime which could be optimized after the code has already been running for a while.

In practice, static AOT compilation is essentially always faster for a couple reasons. The various types of overhead associated with supporting dynamic re-compilation usually aren't offset by the gains. Re-compiling code at runtime is expensive, so it is virtually always done at a lower optimization level than AOT compilation to minimize side-effects. CPU silicon is also quite good at efficiently detecting and optimizing execution of many of these cases in static AOT code. You can also do static optimization based on profiling runtime execution, which is almost (but not quite) the same thing with more steps.

Re: SectorC: A C Compiler in 512 bytes

#69

Now they just need to port something like oneKpaq to 16 bit or maybe something from the extremely tiny decompressor thread [1], just to test compression level to get an idea kpaq on its quickest setting(taking minutes instead of what could be days on its highest) reduced SectorC to 82.81% of its size, of course adding the 128 bit stub knocked it to 677 bytes. It would be interesting to try it on the slowest takes day…

I once tried making a 1kb binary to see what I could fit in, once you've got to the point of considering compression there isn't much ordered data left to compress. I worked it out to be a ~10 byte saving.

Re: SectorC: A C Compiler in 512 bytes

#70
post #60
post #56

Earlier quoted context omitted.

C has a bit of a history with interpreters and reduced implementations (not to devalue SectorC which is absolutely cool). I'm thinking Small C Interpreter for CP/M: http://www.cpm.z80.de/small_c.html an interpreted version of https://en.wikipedia.org/wiki/Small-C

The book that had the Cain/Hendrix "Small C" compiler, runtime library, assembler and tools was a fantastic resource that taught me C and compiler construction at the same time. In general, reading (lots of) source code is a good way to learn how to do things in a new language, i.e. to move from the lexical and syntactical level to the level of idioms for problem-solving. On reflection, I find it strange that in prog…

Small C was the inspiration for SubC, a project of mine. It is pretty much a cleaned-up and slightly extended rewrite of Small C that compiles with few warnings on modern compilers. Also comes with a book.

http://t3x.org/subc/index.html (source code)

http://t3x.org/reload/index.html (book)

Post reply on HN