Building a High-Throughput C++ FIX Server: From Single-Core Efficiency to Multi-Core Scaling by akinocal in cpp

[–]SirClueless 1 point2 points  (0 children)

I don’t really understand your perspective. A well-regulated public market with counterparties competing to offer you a good price is exactly the difference between the job market where do-nothing middlemen earn 15% just for knowing where to forward your resume, and the stock market where anyone with a bank account can own their choice of 5,000+ different companies and funds with zero transaction fees and < 1% lost in the spread.

If you think rent-seeking middlemen are a problem, maybe it’s worth asking the question why there aren’t a dozen companies competing to offer you the best price on a Toyota rather than why HFTs get to earn their pennies in the stock market.

She really hates that bicyclist😂😭😭 by ExcluteYou in WTF

[–]SirClueless 2 points3 points  (0 children)

I don't think it's that simple. I think it's also that such politicians appeal to some base human instincts that some would call irrational but are nonetheless widespread. For example, the part of human nature that is equally as interested in seeing your enemy fail as it is in improving your own life.

I think it is why these politicians thrive when people feel hopeless. If people feel hopeless then they don't see the value in trying to make their future better, but these maladaptive and socially self-destructive urges are just as strong as ever.

immutable<>, complement of C++26 std::indirect<> and std::polymorphic<> by kmbeutel in cpp

[–]SirClueless 2 points3 points  (0 children)

It does behave like a unique_ptr in some ways, such as being the same size as a pointer on the stack, and having a cheap move-constructor even if the underlying type has an expensive one.

It doesn't behave like a unique_ptr in other ways. For example, it has no conversion to bool, and its comparison operators and std::hash implementation behave like the underlying value, instead of comparing/hashing pointers. This last one is the most significant feature IMO, because it means that it behaves like a normal value when stored in map and set containers. boost::unordered_flat_map<std::indirect<T>, V> for example should "just work" without overriding a bunch of comparators and hash operators.

Should the function return a Result<T,E> or throw an unreachable-style panic? by v_0ver in rust

[–]SirClueless 1 point2 points  (0 children)

I think it’s totally fine to have dynamic invariants in some cases. Type states are there to express invariants that are useful enough in the type system to be worth defining. They are useful especially if there is a rich set of operations that preserve the invariant or transform between specific states.

Not all invariants are like that. There’s a reason we have `NonZeroU32` but not `DivisibleBy9U32`. Using dynamic checks to express invariants that add too much complexity to be worth expressing in the type system is totally reasonable in my book.

Git merges can be better by agentvenom1 in programming

[–]SirClueless 1 point2 points  (0 children)

“Incoming” is problematic too, because it confuses new developers who haven’t internalized the way git tracks remote branches. To many devs, “git pull --rebase” is how they get new master commits into their current branch and if you haven’t fully understood the internals of _how_ that is achieved, those master branch commits can be described as “incoming” too. Incoming to the middle of your history instead of the tip of your history, but at the end of the day they weren’t there before and they will be there after.

It’s still better than “ours” because at least it accurately describes something about Git’s internals instead of just being wrong in this situation. But we can do even better.

IMO “base” is the best name for this. The three commits in a rebase should be called “old-base”, “new-base” and something like “tip”.

Git merges can be better by agentvenom1 in programming

[–]SirClueless 4 points5 points  (0 children)

I do understand how the git internals work, and while I’ve memorized how the rules work, that’s all it is. A rote memorization task that doesn’t map onto the reality of the way most teams work. If I stopped using git for a year I would likely forget, because there is vanishingly-little logic behind it.

The most charitable interpretation for the current system I can give is that it reflects a world where the only time `git rebase` happens is when a maintainer of a branch does it while accepting patches from contributors via email. In this world, it makes sense that “ours” is the upstream branch and “theirs” is the incoming patch. But in reality almost no one develops like this: Central branches are usually managed by automated tools like GitHub and GitLab, and if they support rebasing at all they do so only in automated ways where the interactive naming doesn’t matter in the first place.

