Live data from Hacker News

The compiler will optimize that away

blog.royalsloth.eu

71–80 of 329 posts

Re: The compiler will optimize that away

#71
post #42

> So far, the only programming language I know of that supports this type of crazy data transformations is JAI, As far as I know JAI is indeed the only language that explicitly lets you switch between AoS and SoA with one bit, but the APL family of languages - (APL, J, K, Shakti, and a couple more) has basically - for 60 years no - taken the "data oriented" SoA approach for storage, and provides the language support…

I also think that it's a shame he didn't bring up NumPy & Pandas, or R. He's just created a data frame and then complained that there's no functions to sort it, but we do have those. They are here.

    ants = pd.DataFrame({
      "name": ["bob", "alice", "carol"],
      "color":["red", "blue", "red"], 
      "age":[1.1, 0.5, 1.2], 
      "warrior":[True, False, True]})
    # Or read_csv to get the data in.

    # Count number of warriors.  True => 1, False => 0
    ants['warrior'].sum() # Returns 2

    # Count old red ants
    ((ants.color == "red") & (ants.age > 1.0)).sum() # 2 again

    ants.sort_values(by="age")
I think Pandas and NumPy should be up there as making the language easy to use in a SoA way.

Re: The compiler will optimize that away

#72
post #45

Earlier quoted context omitted.

> Somehow over the years I've found that the animals/cars analogies given in OO tutorials are one of the few places that fit well with the model. Yes, and I've never actually needed to implement a cat or a cow in any project :) The other thing for which OO works much better than plain data is GUIs - and I think it is not a coincidence that OO popularity exploded together with the the coming-of-age of GUIs. The other…

> The other thing for which OO works much better than plain data is GUIs This cannot be further from my experience. Switching from Java/AWT/Swing to ClojureScript/Reagent/Re-frame has been suoer liberating. Every GUI programmer must fiddle with reagent once: https://reagent-project.github.io/

Well, you really picked the worst representative with awt/swing. I'd say Qt or even classic VB6/Delphi are great examples for OOP gui development.

Re: The compiler will optimize that away

#73
post #44

Good article. My own thinking when coding performance is also towards data oriented approaches. For example Bevy in Rust. If stuff needs to be fast, it needs to be in cache. To do that, have everything nicely packed so you only ask for a chunk as often as you need. Then when you need it, it's already there. Thing about old fashioned OO is it's often fine enough for your run-of-the-mill CRUD app. If you look at the la…

> If you imagine a game that has characters, relationships, items, spells, and so on, it's often not that easy to model as encapsulated objects. Does each character have a list of other characters that they have a relationship with? What happens when you want to change the relationship, or a character casts a spell that temporarily changes the relationship? Can easily end up a mess, because it's not obvious where suc…

That sounds like a poor man's component if you already separated it into another class...? And that data is no longer belonging to the instance now.

Re: The compiler will optimize that away

#74
post #12

I can remember the columnar approach used in Fortran back in the day. Fortran did not have records, only scalar arrays, so a natural way to represent a bunch of "objects" was to have a bunch of arrays for each property value. IDK if such prior art is any helpful today, though :)

This approach is still used (conceptually, at least) in statistical computing. NumPy and R are good examples of this approach, and also have solutions for the indexing problems outlined in the article. That being said, statistical computing is at the mercy of the high cost of matrix multiplication. I think that you can alter the order of arrays in numpy, and examine the performance difference.

I think the desired functionality is closer to Pandas than Numpy — you want coordinated arrays of different data types, not higher-dimension arrays of the same data type.

R and Pandas aren’t exactly known for their outstanding native performance (they’re generally fast after converting dataframes to arrays and outsourcing to C or Fortran) so they’re great demonstrations of the syntax for some of these indexing problems but leave a lot to be desired.

Re: The compiler will optimize that away

#75

Good article. My own thinking when coding performance is also towards data oriented approaches. For example Bevy in Rust. If stuff needs to be fast, it needs to be in cache. To do that, have everything nicely packed so you only ask for a chunk as often as you need. Then when you need it, it's already there. Thing about old fashioned OO is it's often fine enough for your run-of-the-mill CRUD app. If you look at the la…

It's mostly a question of hierarchy of data and responsibilities. Character objects that administer changing relationships are doing too much.

For example, relationships involving "characters", "relationships", "items", "spells" etc can be handled by objects like "party" and "inventory" and "spell book" (glorified lists supporting a few custom named operations that basically do the same things) which contain the links to other objects. A spell that temporarily replaces your equipment simply swaps out your "character's" "inventory" object with some magical temporary one, and then swaps the real one back again when the "effect" from that "spell's" "invocation" ends. After this, adding support for something else like a spell that swaps inventory with the victim or steals their equipment would be trivial.

Convert this to functional terms and you've basically got a hierarchy of data that you operate functions on and generate new data to put back into the hierarchy, matching the morphing environment. It's all about the data in the end, regardless of your source point of view.

Re: The compiler will optimize that away

#76

