55 GiB/s FizzBuzz (2021)
codegolf.stackexchange.com
codegolf.stackexchange.com
To me, that is amazing systems architectural design - so many different parts of a regular linux kernel all working together to let this fastpath happen.
Would such a thing be possible on Mac OSX's Mach ports or Windows's Named Pipes?
I assume this is what the author meant by “page table contention” as a bottleneck: Without TLB invalidation there would be no need for either process/thread to ever touch page tables in a scenario like this.
TLB has to be flushed for process context switch on x86 regardless of Windows/Linux - but modern systems typically allow it to be selectively flushed (the system can elect to not flush tlb for the shared mappings that exist in both processes).
TLB miss vs Cache miss are an order of magnitude apart, and multiple orders if the corresponding pte itself is resident in dcache.
What’s the mechanism for this? AFAIK one of the main motivations for the recent heated discussions on PostgreSQL adopting a threaded model would be eliminating TLB flushes in high-context-switch environments. Can Linux already preserve their (massive) shared mappings?
The OS juggles these based on what processes are resident on CPU and the various active mappings then uses INVPCID[0] during a context switch.
if(((i%3)||(i%5))== 0)
buy_0_day_to_expiry_options() if (is_trading_day())
buy_0_day_to_expiry_options()It's not just the algo's, it's very much the latency.
( eg: https://www.velvetech.com/blog/fpga-in-high-frequency-tradin... )
> I suspect that what's happening is that the program was somehow compiled with ASLR turned on. For some reason, the dynamic linker doesn't respect the 4 MiB alignment of the BSS segment in this case, effectively ignoring my .align, and that's what's causing the bugs.
> @chx: I already have a master's thesis. This was harder. – ais523 - high effort answers Oct 29, 2021 at 1:17
Rust -> 23.2MiB/s
Python3 -> 28.6MiB/s
C -> 238MiB/s
Does anyone know why Rust's performance is in the same ballpark as Python3.
I thought it would be more closer to C.
In order to get similar performance as C, you probably need to take care of this lock yourself:
let mut lock = stdout().lock();
write!(lock, "hello world").unwrap();
(And also you need to make the buffering size for stdout match C’s.)Huh? Traditionally, stdio implementations have placed locks around all I/O[1] when introducing threads—thus functions such as fputc_unlocked to claw back at least some of the performance when the stock bulk functions don’t suffice—and the current ISO C standard even requires it (N3096 7.23.2p8):
> All functions that read, write, position, or query the position of a stream lock the stream before accessing it. They release the lock associated with the stream when the access is complete.
The Microsoft C runtime used to have a statically linked non-threaded version with no locks, but it no longer does. (I’ve always assumed that linking -lpthread as required on some Unices was also intended to override some of the -lc code with thread-safe versions, but I’m not sure; in any case this doesn’t play well with dynamic linking, and Glibc doesn’t do it that way.)
[1] e.g. see https://sourceware.org/git/?p=glibc.git;a=blob;f=libio/iofpu...
https://ismailmaj.github.io/tinkering-with-fizz-buzz-and-con...
Here's a C program counting, with a 1ms delay between lines. The second column is a duration since the previous read():
$ ./out | rtss
4.7ms 4.7ms | 1
4.7ms | 2
4.7ms | 3
4.7ms | 4
4.8ms exit status: 0
You can see they were all written in one go. When allocated a terminal, they come out line by line: $ rtss --pty ./out
0.8ms 0.8ms | 1
1.9ms 1.1ms | 2
3.0ms 1.1ms | 3
4.1ms 1.1ms | 4
4.3ms exit status: 0
Rust lacks this adaptive behaviour for output, and will always produce the second result, terminal or not.Technically it unconditionally wraps stdout in a LineWriter (https://doc.rust-lang.org/std/io/struct.LineWriter.html), which always flushes if it sees a write containing a newline. To maximise throughput you therefore want to batch writes of multiple lines together, for example by wrapping it in a BufWriter.
In audio dev it's very common for dsp code to be written in assembly.
Extreme algorithmic research combined with a high LOK of Linux syscalls and platform specific optimizations is what allows this to exist. To quote the author, Alex Smith, himself:
> @chx: I already have a master's thesis. This was harder.
This is in a different universe than what can be produced by simply "do it in assembly".
It's one of those extremely-common-in-the-US-military-almost-no-usage-outside-it type things apparently, like behoove or tack (hyphen) or diggit (multi-tool), which I'll keep in mind in the future.
No, author's extreme boredom and/or free time allowed this to exist. Nothing else.
Also I bet the reason is more of architecture in your web app. It's harder to make it as fast, for sure, but it shouldn't hang or be unusable.
And then all you web devs could still compile rust to wasm. wasm is already faster than JS anyway. JS was a mistake.
"OK: I went to the University of Washington and [then] I got hired by this company called Geoworks, doing assembly-language programming, and I did it for five years. To us, the Geoworkers, we wrote a whole operating system, the libraries, drivers, apps, you know: a desktop operating system in assembly. 8086 assembly! It wasn't even good assembly! We had four registers! [Plus the] si [register] if you counted, you know, if you counted 386, right? It was horrible.
I mean, actually we kind of liked it. It was Object-Oriented Assembly. It's amazing what you can talk yourself into liking, which is the real irony of all this. And to us, C++ was the ultimate in Roman decadence. I mean, it was equivalent to going and vomiting so you could eat more. They had IF! We had jump CX zero! Right? They had "Objects". Well we did too, but I mean they had syntax for it, right? I mean it was all just such weeniness. And we knew that we could outperform any compiler out there because at the time, we could!
So what happened? Well, they went bankrupt. Why? Now I'm probably disagreeing – I know for a fact that I'm disagreeing with every Geoworker out there. I'm the only one that holds this belief. But it's because we wrote fifteen million lines of 8086 assembly language. We had really good tools, world class tools: trust me, you need 'em. But at some point, man...
The problem is, picture an ant walking across your garage floor, trying to make a straight line of it. It ain't gonna make a straight line. And you know this because you have perspective. You can see the ant walking around, going hee hee hee, look at him locally optimize for that rock, and now he's going off this way, right?
This is what we were, when we were writing this giant assembly-language system. Because what happened was, Microsoft eventually released a platform for mobile devices that was much faster than ours. OK? And I started going in with my debugger, going, what? What is up with this? This rendering is just really slow, it's like sluggish, you know. And I went in and found out that some title bar was getting rendered 140 times every time you refreshed the screen. It wasn't just the title bar. Everything was getting called multiple times.
Because we couldn't see how the system worked anymore!
Small systems are not only easier to optimize, they're possible to optimize. And I mean globally optimize."
http://steve-yegge.blogspot.com/2008/05/dynamic-languages-st...
what in the god damn
https://www.amazon.com/Object-Oriented-Assembly-Language-Len...
Indeed, my first industry job, after spending my undergraduate and graduate degrees honing C++ skills, was doing object oriented C. It was actually great, taught me a lot about what actually matters in a language versus what people will tell you.
Now, obviously, programming languages encourage and afford the use of certain paradigms. But that's all they do. A program is not object oriented because it's written in C++. It is object oriented because it is written in terms of objects, regardless of what the underlying language may support or encourage.
Assembly, being the base language of the CPU, can be written in any paradigm any other language might permit, since all other programming language paradigms are obtained as limitations on the underlying assembler that may be generated. You can always just apply those limitations manually to get an object oriented program, or a logic programming program, or a functional programming. It just might be very costly and difficult.
That you have some set of macros that work on common data structures and use a function pointer lookup to dispatch some behavior isn't insane. I mean, if your macros are that advanced why not use a real programming language, but shit got weird in the 80s and early 90s.
Some wonderful systems were written in assembly. Donkey Kong comes to mind.
More likely to be the opposite IMO. AI could make the Sufficiently Smart Compiler a reality; maybe autovectorization will finally work and you could write FizzBuzz in Python and it would perform like this.
For like 99% of websites and software today, if anyone cared about the app performance, I am pretty sure most would be able to achieve at least 50% speed-ups through very basic changes (correct caching, optimizing assets, replacing bloated 3rd party libraries with a basic native call that does the same thing, configuring the servers and databases properly, etc.).
EDIT: That being said, I am pretty sure in a few years AI would be able to provide one-click optimizations to a repository that would either apply best-practices or rewrite the original code in performant Assembly.
See https://danluu.com/octopress-speedup/
> "This blog is a static Octopress site, hosted on GitHub Pages. Static sites are supposed to be fast, and GitHub Pages uses Fastly, which is supposed to be fast, so everything should be fast, right?"
followed by
> "I'm not sure what to think about all this. On the one hand, I'm happy that I was able to get a 25x-50x speedup on my site. On the other hand, I associate speedups of that magnitude with porting plain Ruby code to optimized C++, optimized C++ to a GPU, or GPU to quick-and-dirty exploratory ASIC. How is it possible that someone with zero knowledge of web development can get that kind of speedup by watching one presentation and then futzing around for 25 minutes? I was hoping to maybe find 100ms of slack, but it turns out there's not just 100ms, or even 1000ms, but 10000ms of slack in a Octopress setup. According to a study I've seen, going from 1000ms to 3000ms costs you 20% of your readers and 50% of your click-throughs. I haven't seen a study that looks at going from 400ms to 10900ms because the idea that a website would be that slow is so absurd that people don't even look into the possibility. But many websites are that slow!"
I'd say a big factor to include here is the choice of language. Going from Python/Ruby to Kotlin/Rust/etc could probably yield a speed up of over 10x / over 1000%.
I am not sure if there are languages that come with a fool-proof ecosystem when it comes to implementing things and making them fast. The only one I can think of are UI-based applications builders, that only allow you to add to your app only a limited subset of UI elements or features.
when it’s painful to progress even a little bit while coding, you try very hard to implement as little as possible
resource constraint can give clarity of focus
vmsplice grants access to a process' buffer/memory to another process - a shared mem equivalent. As the initial competition requirements are likely vague, I'd imagine it's unclear if this is still good wrt the rules.
You can scroll upward to the original question to see the initial requirements, and check the edit history to verify that they haven't changed since the start of the challenge:
> Write your fizz buzz program. Run it. Pipe the output through <your_program> | pv > /dev/null. The higher the throughput, the better you did.
> The program output must be exactly valid fizzbuzz. No playing tricks such as writing null bytes in between the valid output - null bytes that don't show up in the console but do count towards pv throughput.
And vmsplice(2) indeed produces a stream of bytes in the standard output pipe that pv(1) can splice into /dev/null, or cat(1) can copy into the terminal.
This submission was not the only one that uses vmsplice(2); others have found that it's far from a magic bullet. Once you pass the I/O hurdle, much work remains in generating the pages of output as quickly as possible.
Isn’t this almost always the whole problem? Most code is bottlenecked on memory and I/O. Complex problems are usually held up by the speed of getting data from one place to another, and not very often on computing the data. As someone who spends his days optimizing GPU assembly, even in the rare cases when compute is the bottleneck, once you optimize it, memory becomes the bottleneck.
For example, there's a clever bit representation to get base-10 carries to happen natively.
The initial competition requirements are not particularly vague about this point: Measuring throughput with `<program> | pv > /dev/null` is prescribed, and it also says
> Architecture specific optimizations / assembly is also allowed. This is not a real contest - I just want to see how people push fizz buzz to its limit - even if it only works in special circumstances/platforms.
Understanding how to deal with memory I/O and file I/O performantly is a relevant skill for every program and programmer.
What’s the significane of “.S” vs “.s”?
Edit:
From manpage:
file.s
Assembler code.
file.S
file.sx
Assembler code that must be preprocessed.Not sure if it makes a difference on modern toolchains.
They’re not cheap, but if you want some serious kit that also financially supports the OPNSense project, the Deciso appliances are tough to argue. Power efficient, durability-focused components, just work.
It’s nice seeing their commercial offerings getting beefier.
How?
The submitted code snippets for Java do not need OSR, though... yet they can be improved further, e.g. should drop the use of String entirely (which would not feel very Java). The other attempt to convert int -> String (byte) uses the naive way to divide by 10 on each iteration, Java.'s Integer.toString does it way better.
Edit: on a 2nd thought, having a dedicated direct buffer [same allocation, different slices] per all the 8 out of 15 ares for numbers and NOT converting int->String each operation but adding 15 would be a pretty boon as most of the time the change would be only the last 2 bytes, and there won't be any 'div' to be had. Div is generally slow (compared to L1/L2 cache misses, and L3 hit), there is not algorithm to parallelize it, and there is one (few) unit that can perform div, unlike 'add')
In theory, yes, but in practice I've never seen it happen. Best I ever saw was matching C speed at toy benchmarks. Even in this benchmark here, Java is decent, but does not beat even the naive implementations in C/Rust.
Also, AOT compilers can do PGO as well, so they can use the same techniques. But they also have way more time and resources, so they can do things like whole program optimization, which is something JITs cannot do because they have much smaller computation and memory budget.
It happened already many times to me that the first naive version of a C/C++/Rust program/function I wrote was already faster than a carefully tuned Java equivalent. AOT compilers for "fast languages" got really good these days. The design of language also influences how well it can be optimized by the compiler. E.g. it might look impressive JVM can devirtualize dynamic calls at runtime, but C++/Rust often don't have to do this at all as programs in those languages tend to have very few virtual calls if any at all.
Java doesn't beat C in this benchmark but beats Rust with ease.
Also, technically there is nothing C can do that Rust can't.
"GC pauses" are greatly exaggerated in terms of impact and frankly for the vast majority of uses cases GC simply doesn't become an issue.
The JVM is really really good because at one point or another they had basically every luminary in the field working on it.
And it's not even that slow anymore compared to, say, starting the JVM in 2010.
Some numbers for those curious...
On modern hardware launching the JVM to run a program immediately exiting takes less than 100 ms (so does starting Emacs complete with its GUI and running some elisp code exiting Emacs: 80 ms on my Ryzen 7000 series including reading from the M.2 NVMe PCIe 4.0 x4 SSD).
It's once you start loading lots of classes that JVM startup time can be slow.
One example would be a Clojure program doing nothing besides exiting: thousands of Java classes being used and you get into 1.2 seconds territory to do nothing. 12x slower than a Java program doing nothing.
As a sidenote for both Java and Clojure there are now ways to reduce startup time, like using GraalVM (which, for example, Babashka, a natively compiled Clojure interpreter, making Clojure startup so fast it can be used for scripts).
> The JVM is really really good because at one point or another they had basically every luminary in the field working on it.
I agree. The JVM is an impressive piece of machinery and it'll even give you, say, an AIOOBE (ArrayIndexOutOfBoungsException) instead of an exploit if you fuck up.
I'm with you all the way and am a daily emacs user but I'm not sure I'd point to emacs as a good performance comparison, haha.
Emacs has always been a bit of a dog in my experience.
It's similar to SWAP in Linux. It was implemented somewhat meh in older kernels, and usually if swap got hit, the system died anyhow. So there was no real difference between random processes being OOM-killed or the system grinding to a halt swapping. Modern kernels in the 4+ line have received quite a bit of work on the swap handling and swap is used a lot and very cleverly to eek out just a bit more available memory more quickly.
Old habits die hard though and it takes time for old knowledge to change.
Low pause GCs (ZGC, Shenadoah) for Java are not generational yet.
Also, even if they were, a very high temporary object allocation rate increases young gen GC frequency and thus increases the number of objects pushed to old gen eventually.
And it is not like those young gen GCs are free either. They burn quite some CPU time and they cause micro-pauses - the GC has to scan parts of the heap to learn which objects are reachable and then it has to copy the survivors. In practice, high allocation rate requires a decent amount of overhead RAM to make that process efficient. It doesn't matter if pauses are only 10 ms short if you do 50 of them per second. ;)
In non-GCed languages those trivial short-term objects are typically allocated on stack and their allocation/deallocation is trivial and doesn't pause at all.
They are. GenZGC is merged into mainline and got into the latest JDK, GenShenandoah didn't manage but will be in next release.
>The problem of GC pauses is solved only if you can afford to waste 5x-20x more memory than the app is really using
I don't think that is true. ZGC uses multi-mapping in order to dereference its colored pointers, this causes some tools to report excessive memory usage but nothing actually hits RAM.
Hmm, for generation GCs, it should use Card marking, the pointers in the tenured gen should have means to be trivially determined where they belong to. With 64bit pointers, there is space for quite a lot of metadata, incl. the Class (or most commonly allocated/used classes).
I feel like I've been hearing this same line for 20 years now
It works by allocating all or most needed memory at program start, instead of asking the operating system for it every time. But, as soon as you don't use heap memory, and use the stack, C++ is again much, much faster than Java.
It all depends on memory management.
To your second point about raw speed, one of the extraordinary things we found in long-running processes performing computation using real-time marketdata at Goldman was that the HotSpot JVM was able to optimize java programs through the day due to their usage, so if you started them each day they would actually end up faster than the C++ versions at the end of the day even though they would start off slower. That's not due to memory allocation it's due to things like inlining of functions.
The implication of that is that if you very carefully inlined all the functions appropriately in the C++ version based on profiling actual usage you would be able to achieve the same result, but for the JVM it just happens automatically without you doing anything.
[1] Search https://en.cppreference.com/w/cpp/language/new for "Placement New"
Can you point us to some benchmarks?
I don't doubt it is faster, but I doubt the "ridiculously" part. Last time I measured it was only a tad faster than jemalloc (~20%) if you allowed the benchmark to run long enough for GC to start cleaning up. Unfortunately I haven't saved it (it was a very informal benchmark). I'm curios to see that esp. on modern low-pause GCs.
Anyway, don't use new in C++ is my opinion.
You could of course FFI into e.g. C for those parts, but that is usually harder to maintain than a few well optimized java classes.
It's a quite common myth developers believe about performance. Hotspots do happen sometimes, but once they have been optimized you quicky end up with a flat profile and an "everything is slow" problem. And in some types of apps, the majority of code is performance critical.
If the majority of code is performance critical, the tradeoffs are of course different.
Hopefully Foreign Function & Memory API [0] makes FFI so much easier that we get to drop down to C without much fuss.
You know who wrote this:
"Essentially, the Quantum FizzBuzz Decoupler is a device that bifurcates the bifizzial substrates and recoheres them into units of Buzzifactive tri-fusion. Its pivotal design focuses on the tripticate circuitry which utilizes pseudo-string theory, ensuring the cyclic decoupling of the Fizzionic and Buzzionic isotopes, thereby creating a conflux of cryptic poly-angular interdigitations.
This hyper-convoluted mechanism leverages the intrinsic infra-doodlality of its multitudinous nano-digitators, producing a reiterative bi-fractal resonance with every flicker of the reciprocal quark-flux nano-helices. Interlocking harmonic modulators within the Decoupler support the synchronous crystallization of the brizzulated waveforms, thus reinforcing the transluminal juxtapositioning of multi-fuzzional intermediates.
Within its dual-core, it harmonizes the phasic disentanglement of quasi-quintessential quantum flux through the divaricating spindles of the orthofizzial transinductor. Furthermore, the Decoupler incorporates an ultra-gloptic resonator to facilitate the recursive modulation of the bifizzial and tri-buzzoidal constituents, hence the stupendously high FizzBuzz output."
At the end of the prompt I tell it to judge its results against my requirements because I was afraid it would use real words, since it usually shouldn’t be making words up as part of its output - let alone making the whole output nonsense - so this is a tough task for it.
If you tell it to judge itself it is less likely to do the wrong thing. (It doesn’t like to end up printing “I disobeyed all the instructions since I used real words” - it’ll rework its output to be more correct. It’s like a cook, if you ask for a chicken pie and then to tell you if what it just cooked is a chicken pie it won’t bake you an apple pie instead. Unlike a real cook, it doesn’t have enough awareness to judge itself if you don’t ask it to.)
It still used the term isotopes. The original didn’t include any real words like that. So it didn’t really meet ALL of my requirements which said “don’t use any real technical words”. It should have changed it to isotrypes or something.
It is still a very impressive result. ChatGPT truly understands the prompt and can really think, as evidenced by its summary at the end, even though I didn’t mention that my request was for comedic effect.
https://youtube.com/watch?v=RXJKdh1KZ0w (my favorite version)
It's an old engineering in-joke.
Edit: oops, thought your comment was a reply to 'mindcrime. I'm keeping it here though for the lucky (very lucky in this case) 10,000.
https://www.ebay.com/itm/364213117135?hash=item54cccb20cf:g:...
I was the only one who spent some serious time on the task, and in the end my implementation was the fastest by several orders of magnitude, despite being the only using something else than C, C++ or java. The programming teacher refused to believe I wrote it myself, but due to a stroke of luck I have saved every revision of the code as a part of a primitive folder based SCM-scheme.
I ended up getting a louse grade due to me not caring too much about school, but the teacher and I were on good terms and he became somewhat of a programming mentor to me
99% of managers claim that developers cost more than hardware, so it's perfectly fine if the code is slow, they can just buy more hardware.
The argument is rather the following: common knowledge is that it’s not worth optimizing the code and that programming languages don’t matter, because the IO is too slow anyway. This fizzbuzz shows just how bad we are at IO compared to the optimum. So if we were to improve the IO, then faster processing would also make a difference. In this case you get an improvement of 179x compared to Python, i.e. your laptop will do instead of multiple clusters in the cloud.
If this task was the bottleneck in a large scale system then it would definitely get hand optimized after a proper analysis.
But if this is an occasionally run task or something otherwise not business critical that doesn’t bottleneck anything, spending orders of magnitude more time hyper-optimizing it would be a waste of time and money.
Match the solution to the job. Optimizing everything is one of the age-old mistakes in computer science.
Maybe? But given that we don't have a way to magically make IO go much faster, that seems pretty irrelevant to the real world. The processor can go faster than memory; sure, we knew that.
> In this case you get an improvement of 179x compared to Python, i.e. your laptop will do instead of multiple clusters in the cloud.
So a highly skilled programmer devoting months to what's typically a 10-minute interview problem (i.e. about 5000x as much programmer time - and the time investment would probably scale superlinearly with the complexity of the problem) was able to get... a measly two order of magnitude improvement. That's really not a good tradeoff most of the time.
* Where do those terabytes of json live? In the example case, the data is not read from anywhere, but rather generated and written to the pipe. All else being equal, I suspect it would be hard to feed such a program at 55GB/s w/ real data from some storage somewhere - in the end you'd be limited by the disk read speed (or network recv speed).
* This example doesn't need much ram for processing. There's only a handful of variables that can be held nicely in registers. Even if you could get 55GB/s of input, there aren't a lot of cases of json processing that won't need to store variables in memory. At a minimum a lot of effort would be required to ensure cache friendliness for these variables to not thrash the cache - if it's possible at all.
* The code for the example is tiny - json parsing requires a lot more instructions. Even in the simplest case - pulling a fixed number of bytes from fixed size records in the input stream requires a similar number of adds and compares (etc) as the example case, and the output memory alignment machinery will be about the same. As the code grows to handle actual parsing of json and processing of data, the instruction count grows quickly to a size where the instruction cache may become a concern.
* speaking of instructions - parsing json has a lot of conditionals. I don't think it's possible to do it without any conditionals, or even without enough branch mispredictions and pipeline flushes to achieve such high throughput.
Of course all of this is assuming that the IO of writing to a pipe is the same as IO in the "get from network or disk etc" sense. They really aren't the same - io to a pipe is IPC, the data never leaves the l2 cache - it's only io to the process not to the CPU. Once you have disks and networks and RAM involved, things change dramatically - the signals have to travel an order of magnitude (or more) further, they have to leave the chip so you must synchronize with a different device, there's protocol overhead for storage and network, etc.
Point being - sure we can absolutely do better with software in a lot of cases, but this is not a good example to derive conclusions from.
If so, that's missing half the picture. "People don't care about performance" isn't why devs gravitate towards Electron. Devs and managers gravitate towards Electron because it means they don't have to hire extra people and do more work to get their native apps working on whatever operating systems they ship to and rewrite the whole app for the web. Yeah, it'd be nice not to have the performance penalty, but some teams have accurately calculated that the performance loss the customer realistically notices is worth the benefits of writing and maintaining the app.
They’re too willing to accept an adequate solution because it “works” rather than spending just a little bit more time to find a more appropriate solution.
That doesn't mean it's appropriate to replace your billing system with one. Even if it works.
It's probably not useful to reason about a whole field in such absolute terms as what's best or what works.
Expecting teams to do more than a master's for every desktop app?
You're not going to have businesses if you apply the standard of this post to everything. Respectfully, the attitude of "optimize the world and damn the consequences" feels like it usually comes from people who haven't tried to deal with the realities of making money with code, even at a level of just understanding why your manager is telling you that they're pushing the release forward against your suggestion.
If that were possible, I don't think it would be unreasonable. A Master's degree is two-ish years, so about two person-years of effort. Once you're looking at even a small team, a desktop app would often have far more effort put into it.
Instead of 'a desktop app', I think the better comparison is to note that this is a FizzBuzz program. By design, it doesn't do any useful or algorithmically complicated work. It's a canonical example of a trivial program.
If you imagine putting Master's thesis levels of effort into every trivial part of a desktop application, then you'd start to outline the full scope of the problem. Rather than a "Master's thesis" effort, you'd be looking at something like a full, crash research program like the Apollo project.
The internet is actually faster than you think if you minimise spurious network requests, but most applications don't do that, leading to seconds of delays.
I agree with the spirit of what you imply: what a waste. On the other hand we do not use titanium everywhere, only where needed. There is best for a specific usecase.
And I remember how my jaw has almost dropped when in 2022 I saw an operator of a POS that used a 80x25 TUI coming from a dinosaur era coded probably with Borland TurboVision... Man, how fast that was! Some windows literally appeared on the screen for a fraction of a second (the operator obviously memorized the sequence of actions). The fact that I found it unusual, when in fact it should be a norm, also speaks something about the performance of today software.
All of our interns: "How do I use this with VS code?"
They ssh using it, everything. They don't know anything else. They don't know that they are using ssh, they have a VS code terminal window open. It's kind of sad.
Meanwhile, I'm trying VS code on my 5 year old Mac, and it's like a slideshow. Open a file...wait for syntax highlighting to fill in, the keyboard response is laggy. It's so terrible. Sublime Text is a Tesla Plaid in comparison.
Not sure what I’m going with this except I know VS code is touted as some kind of counter example a lot. But I also know such care didn’t go into most Electron codebases.
Is there no chance that at least some of those code-bases would be inefficient in other frameworks too? And no chance that the projects would have taken longer to release, or wouldn't exist at all because it was deemed too much faf, if another framework were used?
Other than running separate node and chromium instances for every instance of an app, what does Electron do to encourage the inefficiency that is attributed to it?
At this point, I think the debate about slow apps is more ideological than reality.
I also think a lot of people are mistaking backend/network latency for front-end slowness. Slack isn’t going to load your scroll back history any faster if the backend is spending all of that time searching the database. People are too quick to blame the front end.
Either that, or some of these posters are running 10-year old hardware and wonder why it’s slow
Some nuance and examples of traditional engineering (titanium as material) were given, if you want to rebuke them.
I am not appealing to popularity. I am offering a counterexample. It seems electron is not the problem (I showed a counter-example), but priorities are.
Software engineers did not wake up and decide to make programs slow. The economic incentives decided that it was not "worth it". For that to change, the incentives need to change. Just claiming it "should" be like this is not as insightful as it may seem.
In the same way we could complain about programs not being formally verified for correctness, instead of not being as fast as possible. Probably that is a worse offender.
I usually agree. But laziness as the primary constraint should feel appalling to anyone who would willingly call themselves an engineer. Perhaps I actually mean to use a different word for engineer but I don't know what it should be
> I am not appealing to popularity. I am offering a counterexample. It seems electron is not the problem (I showed a counter-example), but priorities are.
I think you are, indirectly or inadvertently, citing electron and arguing in defense of it as a reasonable choice/option does do that.
> Software engineers did not wake up and decide to make programs slow. The economic incentives decided that it was not "worth it". For that to change, the incentives need to change. Just claiming it "should" be like this is not as insightful as it may seem.
Laziness is a choice. There are known better options, but software engineers *DID* choose to make it slow. The common axiom good, fast, or cheap; pick two. If you choose ease of development over fast you chose to make it slow. The people who build in python over C because they can write python faster, chose to make runtime slow. I guess you could argue for ignorance as a reason, but once you realize your software is slow, and refuse to do the work needed to fix it. You've also made the choice for it to be slow.
> In the same way we could complain about programs not being formally verified for correctness, instead of not being as fast as possible. Probably that is a worse offender.
Good engineers are willing to make the right trade offs. and I still believe that laziness is a positive trait in software engineers. But great engineers find a way to have both/everything, and people acting ethically don't prioritize their comfort or convenience over what's in the best interest of users.
The problem isn't if we can or can't make it fast, or correct, or user friendly. 55GiB/s fizzbuzz proves if you care enough, anything can be fast. The problem is people don't care, and that others who also don't care throw up their hands and say good enough is acceptable. And sure by definition it is acceptable. But I'd argue everything is awful, on fire, trash, user hostile, bad because too many people go ehh good enough you can stop trying.
It seems the difference is what we each are including in the "universe" of the problem. To me, it looks like you start and end with the developer (maybe developer + user), and assign laziness to them (aka you turn it into a moral problem).
On my argument, I am including the company, the users, and the whole economy. In that context, it is not about what the developer wants, but about the economical incentives, and it is not a moral problem but an optimization one.
#!/usr/bin/env gawk -f
BEGIN {
for (i=1;i<=100;i++) {
printf(" %2s", i%(3*5)!=0 ? i%5!=0 ? i%3!=0 ? i : "fizz" : "buzz" : "fizzbuzz\n" )
}
printf("\n")
}
No idea as to actual throughput though. I believe this is slower than explicit loop, if/then, or switch/case testing though (based on hazy recollections of past performance testing).https://css-tricks.com/tales-of-a-non-unicorn-a-story-about-...
Asking for a list of tasks that will come up or code examples is particularly naive. Technical jobs aren't a laundry list of exact needs.
Being an engineer in any field requires versatility, including the ability to solve problems on your feet and to learn new technology, or to learn tech you already know to a greater depth, at the drop of a hat.
This is one of the few times I've ever read a story about impostor syndrome where the story teller actually was an impostor. Bizarre.
"Write FizzBuzz" - "OMG, MATH!"
Impostor meets Dunning-Kruger.
Also fizz buzz has nothing to do with the kind of programming that was expected from the job description. Now you might reasonably object that fizz buzz is supposed to be something so rudimentary that any programmer could implement. But the point is UI/UX people don't typically do any algorithms work at all. Their interaction with JS is often just to call an API and shove the resulting data where it needs to be in the DOM. They may never have to use a loop, ever. Or conditional testing. Or think about infinite sequences. To a proper software engineer like you or me fizz buzz seems ridiculously simple. But I could totally see a UX designer whose only interaction with self-taught JS is to glue APIs together being tripped up.
I've asked the people I work with that have this combination of skills but, unfortunately, they all popped out of existence the moment the question left my mouth.
Perhaps they were impostors too?
It is barely in the same family tree as FAANG coding tests.
“ HTML5, CSS3, JavaScript. I’m a master at the first two, but since there was no mention of programming stuff and the responsibilities section was so design-centric, I figured my jQuery proficiency and capacity to self-teach would suffice.”
The entire job description read like a UI/UX designer with a minimal understanding of JavaScript.
Her point is that if they wanted a software engineer then they should have hired one. She isn’t trying to be one.
There's no version of a person who meets this requirement that cannot fizzbuzz. They put engineer in the title of the position.
"UX Engineer" is a completely reasonable title for someone who uses Javascript, HTML, and CSS to build web frontends. That person is absolutely a programmer, and absolutely must be able to fizzbuzz (and much, much more).
In HR parlance, if the person meets the BQs then they are considered qualified. If someone comes along and you have two equals but the one of the two had the preferred then they are the preferred candidate. Preferred candidate would be expected to know fizzbuzz.
The part you pasted was in the preferred qualifications.
Also engineer term is overloaded here which is also her point
This is not a point of contention. It is the entire point of fizzbuzz. Fizzbuzz was designed to stop wasting interviewer time by filtering out people who could never in any way be construed to be qualified for a position that involved writing code.
And fizzbuzz is not a math problem. I’m sure the interviewer would’ve even given her a hint if she came as far as writing a loop and writing the different branches but not figuring out how to differentiate the cases. I’d shrug that off as nervousness perhaps.
I wish I could meet these people who can't code a fizz buzz.
// The bytecode interpreter consists of four instructions:
// 1. Load the bytecode from memory into %ymm2;
What is the performance impact of this load? Do you get more store-to-L2 memory bandwidth if you aren't loading at the same time?
>LINENO_TOP doesn't need to be initialized for new widths, because an overrun by 100 lines is possible, but by 10 billion lines isn't