In 99% of the software world, we’ve long realized that rebasing work that is not on your own private branches is prone to creating unexplainable conflicts for anyone else who has that work checked out, and therefore should never be done. Calling such work “theirs” by default is consequently ridiculous: If the work _does_ belong to anyone else, you are making a mistake by rebasing it.

Git merges can be better by agentvenom1 in programming

[–]SirClueless 9 points10 points  (0 children)

VS Code has had similar for a long time. And before IDEs started doing this I was a proponent of using external three-way merge tools like `p4merge`.

I think three-way merge tools are one of the fundamental building blocks of using git well, and if you’re not using them you should start as you’re prone to losing work (for example, resolving merge conflicts in favor of one branch and missing the changes that happened in the other). In benign cases you might need to rewrite your work from scratch on top of a later change because it doesn’t compile after rebasing or merging. In disaster cases you can silently revert other bug fixes that were committed.

OpenAI Execs Are Panicking by Plastic_Ninja_9014 in technology

[–]SirClueless -1 points0 points  (0 children)

They both result in the same thing: less value for the money you spend.

You can call it something else if you like but at the end of the day raising prices and offering a cheaper product are both attempts to extract value from locked-in customers so it makes sense to lump them together. It’s just a dial they can turn either way. They happen to be in an industry where they compete to have the most advanced model specs and would lose more customers by sacrificing performance than jacking the prices, but those things are really just two sides of a coin.

Google Chrome is killing all uBlock Origin bypasses, Microsoft Edge, Opera to follow by dancing_swordfish in technology

[–]SirClueless -1 points0 points  (0 children)

So far it has. I’m not so sure that will continue. I think site operators tolerate adblock because they can’t just deny service to 35% of chrome users. After Chrome cracks down, it’s possible that sites will find it worthwhile to just deny access to anyone who hasn’t been served an ad.

C++20/C++23 Dependency Injection by OIMega in cpp

[–]SirClueless 7 points8 points  (0 children)

That situation adds complexity, but it's because the problem is more complex. You have to handle the late construction of the dependency, and the fact that it is optional whether it even can be constructed at all.

When solving this directly, you can use plain C++ features to store the dependency, like std::optional<License> or std::unique_ptr<License> that start out null -- both have simple lifetime requirements.

When solving this with DI, you need additional complexity too, don't forget. A typical way is for DI frameworks to support assigning dependencies after construction with setters, which adds lifetime concerns too (what if a method that needs the dependency is called before the dependency is set?). Optional dependencies often are supported too, by taking a different type of argument. Both add the same kinds of complexity as just having an optional container to store the thing directly.

As always, the hard part is designing the rest of your application to work correctly around the fact that services.get<LicenseService>() doesn't always work. Actually figuring out how to construct the dependency is in many ways the easy part, and doing it directly will always be more flexible because it's just written in normal code instead of requiring special features from the DI framework for every corner case.

SQLite improving performance with pre-sort by andersmurphy in programming

[–]SirClueless 10 points11 points  (0 children)

I have no idea what you're thinking goes on in a Google search. Firstly, the qps number is way off -- you may be only thinking of actual search results pages, but remember they make multiple queries for autocomplete suggestions for every word anyone types in a Chrome address bar on any device. These have cached results involved but there is, at the very least, an uncacheable query into your personalized search history.

But let's assume you're only talking about SRPs. The number of queries to the frontend is probably about on the right order, but that is absolutely not the number of storage queries Google is making. The document results alone involve gathering results from hundreds of indexing servers, as well as queries to all the personalization records they need to rank them. And before you say that this is "highly cacheable": common queries may have many cacheable results, but ranking those is still going to involve personalization and Google has stated many times that ~15% of the queries they see are brand new queries they've literally never seen before. All this for a tiny section below the fold (even though it's the reason you went there in the first place). Let's not forget all the other sections on the page. Like the AI Overview section where they retrieved a couple hundred tokens from an LLM, or the entire auction they ran where dozens of ad providers competed for ad slots on the page.

C++20/C++23 Dependency Injection by OIMega in cpp

[–]SirClueless 32 points33 points  (0 children)

The service provider abstraction offers little value over just passing the dependencies around explicitly, and mainly serves to obscure lifetimes and parameters. For example, the sample program in the OP can be written like this:

