CppCast - Kvasir

Episode Date: November 9, 2016

Rob and Jason are joined by Odin Holmes to talk about developing for Embedded Microcontrollers with C++ and the Kvasir library. Odin Holmes has been programming bare metal embedded systems for... 15+ years and as any honest nerd admits most of that time was spent debugging his stupid mistakes. With the advent of the 100x speed up of template metaprogramming provided by C++11 his current mission began: teach the compiler to find his stupid mistakes at compile time so he has more free time for even more template metaprogramming. Odin Holmes is the author of the Kvasir.io library, a DSL which wraps bare metal special function register interactions allowing full static checking and a considerable efficiency gain over common practice. He is also active in building and refining the tools need for this task such as the brigand MPL library, a replacement candidate for boost.parameter and a better public API for boost.MSM-lite. News Compiler Explorer's embedded view A peek into the WebAssembly Browser preview WebAssembly Browser Preview Cling on Ubuntu on Windows Odin Holmes @odinthenerd Odin Holmes on GitHub Odin Holmes' Blog Links Kvasir Meeting C++ Lightning Talks - Odin Holmes - Modern special function register abstraction Brigand Embedded C++ Conference in Bochum Sponsor JetBrains

Transcript
Discussion (0)
Starting point is 00:00:00 This episode of CppCast is sponsored by JetBrains, maker of excellent C++ developer tools, including CLion, ReSharper for C++, and AppCode. Start your free evaluation today at jetbrains.com slash cppcast dash cpp. And by Meeting C++, the leading European C++ event for everyone in the programming community. Meeting C++ offers five tracks with seven sessions and two great keynotes. This year, the conference is on the 18th and 19th of November in Berlin. Episode 78 of CPP cast with guest Odin Holmes recorded November 3rd, 2016. In this episode, we discuss WebAssembly coming to your browsers. Then we talk to Odin Holmes.
Starting point is 00:01:01 Odin talks to us about developing for microcontrollers in his Kvasir library. Welcome to episode 78 of CppCast, the only podcast for C++ developers by C++ developers. I'm your host, Rob Irving, joined by my co-host, Jason Turner. Jason, how are you doing today? I'm doing all right, Rob. How about you? Doing pretty good. We're doing a little bit of time travel this week, right? Yeah. We'll be recording today, releasing it sometime next week and uh
Starting point is 00:01:47 because i'll be out of town and i gotta say i kind of wish we could be actually time traveling right now because then we could skip ahead to uh november 9th or 10th when the election's over that's about all i'm willing to say about politics i don't want to alienate anyone but uh i'm looking forward to it being over i i will i i will say that i have not met a single person who is excited about this election yeah so i think everyone's ready for it to be over yeah pretty much okay well at the top very episode i'd like to read a piece of feedback uh we got one here today from iran who writes in from israel it says been listening to various programming related podcasts for a while but yours is just unbelievably spot on my interest from Iran who writes in from Israel. It says, I've been listening to various programming-related podcasts
Starting point is 00:02:26 for a while, but yours is just unbelievably spot-on my interest. Keep on with the great work. To contribute my share, I'd like to suggest a topic, Dynamic Binary Instrumentation and Optimization. The most prominent tool I'm aware of is Intel PIN, which provides an API that allows monitoring various types of commands at runtime as well as modifying the program in memory. This provides a relatively short path in profiling executables
Starting point is 00:02:49 and optimizing them accordingly without access to the source code. PIN isn't alone in this field, of course. Some compilers offer PGO, FileGrind, or use similar techniques, but it's unique in being a platform for tool development. I believe the ability to dynamically interact with an executable can be mind-opening and writing dedicated tools can provide new insights into what your programs are really doing at runtime. While this is not a C++-specific topic,
Starting point is 00:03:13 it may suit your audience. So that's definitely not something I'm familiar with, Intel PIM, but I know Intel puts out a bunch of really interesting tools for programmers. Yeah, I've never heard about that at all. But it definitely might be a topic we could cover on the show. We'll have to see if we can look into that a little bit more. We had someone else from Intel on, right?
Starting point is 00:03:35 Talking about hardening of executables? Yes. Yes, we did have someone from Intel on a while ago. But yeah, Euron, thank you for the suggestion. It's definitely something that could be interesting. We'd love to hear your thoughts about the show as well. You can always reach out to us on Facebook, Twitter, or email us
Starting point is 00:03:51 at feedback.cvpcast.com. And don't forget to leave us a review on iTunes. Joining us today is Odin Holmes. Odin has been programming bare metal embedded systems for 15 plus years, and as any honest nerd admits, most of that time was spent debugging his stupid mistakes.
Starting point is 00:04:07 With the advent of the 100x speedup of template metaprogramming provided by C++11, his current mission began teach the compiler to find his stupid mistakes at compile time, so he has more free time for even more template metaprogramming. Odin is the author of the Kvasir.io library, a DSL
Starting point is 00:04:24 which wraps bare metal special function register interactions, allowing full static checking and a considerable efficiency gain over common practice. He's also active in building and refining the tools needed for this task, such as the Brigand MPL library, our placement candidate for Boost Parameter, and a better public API for Boost MSM Lite. Odin, welcome to the show. Hi, guys. Thanks for joining us. Yeah, it's a pleasure. I'm curious how you got started in embedded systems, if you've been doing that for over 15 years now.
Starting point is 00:04:54 Oh, Assembler. I think like pretty much anyone at that point. Back then, you couldn't really get a c compiler even for uh most chips okay so when what did you start programming with then i guess what was your first uh experience programming uh pick pick uh um processors uh that was your first experience overall um yeah well, I did a little bit of like, C for dummies and C++ for dummies. And I was like, super isolated as a nerd as a kid, because I grew up like among hippies and suddenly programming like I somehow was hung up on parameters being positional. That took me like two weeks to figure out that it wasn't like they were matching names. They were just matching positions and types. So like if you're super isolated, yeah.
Starting point is 00:05:58 And so I got more into electronic design. I'm actually a half-decent electronic engineer. And then I came back to programming, yeah, programming picks because I needed some processing power in my electronic design. Interesting. I did nothing but pick assembler for years. And then at some point, the systems I was making got pretty complex and I got a really hard to find bug like my my ring buffer was
Starting point is 00:06:35 being corrupted and usually was being corrupted in an area that wasn't actually being used and so it's like a super seldom bug and it took me like three weeks to find it not a friend of mine helping me trying to find it and then you know he had this offhand comment like if you'd used a real programming language that wouldn't have happened and yeah it kind of stuck with me i didn't really act on it for you know another year or two and i had gotten into some you know windows programming in c++ so i basically leapfrogged c in my whole development um went straight from uh assembler to uh c++ uh i mean i i somehow do things the hard way a lot of the time like my my second c++ book was uh modern c++ by andre alexandrescu which i had to read like
Starting point is 00:07:21 five times before i understood anything. I imagine. But it kind of like my feeling for how people write programs was like I thought, oh, I'm doing things like the normal way by making things policy-based. Yeah, and it wasn't until three years ago that I really started being active in any kind of C++ user group stuff and noticed that, oh, I'm kind of the oddball out. That's interesting. I think it might be the first person we've had who got started on microcontrollers oh yeah um i i mean there are a lot of people that got started on microcontrollers but i think very few of them have switched to c++ and hence are not on your show i mean i'd imagine actually your last guest dan sacks i imagine he probably started on microcontrollers you know probably far before i was born but uh yeah he might be a candidate for
Starting point is 00:08:22 that title maybe i mean he probably started on machines that were less powerful than today's microcontrollers, but put it that way. Almost certainly, yes. Yeah, plenty of people on here have started on 8-bit systems, yeah. Okay, well, Odin, we have a couple news articles to discuss, and then we'll start talking to you more about C++ on microcontrollers, okay? Sure.
Starting point is 00:08:45 Okay, so this first one, Jason, maybe you can talk about this, is an update on Matt Godbolt's blog about some new features in Compiler Explorer. Yeah, so the Compiler Explorer, he's been doing a ton of UI updates lately. I showed some of them in my talk at CppCon, but his most recent update is that you can now do embedded Compiler explorer views on your own web page so if you have a code snippet and you want to show how this compiles to assembly you can just put some javascript in your web page get an embedded view and that does seem like uh i mean we've looked at plenty of recent blog posts that have been referencing uh gcc godbolt
Starting point is 00:09:19 so he's just making gonna make it a lot easier because people have been like embedded just putting the links because you can embed all the code in the link, I think. Yes. But now you'll be able to just embed it to Vue. That's awesome. Yeah, with, I guess, the compiler selection, whatever, that you want to demo to. I haven't played with it enough to see how it works. If you have multiple compilers and you want to do that embedded, it seems like it would start to get crowded quickly. Right. Definitely a great new feature.
Starting point is 00:09:44 Okay, next up up we actually have two articles one from windows and microsoft edge team and one from mozilla the firefox team and they're talking about the web assembly going into a browser preview state so it's kind of hard to believe that they've done this much work so fast that they're getting to the point where we can actually try it out in our browsers. I think it's on the Mozilla side, they're saying it's available now, and if you just turn on a certain flag to enable WebAssembly, you can go ahead and run with it. Yeah, it's astounding just how much effort this is being put into these systems,
Starting point is 00:10:24 and the performance that they're starting to get is pretty crazy. Yeah, they do have a little graph here on the Mozilla page comparing throughput of ASM.js and WebAssembly. And ASM.js, it's already showing pretty impressive performance, but WebAssembly is maybe about 10 or 20% faster. Right. Anything you wanted to mention on this one, Odin? No, it's not really my neck of the woods, but anything closer to native is welcome in my mind. Yeah, absolutely.
Starting point is 00:10:57 So we had JF on here talking about this, right? Yeah, and it's been like a year since we found him on. That's what I was just wondering. July 9th. And that was right after it was first announced. And this Mozilla article is saying they're expecting the WebAssembly to be, the design spec to be finished and to kind of go live in March next year. So that's a lot of work in just under two years.
Starting point is 00:11:28 Yeah. And, you know, I just still have such a hard time wrapping my mind around the fact that if you compile C++ to JavaScript, it's like orders of magnitude faster than running native JavaScript. Yeah. Yeah, it's pretty crazy. Okay. This next one is actually a YouTube video
Starting point is 00:11:49 from a former guest, Dimitri Nustruk, and it's Kling on Ubuntu on Windows, which is pretty crazy to wrap your mind around. Basically, Windows 10 recently added an Ubuntu subsystem? Yes. Yeah. Have you played around with that at all, Jason? I haven't, but the people that I know who have say it's pretty sweet.
Starting point is 00:12:11 It works pretty well. Yeah, I think I have it enabled, but I haven't actually gone and tried to mess around with it at all. But yeah, if you're a developer on Windows, you can now turn on Ubuntu and get the full bash shell and everything else you would want. And because of this, we can now get cling on Windows pretty easily. And Dimitri has this video where he's just walking people through how to get cling set up on Windows and how to
Starting point is 00:12:35 play around with it. Yeah, I still personally haven't found a use case for cling. But I'm always in favor of more tools on more platforms yeah absolutely okay well uh odin let's start talking to you about microcontrollers um to start off maybe tell us what kind of hardware you work with well a lot of stuff in my day job uh um you know spanning from 6k a ram to 256k a ram uh mostly arm cortex you know we have some legacy stuff but every all new designs are uh arm cortex uh you know m034 because i mean they're essentially as cheap as another microcontroller and they're as powerful as my first pc was so yeah a bit less ram but uh you know as far as processor power so if we can dig in just a little bit by legacy what do you refer to oh the the pics uh we actually have some
Starting point is 00:13:32 products that have been around for 12 years now um and it's actually quite interesting we come up with a lot of uh memory management stuff to try and get new features into these old picks that have you know maybe uh 300 bytes of ram and so yeah i mean uh you can get pretty far away from the classic uh stack and heap model if you uh if you adapt that very much to your own uh design 300 bytes is pretty limiting yeah yeah um yeah but i i wouldn't suggest it if you like having free time yeah no it's i mean we have a lot of them in the field so it's kind of a curse uh um but uh yeah it's a lot more fun to work on the new ones where we can use real C++. So then you say ARM Cortex, which I'm not terribly familiar with the ARM family line.
Starting point is 00:14:35 What does that give you? What's the lowest-end ARM that you use? The lowest-end ARM is the Cortex-M0, and you can get it, you know, they start at about 48 megahertz with 6K RAM, and usually have a lot of peripherals on the board, though. Like, they'll have a USB, you know, CAN bus, several UARTs, comparators, op amps, analog digital converters, all that stuff on one chip. A lot of times they even have the oscillator on chip. So for, you know, 50 cents or maybe 60 cents, you can already get a fully functioning processor. And maybe it's a little more than a dollar
Starting point is 00:15:18 if you want USB connectivity. But that's like a whole system on chip, basically. Like the RAM's on there, flash the rams on their flashes on their crystals on there and yeah I mean there there there's not really much of a market in my eyes for anything below cortex I mean I'm pretty sure people will come up with a lot of stuff but for for anything that needs to connect to any modern systems, Cortex is the way to go. So it's a 32-bit arm. You can use GDC with it, whatever.
Starting point is 00:15:50 Yeah, it's the same Thumbtube instruction set as the bigger arms. I mean, some of the stuff is implemented differently. Like, I don't know, compare and swap will fail if there's any interrupt, because as soon as you don't have multiple cores, it could only be an interrupt. And so they just hardware it. Even if that memory isn't being touched, it just says,
Starting point is 00:16:13 ah, it was touched if there was any interrupt in between. So it is a little bit different than the big ones. But for the most part, it's probably not a whole lot different developing for these tiny chips than it is for the more mainstream stuff. part, it's probably not a whole lot different developing for these tiny chips than it is for the more mainstream stuff. From a core standpoint, from a RAM and other
Starting point is 00:16:33 resources standpoint, it is very different. Okay. Do you want to tell us a little bit about the open source library you work on, Kvasir? Am I pronouncing that right? Well, I think it's probably debatable it was it was a norse god uh we figured you know since the loki library was a norse god we we'd name our uh and it's uh i guess if with a bit of stretch of the imagination it was the god of
Starting point is 00:16:56 innovation right kvasir so uh that's why we named it that and it was one of the only norse gods that didn't have like special characters in the name which which would have been hard. But yeah, Kvasir is basically what grew out of that seed that a friend of mine planted in my brain that you should just use language tools to not be able to make those kinds of mistakes. And so, uh, with, uh, what we've done so far, um, is been to, uh, abstract, you know, add a layer of abstraction around any interaction with, uh, special function registers, which is where you're actually talking directly to the hardware, right? So, you know, configurations of things, interrupt status flags, that kind of stuff. Because that's where a lot of the bugs come from. I mean, first of all, you have to market volatile and nobody understands volatile very well, including like even compiler implementers. I mean, going back to Matt Godbolt's awesome tool, if you play around with the volatile keyword, I'm sure you'll find some stuff that it's doing wrong in even modern GCC.
Starting point is 00:18:08 So if it's something that's iffy, then it's a good idea to wrap it, right? Because then you have one place to adapt to compilers doing weird stuff. The problem is that volatile takes away a whole lot of the compiler's ability to optimize things, especially it's a blunt tool. but allow reordering in another place, like in one use of the variable in one context and in another context you want to do it differently, you mark that variable volatile,
Starting point is 00:18:52 and so it won't be reordered. And reordering on these tiny chips actually adds a lot more performance than you would think because addresses are 32-bit, but instructions are 16. So to actually add, to actually load a full address takes like three instructions. But you do also have a load with offset.
Starting point is 00:19:17 So if you can reorder things to where they're next to each other, as far as an address space, then you can save a lot of loads, a lot of address loading. Interesting. So, yeah, you know, I don't want to get too deep into the weeds. I know this is, you know, outside the domain of probably most of the listeners. But what we did was to make constexpr global variables, which are basically just empty structs. But we put all the knowledge that we have about this bit field that this global variable is representing,
Starting point is 00:19:53 we put all of that into the template parameters. And so you can pass these things in sort of a C-like syntax to functions that are also templated, and they can work on this template information and then pass whatever result they have back. And so you can do like a big, lazy, evaluated chain of stuff. And then at the end of the chain, you can do optimizations at compile time using template metaprogramming and then generate the most efficient, most safe code you could. And then you can, you know, like you can't write to a read-only bit fields
Starting point is 00:20:28 or read-only bits. You can make other rules like, you know, you have, for example, some bits that get cleared when you read the register. So you can force the user to write read and clear rather than read because you have this information. You can get this information from the same source as the debugger gets its information, ARM standardized like hardware description files, which we put through a Python script
Starting point is 00:20:55 and generate these global variables with all this information in there. So yeah, essentially we've taken a whole category of potential errors that the user can make out of, I mean, it won't compile, right? It's not something you'd see at runtime. It'll happen at compile time and you won't ship it. And the odd side effect that we found, which we didn't actually initially expect, is that we can do much better optimizations than somebody writing C can. I mean, they could, theoretically, but no one could be able to read the code, and so they don't, right? is that we can do much better optimizations than somebody writing C can. I mean, they could, theoretically, but no one could be able to read the code, and so they don't, right?
Starting point is 00:21:37 Plus, if, you know, if me and my team of super nerds that look at this stuff all day come up with some stuff, then we can put it in there and it benefits everybody, even if you don't know how, you know, the special functions of this particular chip work, right. It's, you know, encapsulated expertise. So, uh, yeah, we've been porting some, uh, libraries from chip vendors or from, uh, arms embed to use our stuff. And sometimes like the flash footprint shrinks almost an order of magnitude. Wow. Yeah. I mean, one of the things that is probably the biggest, biggest bang for your buck is initialization. Because actually with these chips, a lot of the code is initialization.
Starting point is 00:22:20 You can set up the hardware to work the way it's supposed to. And after that, you're just pushing data around. Right. and after that you're just pushing data around, right? So a lot of the modules are organized in a way that they have like power clock register is common for all the modules. And you'd be touching that in the initialization of every module, just changing one or two bits, right? But we can take lazy evaluation to extreme and just save the initialization in a compile time readable format and then do initialization all at once, doing optimizations across all of this information.
Starting point is 00:22:57 So we can take, you know, GPIO, pin multiplexing, power clock registers, stuff like that, and sort it to where it's all next to each other and then merge it together into one operation rather than a bunch of them. So from the programmer's perspective, they're writing like, I don't know, 10 or 15 statements saying, I need to set up all these different hardware flags. And you say, that's great. I'll merge that into basically two writes to two different registers and be done with it. Yeah, yeah. Where they're usually doing like load address, read, modify, write, because they don't want to affect the other bits that are in the register. They just want to affect their little bit field.
Starting point is 00:23:35 And so, you know, once we can prove that we're touching all the bit fields, then we can just write rather than read, modify, write. And we don't have to load the address 16 times, we just have to load it once, right? So the first one costs about the same as it usually would, and all the rest are free, right? Okay. Plus, we're also benefiting from load with offset more often, because we sorted things by address, right? And actually, that sorting was what got me into my work with the Bridge End Library, because I had originally written my own replacement for BoostMPL, because BoostMPL is just super slow, right? They're using linked lists rather than
Starting point is 00:24:18 battery-addict templates. They're using a lot of macro stuff that was built to squeeze every last drop out of a compiler that was made five, ten years ago. So, yeah, I made my own replacement for that. And then I found that BridgeEnd was actually faster at some stuff and way more famous than me, obviously. So I decided, why don't I backport everything I know into that? And, you know, we can collaborate because I hate it when like, there's 50 different projects, because there's 50 different people interested in the field, right? Why don't they all work together? So yeah, that when I joined BridgeAnd, we could sort maybe, you know, 100 things. And now it's like several thousand in less time. So yeah, we did a lot of work there.
Starting point is 00:25:07 You're saying and sorting at compile time, right? At compile time. Yeah. Like a list of a thousand types you can sort, you know, in a fraction of a second. It's it's it's I mean, some things literally are three orders of magnitude faster than they were on a five-year-old desktop with a five-year-old library and a five-year-old compiler, right? I mean, okay, maybe if you're comparing today's compiler compiling that old code, it might not be three orders of magnitude. But yeah, I don't think people realize how much faster template metaprogramming has gotten just over the last two years. So can you maybe give us a taste of how you're able to speed up the template metaprogramming
Starting point is 00:25:53 that much? Sure, sure. Well, variadic templates are, in most algorithms, on order of magnitude in and of themselves, right? We don't have to do linked lists of types. We can have a vector equivalent of types, right? Right. And then on top of that,
Starting point is 00:26:13 we can also do what's called fast tracking, where if we're iterating through a list of types, rather than taking one off, doing something with it, and then taking the next off, taking the next off. I mean, maybe we're looking for a type at a certain index, right? Well, the algorithm for that would be, you know, take the list, drop the first one, you know, take it out of the list, and then count how many you took out. And then the front of the list at that point is your index, right? That's, you know, functional programming, probably weird for non-functional programmers, but yeah, that's how you do it. But, you know, with fast track, you could say, well, I'm going to check if the
Starting point is 00:26:52 amount that I want to take off is, you know, say more than 16. And if it is, well, I'll just take 16 off, right? So we, you know, you can build up these, you know, usually power of two fast tracks where you're taking off a lot of types in one operation rather than one type each time. It was, I think, originally developed by the Bridgend authors. At least that's where it was popularized. And it was originally to get around max instantiation depth issues, right? Because the compiler will complain if you have a template that's got a nesting depth of more than, depending on the compiler, something around 256, right?
Starting point is 00:27:32 Right. So if you bite off more than one every iteration, every nesting call, then it's kind of like a trampoline if there are some functional programmers listening. But yeah, it allows you to do more instantiation depth. But it's also way faster. Another thing was there were some ambiguities
Starting point is 00:28:01 in the format of the boost MPL meta lambdas and that needed to be resolved using Svine, which is actually super slow. And so we changed the meta lambda format to where it was, you know, not contents dependent or not data dependent. And that sped it up quite a bit. That was actually mostly my contribution uh and very recently um we found another way uh or uh to to speed things up because you know the the problem with uh template algorithms is you're instantiating a type for every operation that you do, right? You know, I'm a, I'm some type and I derive from this, you know, the same type,
Starting point is 00:28:52 but without one element or something similar, right? So we're every, every step in, in, um, the instantiation of the templates gets remembered by the compiler. And another thing that slows it down is the way we make decisions, at least classically, is through template specialization. And that's pattern matching on a lot of types, right? And so that's potentially slow. And so what I came up with is that I named the metamonad pattern, which basically uses an alias, which is a member of a templated struct. Because with aliases, we don't actually create types, right? It's just an alias to that type.
Starting point is 00:29:40 So we don't create a type. Problem is we can't make decisions, right? Because we have no alias specialization. But if you set it up so that a constexpr function decides which struct is next in the chain, and that struct has a nested alias that actually does the operation that the constex of function is selected,
Starting point is 00:30:06 then you can write algorithms in a kind of a really weird way because you don't have like multiple parameters. You just have one list because it's an alias and you have no specialization. But you can get by with creating a whole lot less types. And because of that, you can make some know, make some algorithms, uh, another order of magnitude faster. Interesting. Have you by any chance written up an article or have any examples on this that maybe we could share in the link notes? Well, there's my, uh, my Metaporky blog. Um, I think I sent you the link. Uh, if you would, uh, add that the last couple of blog posts have been around about this.
Starting point is 00:30:46 I really should have actually written more. That's kind of a chronic problem with me. I always have way too much to do. The Quasi library as well is actually pretty poorly documented. We actually use it in our contract development stuff. And I have explained it to some people doing consulting work and there actually are some other people using it but yeah I think you know before before it's it's compatible with the masses we need to document it some more but internally
Starting point is 00:31:19 I've been adding a lot of people to the closet development team I think I tweeted a couple of days ago, we're probably the only embedded company where a hardcore template metaprogramming course is part of onboarding. Yeah, we've been trying to add people to the project because that's just register abstraction. We can take this much, much further. We can take this much, much further. We can abstract different peripherals in flexible ways using
Starting point is 00:31:52 policy-based class design. We can use some of the knowledge that we have about creative memory management to speed things up and save RAM. One of the big uh the big uh differences between our field and say classic uh you know desktop apps is that we are so ram constrained uh yeah i mean classically people think of okay this object doesn't live forever plus globals are evil. And on the other hand, it's not, you know, its lifetime isn't connected to the stack. So we'll put it on the heap, right? But if you have to prove that there is no peep fragmentation scenario where your device
Starting point is 00:32:39 will crash, then you have to add a, you know, a heap fragmentation penalty is what we call it of often, you know, several X on top of what your, what your usual heap use would be. So if you can connect, you know, if you can, if you can organize object lifetimes in other ways, like with state local storage, for example, or, you know, making them protected, mockable, but still essentially globals, right? If you make them like static members of template functions, well, I can, you know, swap out the template function by using specialization, so it's mockable. And okay, it is a global, but not everyone can access it because you could make private, right? So looking at other object lifetimes in order to get rid of the heap is usually a huge RAM
Starting point is 00:33:37 savings. And it makes you a lot more deterministic. I mean, the value of deterministic behavior, again, is something that's very misunderstood outside of usually, you know, they don't like theoretically prove anything. And there are usually little, you know, hardware in the loop tests, integration tests, whatever. If it works once, then okay, yay, right? And but if you have non-deterministic behavior, then there's probably a chance that it won't work some of the time. And so, yeah, a lot of, a lot of our, uh, um, a lot of what, uh, um, of our intellectual property back in the beginning of, uh, auto intern, the company I run, um, was knowing the timing requirements for,
Starting point is 00:34:41 uh, control units in cars because they're not deterministic, right? If you know that they have a window between, I don't know, 1.6 milliseconds and two milliseconds, where they will guarantee to answer you, and then from zero to five, you probably will get an answer, then it's actually quite hard to figure out that you only have that small window, it will always answer, right? and as far as i've heard from other people like kuka robots and even modern stuff i mean the auto industry is pretty pretty uh uh pretty old in the way they do things but you even like industrial robots have the same problem where uh it's poorly documented and poorly known what their timing requirements are and a lot of
Starting point is 00:35:23 that comes from schedulers in the heap because those are the only two real non-deterministic things, right? I mean, you have in any given point in your system explicit state, which is, okay, you know, what state am I in? Am I initialized? Whatever. And you also have like implicit state. You know, how is my heap fragmented?
Starting point is 00:35:44 What's the phase shift of my scheduler switching through different tasks? And, you know, if you put those two together, if you were to try and exhaustively test all scenarios, the exhaustive test would state, you know, not use a schedule, use some run to completion kernel, use, uh, other memory management, not the heap, then, uh, you have, uh, um, yeah, you have, you have many, many, many, many, uh, scenarios that suddenly cannot happen anymore, right? Like the, you know, the, the possibility of, uh, control paths is decreased by several orders of magnitude. And therefore, race conditions, timing dependent stuff either becomes very often or very, very seldom, both of which are good, right? I mean, if the bug is so seldom that no one's ever going to see it, that's good. And if it's quite often, then you're going to see it. And so your customer won't, right?
Starting point is 00:36:46 Right. So I'm curious what lessons you think maybe regular application developers could learn from this. I mean, it seems like doing more work at compile time is better for everyone. Yeah. Well, I think we're kind of at an interesting state where, I mean, you know, Alex Andreescu taught us how to do policy-based class design a long time ago. The problem is you have to write really ugly types, right? In, you know, in any field in C++, I think we have the ability, again, to use more policy-based class design because we can use auto or we can use concept-based polymorphism to wrap whatever ungodly type we created in a wrapper that people can talk about, right? And, you know, we can create factory functions that build these,
Starting point is 00:37:34 you know, obviously templated factory functions, but the user doesn't have to know, that build these policy-based classes. And, you know, we can add a lot of flexibility without it having to be runtime flexibility. I mean, like a simple example, if you use standard function, right? If you give it a small function object,
Starting point is 00:37:56 it will put that on the stack, right? It has like a small object optimization. But I can't say how big that is, right? I mean, usually it'd be like, if my object is smaller than three pointers then it'll go on the stack as far as i know that's like the clang and gcc but that might be outdated i haven't worked in that field for a while but i mean you you could be maybe for for multi-plating reasons you don't want to use the heap right because the heap is again you know at least in most systems just some global instance with a lock around it
Starting point is 00:38:24 right yeah and so you don't want to do that so so you maybe you have function objects that are at least in most systems, just some global instance with a lock around it, right? Yeah. And so you don't want to do that. So maybe you have function objects that are the size of four pointers and want to put them on the stack. Well, you can't do that. You'd have to go into the library and change how the standard library is implemented. We could theoretically make an extra parameter that you could put into your standard functions uh that would
Starting point is 00:38:46 decide what that size is and give have it defaulted so nobody ever plays with it doesn't know that it's there right um i mean it's it's kind of terrible that the classic examples of policy based class design is allocators because allocators are just written in the wrong way. It kind of gives the whole idea a bad name, but that's, you know, that was, that predates, uh, Alagazandrescu, um, at least talking about it. Uh, but yeah, that's one of the early policy-based class design, uh, implementations. I'd like to interrupt the discussion for just a moment to bring you a word from our sponsors.
Starting point is 00:39:22 ReSharper C++ makes Visual Studio a much better IDE for C++ developers. It provides on-the-fly code analysis, quick fixes, powerful search and navigation, smart code completion, automated refactorings, a wide variety of code generation options, and a host of other features to help increase your everyday productivity. Code refactorings for C++ help change your code safely,
Starting point is 00:39:44 while context actions let you switch between alternative syntax constructs and serve as shortcuts to code generation actions. With ReSharper C++, you can instantly jump to any file, type, or type member in solution. You can search for usages of any code and get a clear view of all found usages with grouping and preview options. Visit jb.gg slash cppcast-rcpp to learn more and download your free 30-day evaluation. Bringing it back to embedded development and C++ a little bit,
Starting point is 00:40:18 I'm curious, as someone in the industry, what do you see as the trend? Do you see a lot of C++ being used? Uh, no. Um, I mean, I, I, I heard, uh, I, you know, I listened to the last, uh, um, cast with, uh, uh, um, Dan Sachs and, you know, he was, he was saying, yeah, well, it's pretty easy to migrate to C++. And there are a lot of, you know, myths about the, you know, performance myths out there. And yeah, he is right to a certain extent. It is quite easy to just use a C++ compiler and compile your C code. But those performance myths, I mean, there are
Starting point is 00:41:00 performance traps out there, right? Like if you turn on exceptions, for example, then there's the so-called emergency buffer of usually like 40 kilobytes of RAM or something where the exception objects go. Like if you throw one out of memory, that object that you're throwing has to go somewhere. And if you're out of memory, it can't go on the heap, right? So there's the so-called emergency buffer. And the compilers are getting better about taking it out
Starting point is 00:41:30 if no one throws exceptions anywhere. But as soon as you use something like standard vector, well, it could potentially throw. And so the compiler is usually not smart enough to say, well, in none of your scenarios are you indexing out of range or something like that, right? So, I mean, if you got a chip with 6K of RAM and you need a 40K emergency buffer, well, there's no way that's going to work, right? I mean, even if you have a chip with 64K of RAM,
Starting point is 00:41:58 well, you blew more than half your RAM just on this emergency buffer that nobody's using. So, I mean, there are performance traps. There are workarounds to all of them, essentially. But, yeah, I mean, I do some consulting work, and I often come into companies where there's the embedded guys and there's the, you know, application developers. Sorry, that was a German word. Application developers. Sorry, that was a German word. Application developers. And there's kind of this feeling by the application developers, those guys should just use C++.
Starting point is 00:42:33 I've heard it can be done. And then we can use, like, we can share code, right? And it's not quite that easy because, okay, sharing code. Well, the application developer, even if they do, I mean, you can turn off interrupts, and then it's just undefined behavior if you ever throw one. And then you can be like really meticulous about never doing anything that would throw one. But still, if you use like a standard vector for say, can packets, right? Can packet is, you know, zero to eight data bytes payload, right? Okay. If I were to do a memory pool of CAN packets, then I would probably add, like, you know, an index into that pool as in which packet I am and probably add, you know, that as sort of intrusive linked list pointer to the next packet in a queue, say, right? If I want a queue of canned packets.
Starting point is 00:43:25 And then I'd have another byte or maybe some bits of another byte say, okay, how many bytes are there in my canned pack? So I'm basically adding, you know, two bytes to make it 10. And then I can do intrus you know, the equivalent in, say, a standard deck of vectors, right, I've like doubled or maybe even tripled my RAM overhead because a vector is always three pointers, three pointers are always 32 bits, and so on and so forth. So, yeah, I mean, there are, you can't just use standard library stuff in these really small chips. You can use a lot of the concepts. I mean, I'm actually doing a talk at Meeting C++ in a couple of weeks or two weeks now. I have to finish. Anyway, on Ranges version 3, which sadly didn't get into the standard, but that's actually something we can use
Starting point is 00:44:26 because it's just a concept essentially, right? It has no dictated implementation, whereas the way vector is written, it's kind of a dictated implementation. Yeah, so most of the standard library is out, which means it is a different C++ than you're used to in desktop development. At the same time, it is a powerful toolbox. So basically, what we're trying to do with Quasir is to make a standard library or a standard framework or at least a good framework for embedded people using
Starting point is 00:45:07 the modern C++ tools. So you said a lot of the standard libraries out. I guess maybe to clarify, or maybe my opinion would be you're saying a lot of the standard containers, but there's no reason why you couldn't still use things like the algorithms. Is that correct uh no you you could use uh uh the algorithms yes okay um i mean the way it's done now i mean even like okay two iterators right and they have to be the same type so i have to have some state deciding which ones begin and end right right uh it's still not quite as efficient as it could be but i mean mean, we may be, you know, nitpicking there, but, but we, we will be able to do that better with ranges, right? If I have, if I, if I want to model my serial port as an output range, um, that output range object doesn't even have to have any state, right? Uh, you know, if you write to it, then, uh, it goes into the FIFO buffer hardware register, which is not part of the object,
Starting point is 00:46:06 right? And if I want to know if it's at end, well, I check the hardware flag. I can't do that with iterators because, you know, first of all, which one's which, right? Which is the begin, which is the end. If they're the same type, you have to have at least some state. Right. Okay. Okay.
Starting point is 00:46:23 Jason, do you have any other questions today um well i am just moderately curious you said you do uh consulting work yeah have you gotten and and you are clearly are using advanced c++ techniques yeah yeah do you ever get pushback from the clients when you go in and be like well i'm going to show you how to use all these template metaprogramming and you need to update your compiler to the latest gcc like do they care um yeah well i actually kind of anticipate that i don't i don't go usually go in and teach them uh the the newest stuff because uh i mean if they don't have a developer in-house that uh you know understands this stuff i'm not sure that quasier's to the the point where you will never get an error.
Starting point is 00:47:08 I mean, it will be at some point, but especially other techniques that we use on the contract development and our products that we do ourselves. As soon as they don't have somebody that understands the library, you can only hand them a finished library, like a tried and true library. And so usually what I do is I give them probably some of the same advice that Dan Sachs would give them. Okay, here's how you would abstract hardware registers as local variables in a class that are private and then you can do modifying functions and it's not quite as efficient and it's not quite as uh statically checked uh but it's definitely still better than than c right i mean even you know function overloading right i mean as a c++ programmer you don't realize like how bad it is like Like, yeah, functional or, or, or being able to make your own types. Right. I mean, okay. I have a packet ID. I have a protocol ID. I want
Starting point is 00:48:11 to not be able to switch them around accidentally. Right. It, you know, if I have a function that takes six ins, then I mean, there's nothing intuitive about that. I have to read two pages of documentation before I can give that thing data. right? But if I have a function that takes, you know, a packet ID, a protocol ID, I don't know, a length, a XY coordinates, whatever, then I know where which parameter goes where, and I know what to call it with, right? Without, I mean, the documentation's in the code, and because it's in the code, the compiler can actually read it, right? I mean, we tend to overlook, like, with all the hype around Industry 4.0 and Internet of Things and all this stuff that's a Twitter account called the Internet of Shit, which is – will give you a very, very good impression of where industry is on this kind of thing, right? I mean the need is there and the potential is there. Like you could make things way more efficient.
Starting point is 00:49:18 You could make things way better, way nicer. And a lot of this is in industry, like, you know, factories. If I walk down the street into the next factory, there's probably no technology in there that was invented after my birth. And I have some gray beard hair, right? I mean, this is, yeah. And, but the reason is, I mean, you know, my Windows 95 crashed all the time, but then somebody came up with unit testing and my Windows XP didn't crash that often, right? There have been advances and many, many, many advances since, you know, the 80s when most of the embedded coding style, I mean, where it comes from. Like if you look in current embedded code,
Starting point is 00:50:05 you'll usually see the variable before the for loop, right? Like compilers have been able to deal with that since before I was born. But that's still kind of the way people code. It's kind of the sleeping beauty syndrome or whatever you call it, right? And that means either the systems are built on just this big pyramid of, you know,
Starting point is 00:50:28 guess and pray type decisions, where somebody said, Oh, well, I tested it, and it worked. Well, are you sure it will always work? Well, I'm going to figure that out, right? Or, or you have things like, you know, autopilot, you know, flight control software, cars, ABS systems, or whatever. And I don't think people realize how many man hours go into really simple things. I mean, I think, for example, Siemens is one of the biggest employers of programmers in the world. And oh, what do they do for software? Well, they have 100
Starting point is 00:51:05 guys working on this thing that turns a switch on and off very, very reliably, right? And so when I hear people talk about, you know, these Internet of Things, Internet of Industry 4.0, and the like, either we're going to see, you know, dynamic programming language, like, you know, my light fixture will run a Java stack and probably use more energy than my light. Um, or we're going to see things that break all the time. Uh, or we're going to have to, you know, increase the amount of programmers that we have a hundred fold, which is obviously not going to happen. So, you know, the only, the only other way out is to increase, you know, improve the way we write code, right? Right. Write things in a way that we have way more program productivity, that we have, you know,
Starting point is 00:51:58 less potential for errors. And this has happened in all the other fields, right? It's just, it hasn't really in embedded because things need to be super flexible to be viable in the embedded field and, you know, less than in other fields. And we haven't really, I mean, before C++11, the stuff that we're doing now would be super ugly. It wouldn't look like as if it were C, right? It would be full of angle brackets and stuff and nobody would use it. But, you know, as a C++11, we have the potential of actually doing this.
Starting point is 00:52:32 And I mean, I'm not sure it's just C++11. With Rust, you could do it pretty well as well. But yeah, I mean, I think also that, you know, the payoff, the potential payoff is huge, right? I mean, if I look at, I don't know, from a government standpoint, right, from an environmentalist standpoint, I mentioned earlier I grew up among hippies, right? If they want to save, you know, say X amount of energy, then they'll go insulate some government building for, you know, $6 million, right? And then if you look, okay okay how much energy did they save well that's kind of equivalent to the standby current of all the microwaves in bohol where i live right
Starting point is 00:53:12 uh how much would it cost to make those microwaves not use that standby current um you know probably in parts something like 50 grand i mean the parts don't cost anything really, but the development overhead would be much higher. You'd need smart, you need to add some amount of intelligence to that microwave power supply. And that's prohibitively expensive because of the way embedded systems are developed. But, you know, with that $6 million of the government spend insulating their building, we could easily develop a library that would not only make it so that it's no longer prohibitively expensive to add intelligence to the microwave power supply but to the other several billion embedded devices. I mean, you could get, you know, many organors of magnitude more bang for your buck than things that are somehow understandable, like insulating buildings. And, you know, from the economic standpoint, insulating the building is probably a loss, right? Because the cost of insulation is probably more than the cost of electricity that they're saving, right? But if you were to lower the cost of developing embedded systems by orders of magnitude,
Starting point is 00:54:32 that would create a huge amount of economic growth. I mean, I don't really understand as a whole why environmentalists, philanthropists, or the government don't invest money in native languages. Because, you know, if I can, if I can stop, if I can move code to native code, just as a general way of explaining it, right? If, if there's less servers out there that run Java stacks and rest light fixtures out there that run Java stacks, it's not really that expensive. I mean, look at the budget of the standard committee. It's peanuts, right?
Starting point is 00:55:11 Look at, you know, the standard library implementations. I mean, that's like a couple of guys, right? And, you know, because of that, there's a lot less Java on servers, right? And people, or in the embedded field, like people say, okay, well, that's just, you know, three watts in standby. That's not really a problem, right? That's like three, four bucks a year on electricity. But there's a lot of microwaves out there, and it'd be pretty easy to make that not happen, right? Yeah.
Starting point is 00:55:49 It'd be way, way, way more than a lot of these, you know, government pet projects. Yeah, where they, I mean, pander to some, I don't know, corn farmers or something. And, or, you know, here in Germany, the biofuel subsidies are insane. Whereas, you know, most, most, most environmentalists will say, well, you know, on balance, it's
Starting point is 00:56:15 probably zero sum effect on the, on the environment, because, you know, not only do they make biofuels out of corn grown in Germany, they also make biofuels out of oil palms in, you know not only do they make biofuels out of corn grown in germany they also make biofuels out of oil palms and you know some other country where they cut down rainforest to plant the oil palms right but with software it's like it doesn't cost anything but man hours in the right place right nobody wants to build infrastructure i mean nobody wants to build infrastructure in other fields too, right? Like, you know, telecom, telecommunications, the government has to go in and reorganize things every decade or so, so that somebody actually updates things, right? But, but people understand
Starting point is 00:56:56 that that's important. People understand that like, I'm not going to build my road and then you build your road, right? We cooperate on things, but not in software usually, and not in interfacing between things. Yeah. Did I mention I grew up among hippies? It went off in the weeds a little bit there. It definitely seems like, I think the answer to the question is there aren't enough politicians who understand software at all. Yes, yes, yes, very much.
Starting point is 00:57:22 I mean, it's not only politicians. Like, even it's many universities. They're, like, they have a software department, but there's still nobody that really understands software. I mean, there are obviously, you know, it's a mixed bag. There are some that are very good. But I think generally people in power don't really understand software because most people understand software, you know,
Starting point is 00:57:43 want to be left alone, program stuff, and you'll want to be involved in some ego battles to get some political position but yeah we're definitely off in the weeds at this point well where can um people find you online odin and uh get more information about Kvasir? Kvasir.io simple enough if they want current stuff I try and feed Twitter now and then
Starting point is 00:58:14 and what I do do is try and talk at user groups conferences and whatever. That actually seems to be the format that I like to present stuff the best in.
Starting point is 00:58:32 Some of them are recorded and can be found online over the next couple of weeks. Actually, a lot more of those recordings will be generated. It's up to the organizers when they actually get onto YouTube. If you're interested, It's up to the organizers when they actually get onto YouTube. But right.
Starting point is 00:58:46 Yeah. Or I mean, if you're interested, I mean, I'm very approachable. Just yell at me on Twitter or something like that. Yeah. OK. OK. Thank you so much for your time today. Yeah, it was fun.
Starting point is 00:59:01 Thanks for joining us. Yeah. Thanks so much for listening in as we chat about C++++ I'd love to hear what you think of the podcast please let me know if we're discussing the stuff you're interested in or if you have a suggestion for a topic I'd love to hear about that too you can email all your thoughts to feedback at cppcast.com I'd also appreciate if you like CppCast on Facebook and follow CppCast on Twitter
Starting point is 00:59:22 you can also follow me at Rob W. Irving and Jason at Leftkiss on Twitter. And of course, you can find all that info and the show notes on the podcast website at cppcast.com. Theme music for this episode is provided by podcastthemes.com.

There aren't comments yet for this episode. Click on any sentence in the transcript to leave a comment.