Quotes: 2:48 Life is really simple, but we insist on making it complicated - Confucius 4:15 Any intelligent fool can make things bigger, more complex and more violent, It takes a touch of genius - and a lot of courage - to move in the opposite direction - Einstein 37:20 Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away - Antione de Saint -Exupery. 49:00 If you can’t explain something to a first year student, then you haven’t really understood it - Richard Feynman 50:38 If you have two equally likely solutions to problem, choose the simplest, Occam’s Razor 56:05 Everything should be made as Simple as possible, But not simpler - Einstein 57:20 Simplicity is the ultimate sophistication - Leonardo da Vinci
00:00 Intro 01:16 Human Brain 6:40 Cannot define Simple. Define What Simple is not? 7:19 Simple is not clever 12:56 Simple is not necessarily familiar 15:18 Code example 21:40 Simple has fewer moving parts 22:11 Simple is not over-engineered 23:27 Rube Goldberg 27:00 Simple is not Terse : Nunit and Junit story, Tony Hoarer quote. 30:35 Well then What’s Simple? 31:00 Simple keeps you focused Example of search engines home page. 38:10 simple eliminates accidental complexity and hides inhered complexity 38:42 Simple fails less 43:50simple’s easier to understand and work with 45:00 isPrime code example 45:35 Simple is elegant 46:45 An Architect’s Dilemma 48:42 Simplicity has to evolve 51:00 Factorial example and Tail Recursion 56:50 Simple makes things easy, but It’s certainly not easy 57:23 Close
You have a problem with the inverse sqrt function? The only thing it was missing was a comment explaining why it works. I can read that and know what it is doing, but I couldn't tell you why that would give you the correct answer. In that case, a comment really is the answer. That looked both pretty simple and fast. As long as it is correct (on the compiler that they are using, since I am pretty sure there is some UB in there), the programmer did their job. There is an aspect of simplicity that you forget, and that's writing code that doesn't lie to you about what the CPU has to do to solve the problem. We are programming machines, not languages. The choice to replace what could be 2-3 lines of simple code with one line of ridiculous functional code was particularly amusing. You replaced one for loop with three and tripled the potential memory consumption (whether the implementation can come up with an optimization to make up for your sloppiness in this case is irrelevant) just so you could write it in a functional style on one line? If you are writing a quick, one-off script for something, then that's fine because worst-case scenario someone else can just completely re-write your code if they have to, but I would fire you if you pulled that crap in a serious application. Don't even get me started on the primes example... Say you write your entire code-base in that "style". Now, 6 months later, your app's performance is dog shit and crashes randomly. How do you expect to debug that? Sure, your code may be "beautiful" and/or "elegant", but none of that matters if your end product is a pile of crap. It's ideas like these that are responsible for the state of web development (and non-native development in general) at present. If you have a choice between writing a few lines of plain old branching / control flow and calling out to a library to do it one line at the cost of memory or performance, it's almost always better to just write the damn for-loop... Just look at where AAA games are right now: high productivity and high quality products that are more technically impressive every year. Now, look back at web development: there's a new fad framework out every few months because somebody found a way to do the old stuff in a more "elegant" way, productivity is terrible, web app quality is terrible, and it still takes web apps SECONDS to do very simple things. It's absolutely pathetic, and it's getting WORSE! If you write code this way, you may call yourself a JavaScript programmer, a Java programmer, etc., or even a web developer, but never, ever, call yourself an engineer. That title is reserved for those of us who actually give a shit about software quality and getting the most out of the hardware that our software is running on.
You sir made me laugh, a lot :). You think you'll get better performance if you write a plain For loop instead of .forEach or whatever ? you're wrong. Functional code and imperative code have the same time of execution. (Measure it). But what you can do with functional style is turn it into parallel program with no effort at all while you will be stuck with Threads, Locks, Fibers which can be simple to write, and take you a lifetime to solve bugs when they occur. Imperative code comes with a lot of accidental complexity, it encourages shared state, temp variables and ugly stuff. About comments, comments are annoyance, they are dead they never evolve, the only truth is in the code itself.
It's not `for` vs. `foreach` with a lambda. That part is roughly equivalent (assuming the lambda or callback passed to it is inlined). It's turning one for loop into two or three + a potential 3X memory consumption that was silly. Functional code only has the same performance as procedural code when it's directly equivalent, e.g. a simple math function returning by value instead of by reference. In that case, the compiler with generate the pass by reference code to elide the copy. The resulting code is easier to reason about in that case, so functional programming wins out. As for the threading bit, that is the main point that FP advocates assume is correct. Unfortunately, they are completely wrong. The key to parallelism is organizing your data to be operated on in bulk, and the key to thread synchronization is to treat threading as a first-class concept in your code base so that 90% of the code doesn't have to worry about it. Yes, simply treating everything as immutable and copying everything "solves" the thread synchronization problem, but it means that whole classes of performance critical applications can't reach their potential. Do you enjoy AAA video games? Operating systems? Would it be reasonable for all of those applications to become (conservatively) 2X slower and consume twice the amount of memory because they aren't allowed to perform any data transformations in-place? No, I don't think it would. To put this in some context, imagine the physics system of a game is operating on hundreds of thousands of rigid bodies. Treating them as immutable means one of two things, either 1) each struct has to be individually copied somewhere else, the old one free'd, and then the copied struct transformed; or, 2) the entire array of structs needs to be copied and transformed individually (without the free). The first case has roughly the same memory footprint but requires a copy and a free between each transformation, which kills pipelining, SIMD, data-locality, etc., and the second case requires twice the amount of memory. If each structure is around 128 bytes(wayyyy conservative), that's 12.8 M. Doubling that, you get 25.6 M (and the extra copy in there is enough to screw performance, anyway). That is a _huge_ price to pay (for that and every similar type of transformation in a system) in either case just to serve some ideology and to not have to think about how threading is supposed to work in your application. At this point, some FP advocates say that optimization can be performed to make this stuff fast and not copy things internally. This is not true. At least, it's not true for the lowest level application in the chain. In JS, you are running on V8 or something similar. In native applications, like V8 itself, you aren't running on anything but the computer, and nobody's there to cleanup your unnecessary copies and make your program magically not as crappy as you would have expected. Bottom line is that we, the entire high-performance industry, _have_ measured it, and we have performed a cost-benefit analysis of FP (and OOP) vs procedural, and we use FP where it makes sense, which is _not_ everywhere. FP is _not_ a magical solution to everything and shouldn't be marketed as such. You might say that the performance difference for a lot of simple JS code (or any other scripting language) is negligible (and you'd be right), but writing simple scripts is _not_ engineering; it's scripting. That was the point I was trying to make. If you take these simple trade-offs that make sense for small scripts and scale them up to a large system, they no longer make sense, and you get the steaming pile of crap that is the internet.
where do you get that "X3 memory consumption"? the pipeline he is appending to the collection consists of pure functions, they don't modify the data, hence they don't have to create new instances. I love this guy, he also gave a great talk on mutability. you should check it out, seems like you could learn a lot from him
Quotes:
2:48 Life is really simple, but we insist on making it complicated - Confucius
4:15 Any intelligent fool can make things bigger, more complex and more violent, It takes a touch of genius - and a lot of courage - to move in the opposite direction - Einstein
37:20 Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away - Antione de Saint -Exupery.
49:00 If you can’t explain something to a first year student, then you haven’t really understood it - Richard Feynman
50:38 If you have two equally likely solutions to problem, choose the simplest, Occam’s Razor
56:05 Everything should be made as Simple as possible, But not simpler - Einstein
57:20 Simplicity is the ultimate sophistication - Leonardo da Vinci
00:00 Intro
01:16 Human Brain
6:40 Cannot define Simple. Define What Simple is not?
7:19 Simple is not clever
12:56 Simple is not necessarily familiar
15:18 Code example
21:40 Simple has fewer moving parts
22:11 Simple is not over-engineered
23:27 Rube Goldberg
27:00 Simple is not Terse : Nunit and Junit story, Tony Hoarer quote.
30:35 Well then What’s Simple?
31:00 Simple keeps you focused
Example of search engines home page.
38:10 simple eliminates accidental complexity and hides inhered complexity
38:42 Simple fails less
43:50simple’s easier to understand and work with
45:00 isPrime code example
45:35 Simple is elegant
46:45 An Architect’s Dilemma
48:42 Simplicity has to evolve
51:00 Factorial example and Tail Recursion
56:50 Simple makes things easy, but It’s certainly not easy
57:23 Close
Venkat's talks are always a delight
This video changed the way i think thanks #venkat
great talk
aweseome talk
Great video Venkat, you are amazing!
Wonderful talk.
You have a problem with the inverse sqrt function? The only thing it was missing was a comment explaining why it works. I can read that and know what it is doing, but I couldn't tell you why that would give you the correct answer. In that case, a comment really is the answer. That looked both pretty simple and fast. As long as it is correct (on the compiler that they are using, since I am pretty sure there is some UB in there), the programmer did their job.
There is an aspect of simplicity that you forget, and that's writing code that doesn't lie to you about what the CPU has to do to solve the problem. We are programming machines, not languages. The choice to replace what could be 2-3 lines of simple code with one line of ridiculous functional code was particularly amusing. You replaced one for loop with three and tripled the potential memory consumption (whether the implementation can come up with an optimization to make up for your sloppiness in this case is irrelevant) just so you could write it in a functional style on one line? If you are writing a quick, one-off script for something, then that's fine because worst-case scenario someone else can just completely re-write your code if they have to, but I would fire you if you pulled that crap in a serious application. Don't even get me started on the primes example...
Say you write your entire code-base in that "style". Now, 6 months later, your app's performance is dog shit and crashes randomly. How do you expect to debug that? Sure, your code may be "beautiful" and/or "elegant", but none of that matters if your end product is a pile of crap. It's ideas like these that are responsible for the state of web development (and non-native development in general) at present. If you have a choice between writing a few lines of plain old branching / control flow and calling out to a library to do it one line at the cost of memory or performance, it's almost always better to just write the damn for-loop... Just look at where AAA games are right now: high productivity and high quality products that are more technically impressive every year. Now, look back at web development: there's a new fad framework out every few months because somebody found a way to do the old stuff in a more "elegant" way, productivity is terrible, web app quality is terrible, and it still takes web apps SECONDS to do very simple things. It's absolutely pathetic, and it's getting WORSE!
If you write code this way, you may call yourself a JavaScript programmer, a Java programmer, etc., or even a web developer, but never, ever, call yourself an engineer. That title is reserved for those of us who actually give a shit about software quality and getting the most out of the hardware that our software is running on.
Nerd..
Yes.
You sir made me laugh, a lot :).
You think you'll get better performance if you write a plain For loop instead of .forEach or whatever ? you're wrong.
Functional code and imperative code have the same time of execution. (Measure it). But what you can do with functional style is turn it into parallel program with no effort at all while you will be stuck with Threads, Locks, Fibers which can be simple to write, and take you a lifetime to solve bugs when they occur.
Imperative code comes with a lot of accidental complexity, it encourages shared state, temp variables and ugly stuff.
About comments, comments are annoyance, they are dead they never evolve, the only truth is in the code itself.
It's not `for` vs. `foreach` with a lambda. That part is roughly equivalent (assuming the lambda or callback passed to it is inlined). It's turning one for loop into two or three + a potential 3X memory consumption that was silly.
Functional code only has the same performance as procedural code when it's directly equivalent, e.g. a simple math function returning by value instead of by reference. In that case, the compiler with generate the pass by reference code to elide the copy. The resulting code is easier to reason about in that case, so functional programming wins out.
As for the threading bit, that is the main point that FP advocates assume is correct. Unfortunately, they are completely wrong. The key to parallelism is organizing your data to be operated on in bulk, and the key to thread synchronization is to treat threading as a first-class concept in your code base so that 90% of the code doesn't have to worry about it.
Yes, simply treating everything as immutable and copying everything "solves" the thread synchronization problem, but it means that whole classes of performance critical applications can't reach their potential. Do you enjoy AAA video games? Operating systems? Would it be reasonable for all of those applications to become (conservatively) 2X slower and consume twice the amount of memory because they aren't allowed to perform any data transformations in-place? No, I don't think it would.
To put this in some context, imagine the physics system of a game is operating on hundreds of thousands of rigid bodies. Treating them as immutable means one of two things, either 1) each struct has to be individually copied somewhere else, the old one free'd, and then the copied struct transformed; or, 2) the entire array of structs needs to be copied and transformed individually (without the free).
The first case has roughly the same memory footprint but requires a copy and a free between each transformation, which kills pipelining, SIMD, data-locality, etc., and the second case requires twice the amount of memory. If each structure is around 128 bytes(wayyyy conservative), that's 12.8 M. Doubling that, you get 25.6 M (and the extra copy in there is enough to screw performance, anyway). That is a _huge_ price to pay (for that and every similar type of transformation in a system) in either case just to serve some ideology and to not have to think about how threading is supposed to work in your application.
At this point, some FP advocates say that optimization can be performed to make this stuff fast and not copy things internally. This is not true. At least, it's not true for the lowest level application in the chain. In JS, you are running on V8 or something similar. In native applications, like V8 itself, you aren't running on anything but the computer, and nobody's there to cleanup your unnecessary copies and make your program magically not as crappy as you would have expected.
Bottom line is that we, the entire high-performance industry, _have_ measured it, and we have performed a cost-benefit analysis of FP (and OOP) vs procedural, and we use FP where it makes sense, which is _not_ everywhere. FP is _not_ a magical solution to everything and shouldn't be marketed as such. You might say that the performance difference for a lot of simple JS code (or any other scripting language) is negligible (and you'd be right), but writing simple scripts is _not_ engineering; it's scripting. That was the point I was trying to make. If you take these simple trade-offs that make sense for small scripts and scale them up to a large system, they no longer make sense, and you get the steaming pile of crap that is the internet.
where do you get that "X3 memory consumption"? the pipeline he is appending to the collection consists of pure functions, they don't modify the data, hence they don't have to create new instances. I love this guy, he also gave a great talk on mutability. you should check it out, seems like you could learn a lot from him