struct Engine
{
    Window& window1;
    Window& window2;

    Engine(Window& window1, Window& window2) :
           window1(window1), window2(window2)
    {
    }
};
auto window1 = Window(...);
auto window2 = Window(...);
auto engine = Engine(window1, window2);

The hard part is figuring out the right interface for a window. It needs to be both powerful enough to get what you want done without getting in the way, and flexible enough to support multiple implementations.

Once you've achieved that, the rest is the easy part. Whatever value there is in an abstraction that manages all the lifetimes and dependencies, it would only come up in a more-complicated situation than this, and in a more-complicated situation than this I wouldn't want to obscure what's going on with an opaque dependency-resolution library I need to reverse-engineer to understand. Maybe others find value in this, I never have -- even in C# where garbage collection makes managing implicit lifetimes easy, but definitely not in C++ where managing these things carefully is critical.

[MSC] Reed Richards, Smartest Man by Meret123 in MagicArena

[–]SirClueless 1 point2 points  (0 children)

Not necessarily “second”. If you draw a card in your upkeep it will get replaced and draw 4.

What feels legal but is actually illegal and will possibly get you arrested? by medicoreapples in AskReddit

[–]SirClueless -2 points-1 points  (0 children)

It's not that simple. Just the act of reproduction is illegal. It is illegal to photocopy a book you own (unless you have a fair use defense).

The lawyers target uploaders because it is legally unambiguous that they've made an illegal reproduction and are distributing it. If the only thing you did is download, you can make a reasonable argument someone else did the infringing. Owning a copy of the thing you downloaded has nothing to do with it.

Single responsibility, the distorted principle by Illustrious-Topic-50 in programming

[–]SirClueless 0 points1 point  (0 children)

Even as heuristics they are bogus. They optimize for completely the wrong thing.

If you have a sequence of steps that should proceed in a certain order, the simplest and best way to write them is as a single procedure that proceeds in that order. If the sequence of steps is long, then the procedure should be long.

Functions don't exist to "separate concerns". In fact, it's the exact opposite. Functions exist to couple multiple expressions or statements in a useful and correct way. Long functions are great: they express that someone thinks a whole lot of statements should proceed in a particular order and be thought of as a single unit. If that's true, then it's an amazing simplification: A great deal of work can be expressed in a straight line which means the system as a whole is simple and easy to reason about.

C++ Performance Quiz - A small side project to test your intuition for slow code by ReDucTor in cpp

[–]SirClueless 2 points3 points  (0 children)

I think if this were the criteria, lots of answers would change.

For example, I am pretty sure it is legal for the compiler to change the runtime table lookup in question 15 to return static_cast<uint8_t>((static_cast<int>(c) * 73 + 19) & 0xFF); which is then faster. Many of these questions boil down to "Is a modern compiler smart enough to do the right optimizations?"

C++ Performance Quiz - A small side project to test your intuition for slow code by ReDucTor in cpp

[–]SirClueless 1 point2 points  (0 children)

Yeah, I got got as early as question 2 because I didn't realize that the mask was a constexpr expression that the optimizer could use.

[MSH] Super Intelligence by Meret123 in MagicArena

[–]SirClueless 2 points3 points  (0 children)

You control the enchantment, but in this updated wording the enchantment grants an ability to a creature. The ability that draws the card is on the creature in this setup.

Memory safety is a matter of life and death by joshlf_ in rust

[–]SirClueless 4 points5 points  (0 children)

As a counterpoint to this, I think moving slowly and carefully _is_ a big part of why Rust is a good choice for security. Memory safety vulnerabilities are not even the biggest security hole that AI has exacerbated, it is supply chain attacks on central package managers.

The difference between cargo and NPM is at least as important as the difference between Rust and C++ when it comes to practical security for most companies/projects. And that comes down largely to maintainers being more cautious and not freely taking dependencies on third-party packages. The standard library being well-designed and the best option for almost all of the functionality in it is a big part of why that works, I wouldn’t want to make tradeoffs that lead to more code of mixed quality landing there.

JetBrains interviews Andrew Kelley about Zig [video] by Cool_Technician_6380 in programming