Wish normal people witnessed how few innovations are being introduced on the CPU/GPU side in the 21st century. The high-performance software industry is low-key carrying the hardware architecture industry on its back. Shaders, pipelines, coroutines, etc are there to make the programmer's job easier in the end. On my old nokia 3110c, I could access my calendar and appointments instantly by clicking right on the d-pad.…

I can't believe anyone would say this, it is basically the opposite of reality.

CPUs and GPUs have come a long way in two decades. Even CPUs are incredibly fast, but between memory allocations, memory layout, multi-threading and just weeding out terrible algorithms, most software can probably be sped up by 100x.

> The high-performance software industry is low-key carrying the hardware architecture industry on its back.

That doesn't even make sense. Do you think GPUs aren't more powerful than 20 years ago and that the difference between quake 3 and Order 1888 is software?

> On my Nokia 3.1, I had to wait for internet synching. The difference between slow and fast software far outstretches that of slow and fast hardware.

Right - doesn't this contradict everything you just said?

Re: The compiler will optimize that away

#77
There’s a nice introduction to a data-oriented approach in here, but it’s buried in some junk.

E.g., I don’t think a lot of developers believe compilers are magic optimizers. And programming languages, including the ones referenced, have changed quite a bit over the last 20 years. A strong enough case for general data-oriented features would cause at least some of them to support it.

Also, a great amount of code should be written for maintainability — that is, to be read and easily understood by a future developer without special insight — rather the performance. Talk of “software cultists” is silly and shows how poorly the author understands the issues driving software development approaches.

Not to mention, a performance analysis of software systems that stops at main memory is about only a subset of software (one that has a pretty thin slice of overlap with “enterprise” software, where your bottlenecks are overwhelmingly IO and DB).

Re: The compiler will optimize that away

#78
post #64

Bullshit! The most important feature for the utter most of enterprise software is to be maintainable over requirement, managing and employee changes. Such optimizations as those described in the article make sense only in a handful of situations, and using them must not be a light-heart decision, because their cost is big. I fully agree with going all in when it makes sense, but we all know what is the root of all ev…

> Such optimizations as those described in the article make sense only in a handful of situations, and using them must not be a light-heart decision, because their cost is big.

This is really not true. Inheritance is not only slow it is needlessly complicated. It introduces dependencies and indirection while gaining nothing.

People who have never programmed before think having a car class inherit from a vehicle class makes sense. Eventually they realize that what they have are arrays of positions and velocities that they need to combine. That could be multiple files with lots of boiler plate nonsense or it could be a single loop.

> I fully agree with going all in when it makes sense, but we all know what is the root of all evil.

If you are implying optimization, you should realize that that quote comes from someone telling his students not to noodle the tiniest details like post or pre increment in their for loops to get the compiler to output one less instruction when their program isn't even done yet.

If you want modern software to run fast, you need to architect for it first. Then you can make things work, then you can profile and optimize. This idea that there are no consequences to the early design decisions you make is a gross distortion of the context of this quote.

Re: The compiler will optimize that away

#79
The implicit premise of the article seems to be that all software has to be heavily optimized. This is completely wrong. All the languages mentioned in the article are still around because it doesn’t matter how performant 99% of code is. For the 1%, we can think about cache misses, SIMD and data parallel approaches. In my experience this is totally possible and not too hard, but has the enormous downside of making that code hard to reason about. You are also optimizing for today’s hardware, which means that it might not run that great on new hardware in 20 years. This means that somebody has to go in and rewrite that hard to understand optimized code. It’s really a tradeoff between the cost of that and the benefits from optimization.

Some of the future costs can be mitigated by using a few techniques from the start. One good idea is to keep an vanilla unoptimized version of the part that you are optimizing around as a reference implementation. This will help understanding what the optimized code does and can be used as a stopgap to support new hardware. It can also be a nice baseline to compare optimizations against.

The beauty of compilers is that they do a decent job of optimizing the 99% of code that would otherwise never be optimized, at 0 cost. This is a different sweet spot on the cost benefit curve.

Re: The compiler will optimize that away

#80
post #49

Earlier quoted context omitted.

It is easy to declare, but it is not easy to use: You can pass the whole thing, but if you want to pass a subset of it? just one element? When you want to extend it, you have to extend many individual arrays, etc. When you want to copy entry 17 to entry 50, you can't loop over the fields - you have to spell out every field.

A subset of an AntColony is another AntColony containing sub-arrays. One element of an AntColony is an Ant which you can instantiate with the data at the appropriate index from each array. I'm not trying to be difficult, I really don't see the problem with implementing these basic programming tasks. I agree that spelling out the fields can become tedious if you have a lot of structures of arrays or lots of fields per…

> I really don't see the problem with implementing these basic programming tasks.

That you have to write them over and over again for every single class. You offer to do that with Python.

> But not a big limitation, I'd argue. Many languages even have features that allow you to write this functionality as a library, 100% inside the language (Python and Java annotations, for example).

This is an argument of the "all languages that are Turing complete are essentially equivalent" kind. True, but not interesting in this context.

Ecosystem matters. If your Java program is the only one that does these things, it may just as well not be Java. You will be unable to use any other library without back-and-force adapters, for example.

Post reply on HN