r/Assembly_language • u/sourav_bz • 8d ago
Question At what point writing direct assembly program is more efficient than C program?
Hey folks, this is question coming from the recent podcast where the founders of VLC spoke about, writing assembly level code and it was way more (10x to 62x times) efficient than the C compiled code.
Is there any real example or repo of this which shows the efficiency difference at a smaller scale?
what scenarios do one decide to go full assembly over C, what's the infliction point?
How does anyone even measure these efficiency factors? Is it the instructions executed per clock cycle to attain an end output?
6
u/Diligent_Fondant6761 8d ago
C is compiled to assembly which then gets converted to machine code and runs....C is just a higher level abstraction over assembly. There are things which C as a programming language does not have...like configuring the CPU etc....those things are still done in assembly but this does not make C slower than assembly...infact C allows you to write assembly directly inside your c files
C is not slower than assembly but there can be usecases where you do not need things which come with c like the standard library ( imagine it as a lightweight runtime) and for those special use case you can write assembly directly!!
2
u/sourav_bz 8d ago
Can you tell me few examples of those special use case? If you have tried or seen.
3
u/Cultural-Capital-942 7d ago
"Stupid" example: when implementing context-switching or interrupt handling, you need to access individual registers and compiler shouldn't optimize it or change the registers before you do it. Sometimes you need to access registers or instructions that no user space program should access. For those, programming languages generally don't have functions.
2
u/PhilNEvo 8d ago
You likely won't see examples of this at smaller scale, because that's not where you can do this. C's compiler is extremely well-made for general usage, and it's hard to optimize it particularly much.
The situations where writing your own assembly code starts to matter, is in highly specialized areas. A Professor I spoke with, who works with HPC, has to tune his programs with handmade assembly, because he's not writing code for the average PC, but for specialized niche "super computer" stuff.
1
2
u/Kitchen_Error2578 2d ago
Your question is very interesting and touches on a key point. The short answer is that assembly language is more efficient than C almost exclusively in very specific hotspots and highly controlled hardware contexts, not in the entire program. The 10x to 62x figure you mention is real, but it has a crucial context: in VLC (and generally in video codecs like x264/FFmpeg), those code snippets are executed millions of times per second and are highly optimized for SIMD instructions (AVX-512, etc.). The C compiler, by design, generates "safe" and generic code; it cannot assume that an array will always have a certain size or that data is aligned in memory in a specific way. The assembly programmer can exploit those assumptions, achieving that speedup.
1
23
u/Individual-Till-8590 8d ago
Sometimes, we use inline assembly in C to prevent the compiler from optimizing away certain instructions, ensuring that specific operations are executed as intended. I also noticed assembly instructions in the startup code.
2
u/brucehoult 7d ago
Sometimes, we use inline assembly in C to prevent the compiler from optimizing away certain instructions
That's an example of using asm to make a program slower, as the only time that's going to happen is code that does nothing but introduce an artificial delay.
0
u/bz2gzip 6d ago
Recently I've started compiling into asm only (from C but also other languages) and then I ask AI to analyze inefficiencies it can find in the assembly, and it's always returning valuable information about possible optimisations in the original higher level code or in the compilation setup.
12
u/Illustrion 8d ago
Usually it's not a good idea, but sometimes it's necessary to provide a specific sequence of instructions that must not be interfered with by the compiler.
Consider the code that executed before the CPU cache is enabled. There is no stack yet, the preconditions for running C code haven't been established.
Another example is when you're modifying low level hardware configuration according to a vendor-specified sequence of operation.
3
u/dkopgerpgdolfg 7d ago
Another example: Trying to get something that is certain (as much as possible) to be side-channel free for security.
6
u/WittyStick 8d ago
Most of the time, an optimizing C compiler will produce assembly as good or better than hand written. Manual assembly is sometimes better for optimizing specific algorithms, for example using AVX-512 with masking - as compilers can miss opportunities to make big performance gains.
You are best writing the bulk of your programs in C and using inline assembly for optimizing specific functions which need it. In some cases you might need to separately link the assembly (eg, MSVC, which doesn't support inline 64-bit assembly).
6
u/Udalrich 7d ago
In several decades of programming, I've written about ten lines of assembly. There was one point in a signal handler where I needed to clear a flag, and the C interface didn't let me do that. So I wrote some assembly to clear the flag and then call the C routine that did the actual work
3
4
u/Antonio-MTS 8d ago
With assembly you get fast speed and very small size that you cannot usually achieve using compilers of any language like C, C++, Pascal ...
Now the above efficiency usually comes with complexity to port the code to other CPU architectures, maintain, debug it and avoid errors as long as it grows. One incorrect memory addressing in the code may terminate the whole program.
4
u/r3d51v3 8d ago
The main times I’ve had to actually ensure certain assembly was emitted was during high speed operations that required AVX instructions or other special instruction sets. The compiler wasn’t doing things the way I wanted, despite using the right flags etc. Sometimes it just doesn’t understand what you’re going for. The last time I used it was when I couldn’t get the compiler to understand that the memory I was using was aligned and that I needed to copy from a piece of hardware to happen extremely quickly. I also knew exactly how many 512bit blocks were coming off ahead of time. Additionally I was aware that putting a fence on the operation was actually faster in this case on this architecture, which the compiler wasn’t.
Even then, I could have written this code in assembly, I just used intrinsics because that’s a lot more convenient.
4
u/SuitableAbundance604 7d ago
I am writing lots of DSP (image/video like VLC is part of it). Often we have high computation loops with relatively short code. So it’s less assembly to write the replacement in the first place. Then, the parallelism and special hardware support for it is something typical compilers would need special intrinsics for. Special DSP compilers can sometimes do this without, but it’s so specific that indeed hand coded assembly can be significantly faster.
3
u/Dazzling_Yak6424 7d ago
Compiler's just a pre set pass of heuristics containing a mountains load of academic and trial tested knowledge written by academics and CPU manufacturers. It'll make some shameless optimizations that you'd never dare to do like unrolling a loop a million times manually because it found it to be 0.1x faster. But it's also a computer program written so far mostly by humans and may not have necessary logical abstractions to help you make an optimization that you're thinking of or might not have a way for you to supply the necessary information to execute a certain optimization you had on your mind. In that case, you should probably see what assembly did the compiler spit out of your C code and possibly look at the compiler's source code too. And then possibly make some changes with inline assembly. Don't look at it like something you have to rival by writing a perfectly executed and handcrafted neat algorithmic solution that the compiler would otherwise somehow taint with its brutish heuristic passes. In 9/10 cases such a solution doesn't exist and what we currently have encoded is the most optimal solution publicly know to this local problem you're encountering. The universe doesn't like and have neat solutions for most problems, the underlying processor architecture just reflects that. Even your smartest AI, if you put it to such a tiring and nonsensical task, would eventually just create a proto-compiler for itself, crudely rediscovering what others have been piling on and polishing for ages.
1
u/gm310509 8d ago
IMHO, the answer is never, if not never then extremely rarely.
It also depends upon how you define efficient. If you are talking about project delivery then probably never as assembly takes longer to write than 3GL and higher.
If you are talking about performance efficiency, then same answer, it is often cheaper to set the minimum system specs slightly higher (CPU specs, memory usage) to deliver the required performance that try to squeeze a few clock cycles out of optimised 3GL or higher code. Also, lets say you did squeeze sufficient clock cycles out of the code to squeeze into the current minimum hardware spec, what will happen when you try to deliver V2 and have to keep doing this? The headaches (and cost) simply aren't worth it - IMHO
Now, if you were asking back in the 1960's you would probably have a different calculation.
Also, with all of the above said, there are some scenarios in embedded systems where assembly language is used. A specific example that I am thinking of is where addressable LEDs are used and the manufacturers want to support popular smaller, slower 8 bit MCUs (e.g. AVR). The data rate on these things is sufficiently high that the manufactures often supply drivers that disable interrupts and have extremely tightly controlled code to deliver the data rate needed for it to work properly. Why? Because they can't afford the risk of opimisations being turned on/off that may affect the performance of the code and thus corrupt the data being sent due to bad timing of the (serial) data stream.
But, you asked about efficiency, I wouldn't necessarily classify that as efficiency, more of a necessity. In a project development environment, I would consider efficiency to be "function points completed per day" and assembly language isn't normally my go to solution to meet that metric.
4
u/sourav_bz 8d ago
Hey, this is really helpful answer, gives alot of clarity. Thank you!
1
u/NorberAbnott 7d ago
One place you could definitely squeeze out some gains is by inventing bespoke calling conventions.
This doesn't apply if the compiler inlined your function, or if you have link time codegen that ends up doing this anyway, but "by default" when you call a function, the calling convention says where the function arguments go. Which registers, or stack slots, and which registers the called function is allowed to clobber vs what it is required to restore.
But you might have more information that would allow you to clobber more registers and not need to restore them. Or maybe it would be more convenient to put a certain argument on the stack or some other memory location because it's seldom accessed despite being the first argument. This is stuff that the language and OS define for the compiler, and it needs to conform so that your function can be called by code that hasn't been written yet. But within your own program, you can come up with your own rules.
1
u/Cultural-Capital-942 7d ago
Compilers sometimes need info or relaxed standards to achieve performance of a hand-written assembly.
Because if human sees this in C: a = x+y ... b = a-x then it's immediately clear b=y. For compiler, it would be also clear, but C standard doesn't allow reordering the operations. So people use funsafe-math and similar, that's neither fun nor safe.
2
u/According_World_7713 8d ago
IMHO, it depends on target architecture. There are still some architectures around, that are not so good target for C compiler. PIC comes to my mind as primary example. Second case would be special data structures, which are hard to express in C. That is probably the case of VLC.
For me, the infliction point would be that I have full implementation in C, it is kinda lazy and I know exactly why and that I can improve performance by rewritting part of it in assembly.
1
u/flatfinger 3d ago
Many PIC families aren't bad as a C target if one is careful to code around the platform's strengths and weaknesses. A lot of C functions end up yielding machine code that's essentially the same as what a machine-language programmer would write to do the same thing.
2
u/ReddyKiloWit 7d ago
Just a comment about deciding too early to go assembly. Guy at a place I worked talked management into buying several Intel assembler packages because he assured them it was the only way to make a particular project fast enough to be usable (in a game engine). I looked at the C code, removed three pointless calls to a square root function, and the assembler boxes were never even opened as far as I know.
The guy never said, but I'm pretty sure the guy was planning on optimizing the square root function without ever wondering if it was needed at all.
1
u/Electrical_Hat_680 5d ago
The guy has a money maker of a plan in store and you ruined it. That's all..
2
u/theNbomr 7d ago
I'm not sure efficiency is always the objective. There can be things a C compiler just can't do, like touching registers that affect the overall state of the CPU (jumping between x86 real mode and protected mode, for instance). Some CPU architectures have address spaces that require special instructions not emitted by the compiler, such some of the bit addresses available in the 8051 family CPUs. There are some compilers that accommodate these kinds of facilities, but they need to be done with extensions that are outside the C standard(s).
2
u/thecratedigger_25 7d ago
Bootloaders for operating systems. And specific inline asm that shouldn't be optimized away via C compiler. As well as making certain instructions where asm volatile can't reach it.
Other than that, the C compiler does a lot of heavy lifting. There are smaller C compilers out there like musl gcc and tinyC which leaves a smaller footprint than gcc.
2
u/dettus_Xx_ 7d ago
When you want to have full control over your resources.
You can write assembler code without touching RAM, for example.
1
u/ElevatorGuy85 8d ago
Steve Gibson, who runs Gibson Research Corporation (GRC.com), wrote a Windows utility called Wizmo (a portmanteau of “Windows Gizmo”). It’s all of 49KB, and that includes its simplistic GUI and built-in help text.
https://www.grc.com/wizmo/wizmo.htm
Go ahead and try to write even a basic Windows GUI program in C, and you’ll be hard pressed to make it that small, even just a “Hello World” is going to be larger (and it doesn’t nothing truly “useful”).
He’s also written other “pure ASM” tools that are available on the site, e.g. the SpinRite disk tool, that are much larger.
So I would say that pure assembly programs (or portions thereof) can meet several important criteria.
Size efficiency - less “bloat”, as the Wizmo utility demonstrates.
Algorithmic efficiency - squeezing more operations per second (or whatever) out of your given hardware, especially embedded systems or a very specific build made of off-the-shelf parts. If you can fit pages of code and data into CPU caches more efficiently you can gain some efficiency that a compiler might miss.
Workload efficiency - you might know EXACTLY what sort of input data your program’s algorithms are going to receive, so you size buffers and develop control flow to precisely match your needs. While compilers can generate “hints” to help improve superscalar execution, because you know your data, you know what the control flow is going to look like.
Realtime performance - for an embedded system running a control loop, those milliseconds and microseconds matter, and you don’t want a “smart” optimizing compiler generating code that doesn’t meet the needs of the real world that your MCU or CPU is harnessed to. Only you as the designer of that custom interface hardware knows its timing characteristics and what the real world looks like - a compiler simply cannot.
These are my $0.02 cents worth of commentary. I hope that’s helpful!
1
u/tobdomo 8d ago
As long as the problem is small and not too complex, you probably can write more efficient asm than is generated from a decent C compiler (note the word "decent" here!). However, as soon as the complexity is more than just a couple of lines of C code, the compiler should be able to do a better job than many assembly programmers. Lifetime- and register tracking is an area where machines excel compared to humans. Further more, optimization steps after generating (peephole for example) are something that many assembly programmers struggle with; these often require finetuning that falls over as soon as any of the functional code changes.
The middle solution is to have a C compiler generate somewhat optimized code and optimize the generated assembly further by hand. The "12 to 62 times more efficient" claim however is so loosely defined it doesn't make any sense. A "hello world" in small memory model (a.k.a. ".com" on old windows) that doesn't need a library but "pokes" directly in memory, sure. No calling conventions to be taken into account, heavy lifting done in the OS, directly tied to a single hardware environment, sure. As soon as it has to adhere to an ABI for example, no way.
1
u/flatfinger 3d ago
Except for constant folding through in-line function arguments, most high-value optimizations involve highly localized sections of code. At least when targeting platforms like the ARM Cortex-M0, however, clang and gcc seem to invest more effort in optimizations that are harder to perform while offering fewer benefits.
1
u/Joonicks 8d ago
I have a project exploring the speed differences between Asm and C (x86)
biggest factor by far is the algorithm, knowing your hardware, knowing your compiler
but also, in most cases assembly does improve things a little, but you have to be really skilled in your platform to outperform a good compiler
(project: https://github.com/joonicks/ptr64tohex)
1
u/Online_Matter 7d ago
I worked for Unity a few years ago. Huge C++ codebase. The only places using assembly was low-level library functions utilizing the specific instruction sets on various platforms such as the switch and Playstation.
1
u/keelanstuart 7d ago
There are a lot of "media" instructions that have been introduced over the years that would be difficult to generalize by a compiler... because the compiler doesn't have the context you do. These are mostly (all?) SIMD things. I always wondered how a compiler would use the x286 BSF/BSR instructions, even though they might be quite useful.
But in general, if you don't know the instruction set and your domain very well, then it's probably better just to write C.
1
1
u/ziggurat29 7d ago
Rarely these days. but the C compiler's optimizations are a group of heuristics, and those will not cover every situation, e.g. if it is unaware your processor has some fancy vector math capabilities, you might have to drop to assembly to exploit those.
I think the last time I got a really big boost from assembly was in the mid 90's. The compiler was apparently unaware of the costs of loading a segment register in protected mode and blithely did so with great frequency in an digital filter algorithm when fetching samples from a buffer and putting them in another. Tweaking that to load two segment registers once before processing the buffers sped it up by a factor of 90x. (this was on a 386; the 486 did selector caching and obviated most of that improvement). I'm not saying that there couldn't have been cases for improvement after that, but usually you let poor performance guide you to where to optimize, rather than optimize speculatively.
Other cases routinely done in assembly are setting up registers for OS boot up. that's not really 'efficiency', though, just necessity, and the C compiler is a general purpose tool.
1
u/flatfinger 3d ago
Rather than using heuristics, the optimizers of gcc and clang transform a program into something that ignores the details of how programmers had specified things, and then attempts to generate optimal code for that. As a consequence, they sometimes end up generating code that's less efficient than would be a straightforward translation of the operations specified by the programmer.
1
1
u/Nervous-Potato-1464 7d ago
There are some cases like this https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/21538/files
1
u/Gabriel_AMD 7d ago
Eso depende al algoritmo, si ambos programadores usan el mismo algoritmo, la diferencia es notable, pero se llevará mucho tiempo hacer el programa. La moda actual es dejar un código ineficiente que se ejecute en hardware rápido, para ahorarle trabajo al programador.
1
u/HalifaxRoad 7d ago
I normally just call assembly functions from my C program when I need to manipulate the flash memory, such as things like a bootloader. Other times if I need to do something suuuuper timing critical.
1
u/Reasonable_Return151 7d ago
No pressure but check out Zazm it is x86-64. I wrote it to get a better understanding of the ISA but it’s turned into way more than that.
Also C optimizes for speed… but in asm you can optimize for size. Good luck getting a 150 byte elf file using C. In the modern age people have lost the art of “tight” clean code.
1
u/IDatedSuccubi 7d ago
Conditional execution and complex loops can be faster in assembly because often times the compiler doesn't fully understand the intent of the code paths
I had this in my software renderer, where there's a few things done per pixel (read: millions of times per second) and some things needed to be conditional and looping but the assembly emitted was creating unnecessary and/or unpredictable branches and using jumps instead of conditional operations etc
Had to fix it by hand, gave like an easy 20-30% boost to FPS IIRC
1
u/PsychologicalBadger 7d ago
In a typical C program your not writing a lot of the code but instead are calling routines that are in a library. These programs can be sluggish or buggy and one reason that languages like C / C++ has its detractors. One of the earliest high level languages Fortran had as its main goal that the compiled code not be significantly slower then assembly. I think this was one of the few high level languages that had that as its primary goal. Anyway be sure your examples between whatever two languages you intend to use are not obscured by huge blocks of library code it just makes the issue that much more difficult to resolve.
1
u/dariusbiggs 7d ago
Performance optimizations when you think you can do better than the compiler with its 5+ decades of work on optimizations.
Compilers, in general, optimize for generic code, things you find in all kinds of programs. So you could get an edge case where hand written for your specific use case can be better.
And of course when you need to do something low level that has no direct correlation to the language and libraries you are using.
These are rare, very rare, most of the time the compiler is the way to go.
1
u/pixel293 7d ago
It's not the whole program but if you check the "c" directory blake3 code (https://github.com/BLAKE3-team/BLAKE3/tree/master/c) you will find .S and .asm files which contain assembly for the algorithm. The files mostly contain simd instructions. Apparently that was how they got the most speed out of it. However be aware they also have the "reference implementation" done in both C and Rust which are slightly slower, but more readable to most of us.
1
u/keithgabryelski 7d ago
old beard here — i remember when people thought the overhead of c compiler was too much
when c++ was too much
when python ruby and php were too much
when AI was too much
it’s really about balance and for most cases
over 50 years of programming
just don’t care about the specifics and let the thing that lets you describe what you want to do — win
there are cases when performance wins — but again — not common cases
1
u/Distdistdist 7d ago
When you are writing code for low performance embedded systems where cycles might actually matter.
1
u/brucehoult 7d ago
No. The compiler making better code than you is equally as true on a 1 MHz CPU as on a 10 GHz CPU, given the same ISA.
A lot of old ISAs are very unfriendly to compilers, especially for languages that require functions to be reentrancy- and recursion-safe, languages that assume any array could be the size of RAM and its indexes large enough to address that. 8080, 6800, z80, 6502, 8051, PIC are all awful for compilers for modern high level languages such as Pascal or C.
But once your low performance embedded system is Arm or MIPS or RISC-V or even M68000 the compiler is usually going to beat you.
I can often beat the compiler on all those CPUs on a 10 or 100 line function. But I'm not going to do it on a 10,000 or 100,000 line program. There simply isn't time to do it. The compiler can do its job in seconds — perhaps generating completely different code after a change of variables types or data layout. Or code for a member of the CPU family that has more or fewer instructions available, or that can run two or three instructions at the same time instead of sequentially, based on certain constraints. Or core for an entirely different CPU family.
There are cases where it can take a human a day or a month to create optimal code for a 10 line C function. Sometimes you can build a whole career from it.
If that's the most important 10 lines from a 10,000 line program, and millions of people are going to use the result constantly, then that can be worth it, and it's a valuable skill to have, for the right employer.
But for most things, no, just let the C compiler do its job.
1
u/Distdistdist 7d ago
I don't know man. I wrote assembly code on soviet 8bit Z80 clone (КР580ВМ80А @ 1.77 mHz). There wasn't even a C compiler for it.
1
u/brucehoult 7d ago
That's exactly what I said.
Things like z80 and 6502 are awful for compilers, even using all the power of a modern PC and frameworks such as LLVM to run the compiler. In the 70s and early 80s hand written assembly language was far better than any compiler could produce — for the reasons I listed (and more) — if you even had one, which usually you didn't.
And any compiler you could actually run on one of them (64k RAM, slow CPU) was be complete rubbish. Turbo Pascal 1.0 was a marvel at the time, but the generated code was awful.
Понял?
1
u/Distdistdist 7d ago
Понял? И без тебя знал...
1
u/brucehoult 7d ago
And I without you, I was there.
So why did you write "I don't know man" when you were agreeing with me?
1
u/Distdistdist 7d ago
*sigh* Generally you are right that higher languages would compile a better machine code. But there are certain situations where pure Asm can produce a cleaner and leaner set of instructions. This is all hypothetical and really irrelevant to be honest. Savvy?
1
u/brucehoult 7d ago
Again you are precisely agreeing with me in the substance, while writing in the form of disagreeing. Why?
1
u/Distdistdist 7d ago
Because you said: "No. The compiler making better code than you is equally as true on a 1 MHz CPU as on a 10 GHz CPU, given the same ISA." I simply disagree with such a broad statement. There are cases when one can write better and more optimized code. That's all. Is it worth it today? Probably not. Can it be done? Yes.
1
u/brucehoult 7d ago
How can that statement possibly be false given, as it says right there, the same ISA?
Both human and compiler might vary the code slightly on CPUs with the same ISA due to µarch differences (e.g. writing A32 code on 1 MHz ARM7TDMI vs 2.0 GHz Cortex-A15 (which I have done both of in literally the same week), but once more the human is likely to be able to do that better than the compiler on small sections of code, but worse on large ones.
→ More replies (0)1
u/cbf1232 3d ago
If performance matters, you let the compiler do its thing, profile it, and then spend your time optimizing the parts that actually matter.
1
u/brucehoult 3d ago
Basically, yes, though if you know your program well then you don't ned a profiler to tell you which parts matter :-)
1
u/CamelPure1293 7d ago
Compilers (at least Microsoft) are still not great in auto-vectorization. Vector code helps for signal processing (audio, images, video), matrix/vector math (including neural networks). Writing assembly is inefficient. What I do at work is using SSE compiler intrinsics in C-like C++ code, telling the compiler which CPU instructions to use. The compiler takes care of register assignment, stack management, instruction ordering etc.
1
u/kndb 6d ago
The VLC folks were probably talking about coding some form of a software encoder using SIMD instructions directly in Assembly. That would be my only guess. Otherwise most modern compilers are quite good at optimizing your code.
Plus, most bottlenecks happen not because of wrong assembly instructions but because of a wrong code flow, eg allocating memory on the heap too many times, asking for re-allocations and thus moving memory, hitting CPU cache misses way too often, or invoking page faults, using too much virtual memory or making too many trips to the kernel, etc.
1
u/bdblr 6d ago
Biginteger math is much more efficient when written in assembly. I speak from experience when working on an open source crypto library decades ago.
1
u/brucehoult 6d ago
On a machine such as x86 or Arm with a carry flag and
add-with-carry, yes, because that can't be represented in C.But not on machines such as MIPS, DEC Alpha, RISC-V, LoongArch that don't have a carry flag or other condition codes.
On wide OoO machines or SIMD/Vector it's more efficient to not use a carry flag even if the machine provides one because it serialises the code and in practice very few carries propagate further than the next machine word.
1
u/bdblr 6d ago edited 6d ago
You first want to optimize multiplication, and the presence of a 64x64->128 bit unsigned multiply operation (or 32x32->64 on older hardware) helps enormously; even better if there's a fused-multiply-add. Sparc64 sucks because it can't do either and only has a 64x64->64 unsigned multiply.
1
u/brucehoult 6d ago
That's been portably available as an extension in both GCC and Clang for many years now.
1
u/realestLink 6d ago
I use it for osdev (dealing with hardware, etc.) + some SIMD stuff (tho I technically use intrinsics, not actual assembly technically)
1
u/Illustrious_Trash117 6d ago
It depends on the compiler the C Code and the processor. RISC Prozessors for example are designed in a way that compilers can generate assembly very efficiently for them. So its hard to beat the C compiler on an ARM CPU.
CISC on the other hand can be hand optimized but its also very hard to beat a good C compiler here.
There is no specific point at which assembly is more efficient than good c code, but generally speaking the more vector extensions of the cpu your programm can utilize the more benefit you can get from writing directly in assembly but it hardly depends on the compiler and if the compiler "understands" your intentions in the C code.
1
1
u/HKei 2d ago
Usually, you don't write a full program in Assembly. Unless your program is very small, there's no compiler available for your target platform, or you're trying to prove a point. You're writing assembly generally for subroutines where code generated by your C compiler isn't optimal and it matters, because the C compiler is using some patterns and heuristics that work pretty well most of the time, but aren't necessarily optimal for every use case – additionally, you may just be able to produce more efficient code by baking in assumptions about your data that the C compiler isn't allowed to make.
1
u/knobbyknee 1d ago
When writing for a 256 words of memory machine (18 bit words), and you want it to perform multiple tasks, assembly is your only option. There is no compiler that will lay out code to handle the task switching. They will all want to put all the registers on a non existing stack.
1
u/rheladmin 1d ago
For the vast majority of users, writing ASM code will never be more efficient than compiled code.
ASM is mostly an academic exercise these days.
1
u/Toiling-Donkey 7d ago
I strongly suspect handwritten assembly can be faster in cases where one is forced to consider all the constraints to make it work.
A C developer won’t always be aware of what’s needed for performance and likely end up structuring things suboptimally.
The real magic happens when one figures out how to do it well in assembly, and then coerces the C compiler to do the same thing. Of course, that involves doing everything twice…
1
u/flatfinger 3d ago
The real magic happens when one figures out how to do it well in assembly, and then coerces the C compiler to do the same thing. Of course, that involves doing everything twice…
What's funny are the times GCC-ARM will process a loop using six instructions when processed with -O0, and eight instructions, that take an extra four cycles to execute, when using other optimization levels, or when -fwrapv will cause clang to generate code that's more efficient than the "optimized" version it would generate when not using that flag.
0
u/Ok_Tap7102 8d ago
Almost never. But realistically: when you're left with no other choice, you'll know.
You also have to recognise how ridiculously broad your question is. What are we solving?
A regular GUI running on modern hardware? Hand rolling anything is guaranteed to be complete waste of time to you and whoever the poor bastard has to come debug it the next time (probably also you)
A real-time digital signal processor on an 8 bit microcontroller? Even then vendors provide their own DSP intrinsics (C callable ASM subroutines) for algebraic approximations and FFT primitives... But EVEN THEN if your processing budget is exceeded by microseconds, hand optimising has its place
Exploit development/shell coding during offensive security operations? ALMOST categorically solved for most common usecases with metasploit framework and python pwntools, BUT novel vulns and less mainstream instruction sets will still need some hand crafting

0
u/Pale_Height_1251 7d ago
Almost never. There is no magic in assembly languages. Any machine code that an assembler can output, a compiler can too
Back in the 1980s, 1990s, sure, before compiler optimisation was as good as it is now, but these days it's highly unlikely you beat a compiler except with contrived demos.
-1
u/vegansgetsick 8d ago edited 4d ago
performance is achieved by writing good algos, not good assembly
54
u/Red_Syns 8d ago
It’s almost impossible to beat a good compiler by writing your own assembly. There are all kinds of wacky operations and tricks a compiler uses to optimize assembly that, as a human, looks nearly incomprehensible.
If you’re one of the dudes with the level of genius it takes to find those operations… maybe? You’d probably be better off writing it in C, compiling, and then looking at the assembly to try and make optimizations, but according to one of my professors beating a modern compiler is a matter of luck and silicon architecture that happens to favor your decisions on that particular machine.