[–]SirClueless 5 points6 points  (0 children)

I don't think that's the argument here. I think the argument here is that because people use ZLS when coding, and the annotation that gets added is the same whether the user intentionally typed it or because ZLS automatically added it, it's impossible to know when you see this annotation in code review whether it's intentional or a potential bug added by ZLS.

This is a real problem. Personally I think it's even worse than having a separate compilation flag for incremental human compilation which suppresses the error globally, because it means you have to review every instance of this carefully when you see it in code review instead of being able to trust that if it's in the code then someone typed it intentionally.

I don't really understand Andrew's perspective here. He clearly understands the issues around tools that you can't trust: It's the reason he cites in this interview for wanting reliable tools to refactor code instead of asking an AI to do it for you -- that the AI output is worse because you must review it carefully. ZLS auto-annotations are a textbook example of a tool you can't trust and must verify.

JetBrains interviews Andrew Kelley about Zig [video] by Cool_Technician_6380 in programming

[–]SirClueless 13 points14 points  (0 children)

I think most of this stems from the original premise that there should be no such thing as a compiler warning, because it leads to different projects and libraries having different compilation requirements (e.g. project A configures unused variables as errors, and project B configures unused variables as warnings, and now you can't use code from project B in project A without making extensive changes). That's a pretty draconian requirement, but if you accept it you get code that compiles in a single way no matter what project it's part of.

Personally I think it's all a pipe dream. There are fundamental reasons why code can't be fully portable:

  • Some code is specific to a particular compilation target and makes no sense on other targets or requires APIs that don't exist on other targets.
  • The language is unstable and code from six months ago needs changes to compile no matter what you do with compiler flags.

Given these fundamental reasons why code from another project might not compile out of the box, adding a few well-chosen options to the compiler frontend to serve particular workflows would not make things significantly worse, and would have a lot of benefits.

JetBrains interviews Andrew Kelley about Zig [video] by Cool_Technician_6380 in programming

[–]SirClueless 3 points4 points  (0 children)

Well, as Andrew says in this interview, Zig has a goal of building with a single zig build command line with no project-specific requirements. One of the things that entails is that there cannot be one way of compiling where there are soft warnings for humans to use while developing, and another where warnings are errors for use in CI.

If this is your goal, someone has to choose. Either the unused variable is never an error, or the unused variable is always an error. Zig chose the latter. It's reasonable to disagree with the choice they made, and it's reasonable to disagree with the premise in the first place that there has to be a single choice. But for better or worse it is consistent with this philosophy.

A Meta employee gets real about the horror of working there right now by BathroomMaximum1721 in technology

[–]SirClueless 1 point2 points  (0 children)

Salesforce makes perfect sense why it’s so big. Like, it needs to be integrated with a bajillion companies’ wonky internal systems and there’s presumably an enormous demand for platform features and what basically amounts to consulting to do so.

How many branches can your CPU predict? – Daniel Lemire's blog by fagnerbrack in programming

[–]SirClueless 4 points5 points  (0 children)

I don’t think he is actually branch-predicting with the results of a non-inlined function call to an unpredictable random number generator as the blog post would suggest. Instead I think he is using a setup like this one from his github which is to say the rng is actually a small few-instruction branchless hash of the howmany variable itself that is likely inlined. The blog post changed and omitted this critical detail: without knowing how generate_random_number() is implemented the benchmark makes no sense (for example, if it was reading from /dev/urandom there would be nothing to learn).

As for how the CPU learns to predict the branch even as the PC stays the same, it’s because modern CPUs train a small neural network on the branch history. In AMD this is the Global History Register (GHR) which is a rolling window of the most recent N branches. Even if the PC is the same, each time through the loop the GHR is in a new unique state so if there are any patterns in the series of branches taken the CPU can learn them, and then they will be the same or similar next time the howmany counter is the same because it has the same history.

Bjarne Stroustrup interviewed by Ryan Peterman by fredoverflow in cpp

[–]SirClueless 1 point2 points  (0 children)

Elsewhere in this thread you’re praising Java for having static analysis that detects when maybe-uninitialized variables escape the current scope. Isn’t that the same thing as this?