My name is Celine and I'm the delivery director at Just After Midnight was created five years ago by our founders, Chris Croucher, who is also another speaker here today and some booth based in the UK. I myself, I'm in Melbourne here in Australia. Along with myself, Chris and Sam, we're all part of a fast growing international digital agency called Reading Room as part of our previous careers and it was before it was sold to EY. On that journey at Reading Room, we were increasingly asked to build more and more critical business websites and apps for clients in corporate and government, many with Drupal at their heart and some not. One question that we found in different ways kept rising, which we and our clients find hard to answer. And the question, what are you going to do just after midnight when my website is down on fire or something is going wrong and being attacked? And invariably, we like many clients, teams and digital agencies without significant out of hours operations, struggle to answer the question. So that's where the idea of just after midnight was born. Today we are the go to support people for brands, government, clients, the agencies and software managed cloud teams. In building an amazing 24-7 team and support product offering across four continents. So we are APAC, Australia, Singapore, US and the UK. We've also built an incredibly strong managed cloud and DevOps teams specializing in AWS and Azure. And we are the 24-7. Some of our more interesting customers include Dyson and making sure that people around the world can still buy a very expensive hair stretchers and vacuum cleaners. Also another one recently is the Department of Home Affairs, making sure that the government comes, people can get their content around changes to visas, arrangement during the COVID pandemic and all that stuff. Volvo is another one supporting their digital assets throughout their round clock US Super Bowl campaign and many more. The Drupal community is one of the most engaged and open technology communities we know of. So we are really proud to support our friends in the Drupal community as all of you gather for Drupal South. And so it's a pleasure for me to now introduce you to Ricky. Ricky is a front-end developer at Prevots Next. She has a passion for accessibility and over 10 years experienced developing Drupal websites. She loves expanding her PHP knowledge and find her design background has been a great asset, translating a design into a workable interface. So on that note, I'll leave you with Ricky and all her experience. Ricky? Hi, everyone. So yeah, hello, Drupal South from my living room in Melbourne. I hope everyone is well in their various states of lockdown. This is a deep dive into the best tools and methods for optimising your Drupal things. Probably don't need to do an intro slide, I've just been introduced, but you can tweet me at Ricky or chat to me in the Drupal Slack. I guess, yeah, as mentioned, I've been in the industry for around 13 years now. And front-end development has certainly evolved a lot. And thankfully, the browsers have too. This talk is mostly relevant for this kind of setup. Components are isolated and organised. You're utilising core asset library system. Component assets are only loaded on pages which actually have those components. So for example, you have a library of global stuff loaded via the themes info file and separate libraries for component assets. Which are only loaded when the component is used on a page. For example, attached in a twig template or a render array. So no other page gets CSS or JavaScript that it doesn't need. But what about different browsers and their varying needs? Can we optimise this even further? IE 11 is the last of the ancient browsers. End of life is only 10 months time. But I think about how much of your HTML, CSS and JavaScript gets written just for it. Do you really want to keep writing code this way? Do you still need to support it? This is a serious question to ask your clients or stakeholders. Can that browser just get basic content without features or fancy layouts? And is it really worth the performance hit to the majority to have such updated code? If you truly do need to support it, then make a clear plan for when that changes. If it's a huge refactor job, maybe get a head start. You don't want that legacy code sitting around for another five years. Either way, you can probably stop writing code for IE 11 right now. Write one code instead. Code that the majority of browsers already understand. It's faster and more interesting to write. Or even better, write tomorrow's code today. Learn what's new and plan in CSS and JavaScript spec. Be ready for the next wave of improvements. Keep your skills at the cutting edge. Then use tooling to support the various browsers. Tooling isn't new. There's always several options for doing something which can be overwhelming. Do you spend too long just getting them all running? Are they helping or hindering? And when was the last time you reviewed them? SaaS is still a hugely popular tool. It was fantastic when it first came out. But it's a very big and complex tool that hasn't evolved much. It's also quite dangerous. If you're not really careful with your mixings and extends, you can end up with huge output. Two megabytes of CSS is never okay, even on a large website. But I've seen it happen too often with misuse of SaaS. Real CSS is the future. Yes, CSS is way older than SaaS, but it's native to browsers. It's not being replaced anytime soon, even if you write it inside JavaScript. CSS specification has evolved a lot. It now fills a lot of the gaps that made SaaS a necessity. Like custom properties, basically CSS variables, but better. And CSS grids, instead of all those grid row and column mixings from SaaSworld. You don't need any tooling to write and serve pure CSS. So no nasty surprises with output. This is what CSS custom properties look like. You can use all of this in modern browsers today. They can be responsive. So anywhere this property is used, automatically changes at this break point. You can override them for a selector. It's called scoping. Notice I don't need to rewrite the font size rule. Just update the custom property. And this is what a fully responsive CSS grid could look like. It's pretty small, huh? It's just one example. CSS grids are incredibly flexible. Again, native to modern browsers today. There's no margins, especially no negative margins, needed for it or its children. It repeats so a new row is made when needed. And it's content aware. The break point is a minimum of 20 character units. So a column will only shrink that far before folding. The columns are always equal width. If you do need a grid system, for IE, you can do a flexbox fallback and use at supports to replace it for modern browsers. This is the progressive enhancement approach. Keeping your fallbacks or legacy code separate helps when it comes time to pull it out. You don't need to refactor your modern code. So those last few examples can be used right now. But tools like Post-CSS allow us to use future CSS. Code that is likely to be implemented in browsers just hasn't been done widely enough yet. It also helps us support older browsers like IE11. As well as some workflow improvements like Auto Prefixer, Imports, and Minifying. It does a lot less than SAS, so it's faster and much easier to set up. These are examples of future CSS spec. You can use nesting, custom properties, custom media queries, custom selectives. And then just set up the Post-CSS plugin, preset ENV. In your Post-CSS config and tell it what you want to support or not support. It refers to your browser list config, so if you need IE11, list it there. And when IE11 dies, just remove that from the browser from the list. No refactoring. The output is much closer to the input compared to SAS. The nesting resolves, the media query resolves, the custom properties get fallback values. Or you can disable custom properties and just have the fallback value in the output instead. But please keep it simple. You can go crazy with Post-CSS plugins and recreate everything that SAS does. Some good questions to ask when adding a new plugin are, is this supporting CSS that browsers are going to implement? Is this essential to my workflow? And can a utility class do what my extend or mixins did? JQuery is also the past. Another fantastic tool that let us write much simpler code. But it's old and can be a bit of a bubble. It's very easy to only write JQuery and not have any understanding of the underlying code, basic JavaScript. That's knowledge that doesn't really transfer to the decoupled JavaScript frameworks. There's also a performance hit in needing a third-party library to load. Vanilla JavaScript is the future. Just like CSS, plain old JavaScript or Vanilla.js is old. But it's native to the browser. It's the foundation of every decoupled framework and it's much more performant than JQuery. Also, the JavaScript spec has evolved to do a lot of what JQuery did. There's no third-party library needed and you don't actually need any tooling for it. This is how easy it is to iterate over a group of elements and some other JQuery equivalents. We have click events, closest, toggling classes, append, prepend, remove. All much simpler to write than it used to be. This is a JavaScript class with customizable options exported as an ES module. This is an example of importing that ES module and then extending it. This is great for building upon existing functionality. Yes, ES modules are supported today in modern browsers. You don't need to bundle the imported module into the file for a modern browser to use it. And if we are supporting older browsers, we can exclude these ES module files from them. Using the type equals module attribute. We can send ES module files only to browsers who can read them. IE will not execute files with this attribute. Then we can use no module attribute to send some files only to older browsers. For example, things like polyfills, which modern browsers don't need. Modern browsers will not even try to load this file. If you're not supporting IE, just give everything type equals module and IE will be JavaScript free. Again, ES modules can be used right now but tools like Babel allow us to use future spec, just like Post-CSS did. New JavaScript syntax that might not be widely supported just yet. Combine Babel with your rollup or webpack setup for even more performance and workflow optimizations, like node resolving the imports, tree shaking, code splitting and minifying. By code splitting, I'm talking mostly about entry point code splitting, where a Drupal steam JavaScript is often broken up into individual components, so each component's JavaScript file is an entry point. But there might be some shared dependencies across components, so to prevent duplication, we can use code splitting. Say we have three components, all importing ES modules. Two components import the same one, a shared dependency. We still want a JavaScript file for each component, so we can attach it when we need it, but we don't want to have the same imported ES module bundled into both components. If they both get added to the same page, that creates duplication. So we can use our tooling to build shared chunks instead. By adding Babel into our bundler, we can generate two versions for each component. One file like the previous slide, importing any shared chunks as ES modules, which we give type equals module. Then a second file that bundles in any imported modules, and is transpiled for IE 11, which we give the no module attribute, like in the polyfill example. IE gets bigger files, so a performance hit, but our components still work. More importantly, modern browsers get the smallest possible file. This is our Babel config. We create two environments, one for module and one for no module. We use CoreJS to include polyfills for us, based on our usage. And just like post-CSS, the preset ENV package allows us to use our browser list config. So it's easy to pull out IE 11 support. The targets option, by default, will defer to your browser list. But for our module environment, we're saying all browsers that support ES modules. Rollup has supported this for a while. Parcel has added it to version two, but I haven't tested it yet. And Webpack is working on adding support for the ESM output format. So the following config is for rollup. First, we create a glob array of all our components as entry points. Then we set up any plugins needed. We pass in an environment variable to defer to our Babel config. Then we set up config needed for the module output. The input is our glob array. Rollup knows what ES modules each file is importing and exporting, which is called tree shaking. Our format is ESM, so it knows we want to use our ES modules in the output instead of bundling them. Then we tell it where to put the chunk files, our shared ES modules. We learned our plugins by calling the base plugin function, passing in the module environment for Babel. This is our config for the no module output, which is a function that accepts a single file. The format is an ife, which ie11 understands. We pass no module as the plugin environment for Babel. And finally, we build a complete config array with a separate no module config entry for each file in the glob. There's a link at the end of these slides for a repo with this set up in it, so you can refer to that. So for each entry point, we get our two versions, which we can send to the relevant browser. No older browser gets JavaScript that they can't understand. And no modern browser gets JavaScript that they don't need. Another form of code splitting is called dynamic imports.  Instead of importing the polyfill at the top of the file, we're first checking if the browser needs the polyfill before importing it. So if a browser has native support for the HTML5 dialogue element in this example, it won't load this polyfill. But Firefox, for example, will load it. The import returns a promise which we can then use. However, this doesn't work with the ife format we're using for our no module output. I haven't tested enough to know what the best format is, but I probably wouldn't worry about IE11 if you want to use this. Yes, there are ways in varying levels you can support IE still. But surely that effort could be better placed elsewhere. Some users have no JavaScript turned on. Why not just treat IE11 like them? If the content is accessible, isn't that enough? You can skip the no module stuff and the grid fallbacks. Free yourself from IE. So to sum up, writing modern code is fun. You'll hopefully learn something new. Performance will greatly improve for the majority of the site's users. If you are supporting IE11, it's easier to undo. And this reflects what's happening in Drupal Core, so it ensures you're in a position to contribute to its front-end. It's a return to the basics with a look to the future. So those code examples are in this top link, this repository. I've blogged about this before, various levels on the previous next blog. There's Drupal issue queues for removing jQuery from Core. And there's tons of resources online about writing one front-end code. And that's me. I ran a little bit quick. Thanks. Thank you very much, Rikki. That was actually very, very interesting. From my perspective anyway, I used to be a front-end developer many, many, many years ago, so yeah, it's gone a long way. It has, yeah. Definitely completely outdated now. From my time. Does anyone have any questions at all? Please put it into either the Q&A or the discussion forum. If there is no questions or anything like that, there is, you know, we can finish a little bit earlier, just reminding you guys all that the lightning talks and round table session starts at 2 p.m., so we're a little bit ahead of time. So, yeah, if you guys have any questions or anything else, if not, then thank you again, Rikki, for this very informational session. Thanks. So I'll give you guys a couple of minutes. If not, then... Okay, correct. Awesome. There are a couple of questions. The first one, how do you decide what browsers to drop support for? Statistics for what are supported seems spotty. Yeah, that's a great question. So, obviously, there's the sort of global statistics of what what average usage is, but we find it more valuable to just get our clients to check their Google Analytics and see how much that browser is being used by their customers. And that usually determines whether it's worth the effort to put in to support it. Great. Another question we have here is do you have any tips for converting away from SAS? I mean, it's a process, especially if you're refactoring SAS files on an existing theme, I'd probably recommend just on your next new project starting with Post-CSS and not including any of your SAS stuff. But, yeah, it's just sort of work your way through the files and replace things and, yeah, convert to utility classes where you've used to extends heavily and things like that. Excellent. Great. Hopefully that answers your questions. Anything else that you'd like Rikki to help you with? Thanks, Drew. I don't think there's any others coming. Well, it looks like we're all going to go and start using Post-CSS and not worry too much about SAS soon. Great. Well, thank you very much again, Rikki, and thank you everyone who joined this discussion. I hope this was as valuable as it was for me, actually. And, yes, we will share if you can put, I'll put again the last slide with all of the URLs if anyone wants to copy it. And I'll tweet a link to those slides as well. Awesome. Thank you very much. Excellent. Well, thank you very much, everyone. Thanks, guys. Yep, and Jess also wants to remind everyone that the live session starts at 2pm. So you have about, I think, 18 minutes. So, yeah. Thank you.


Hi friends welcome back to my channel and a special welcome if you're new here. My name is Jen I'm a certified weight loss and nutrition coach and I'm on WW personal points. Happy Saturday It is Saturday, so it is grocery haul day. I am still in the middle of my use it up challenge I have done so well shopping my pantry fridge and freezer that I have no doubt that a lot of the food that we have on hand Will be used up before we move in just one short week That's crazy to even think about so this week. I did the same thing I built my meals around what I had in my pantry my fridge and my freezer I did have to pick up a few groceries to kind of fill in the gaps So I'm going to share with you first my grocery haul and then what meals I'm putting together for the week So if you're excited give this video a big huge thumbs up Subscribe if you're not because I upload a grocery haul every single Saturday and I do upload five days a week So make sure your bell is on so you never miss a single upload Check out that description box down below for nutrition coaching I offer personalized to you macros and calories as well as one-on-one coaching if you would like to chat with me directly Links discounts to my favorite things are also down in that description box Lastly come on over join us on facebook. We would love to have you So let's jump into my grocery haul and my meals for the week So here is my grocery haul We have another pretty small haul because I shared last week that because we're moving Here in about a week. We are shopping our pantry fridge and freezer So i'm going to show you what I picked up for groceries and then i'll share with you all of the meals that i'm planning for the week So I always pick up a case of diet coke for troi We did get some dog treats just because we don't have a whole lot left and these we plan on taking with us On our three-day road trip to arizona. So these are the nudges Jerky bites made with real chicken flour tortillas for troi. He asked for these He's been trying to use that meat and cheese and making quesadillas I also needed to pick up some milk for him and some prune juice I did grab one more frozen pizza This has been really helpful if i'm not home or if i don't make something for dinner that he likes or Nothing for dinner at all and i'm just eating leftovers. He can warm himself up a pizza And then I did grab a pack of the bob oven sour cream and chives mashed potatoes as a side dish for a dinner this week So that's everything that I picked up for groceries, but let me show you what i'm putting together for dinner So for dinner tonight I'm using the butterfly crunchy shrimp that I picked up at our local butcher with my gift card I shared in last week's grocery haul that my mom gave us a gift card for our local butcher that we had to use up Before we move and so I did pick up some pre-made things so far. Everything's been really really good I'm going to throw these butterfly shrimps in my air fryer And then we're going to eat the trader joe's pasta This is just basically marinara sauce and penne pasta And then i'm going to steam up some frozen broccoli. So that is dinner for tonight Here's another dinner for the week starting with another one of those nice pre-made options at the local butcher This is parmesan with marinara chicken. This looks so delicious last time I just threw these in the oven and the pesto one that we had last week was amazing So this week we're going to eat up the marinara And then i'm going to use those sour cream and chive mashed potatoes And then i'll steam up a bag of california style mixed vegetables So that is dinner number two for the week. We're also going to have a taco night This is going to use up quite a few things. So for my taco shell I'm actually going to use the folio cheese wraps I'm out of low carb tortillas and I don't want to buy another pack and these are really good It just takes the place of adding any cheese to the taco or the burrito Either however you want to look at it either a taco or burrito night And then the tortillas that I picked up will come in handy and then I have this little good foods avocado mash these little containers I got these from imperfect foods. We definitely need to use these up So we'll add some guacamole and I have a can of the trader joe's fat-free refried beans We can use these some 96 percent extra lean ground beef Light sour cream will definitely use up that and then we have about a half of a bag Of the sargento for state cheddar cheese blend that we'll use as well So another dinner is taco night and our final dinner for the week is going to be grilled cheese and soup Again, this is a great way to use up cans of soup in my pantry bread and cheese I have a can of progresso creamy tomato with basil reduced sodium soup This will probably be for troi and then I have my amy's organic lentil soup that I'd like to eat up as well And I love love love lentil soup. So this will be mine I have about three quarters of a loaf of bread.  So I'll use this for my sandwiches This for troi sandwiches. I have some light hibardi cheese from trader joe's This will be the cheese that I use and then we have some sliced sharp cheddar for troi sandwiches So grilled cheese and soup night. Thank you for joining me on another weekly w w budget Shot my stash use it up grocery haul if you enjoyed it Don't forget to give it a big thumbs up It really helps out my channel and of course subscribe ring your bell So you never miss a grocery haul or any other video in general. Remember I do upload five days a week So make sure your bell notification is turned on check out that description box for nutrition coaching Links discounts to my favorite things and lastly, don't forget come and over join us on facebook We'd love to have you happy saturday friends. Happy weekend, and I'll see you in tomorrow's video. Bye You


You may know that as a Bellevue College student, you have access to many resources for your research through the Bellevue College online collections. But did you know that you also have access to online resources through King County Library System? That's right. Access to the online resources of King County Library System is free to all currently enrolled Bellevue College students. What types of online resources are there? There are e-books, databases with sources for your research, newspapers and magazines for research, current magazines for casual reading, audiobooks, streaming movies and documentaries, read-along and video storybooks to enjoy with children, and more. You can explore the databases available to you by going to the KCLS homepage at kcls.org and on the top banner, clicking on Online Library. The online access does not mean that you are able to check out physical library materials from a KCLS branch with a student account, however. If you would like to be able to check out physical library materials, you can sign up for a library card online or you can visit a KCLS branch. If you aren't finding what you need through the online resources at KCLS, you can always check the Bellevue College Library's online resources as well.


This is stock number 9828, we are here at Summit Automotive in Fond du Lac, Wisconsin. You're new and use sports car headquarters. Today we are checking out this super clean 2016 Subaru WRX. This vehicle has the 2 liter 4 cylinder motor, which pumps out 268 horsepower. From this HD video you will be able to tell that this car is extremely clean all the way around, inside and out. We shoot all of our videos in 1080p, so if you have HD capabilities on your computer tablet or smartphone device, turn them on right now, because it's like you're right here looking at the car with me. Very clean down this side. Comes with these 17 inch painted alloy rims, Falcon Xenus 23545 ZR17 tires on here. And these tires have a decent amount of tread left, I'd say right around 50% of the tread left on those tires. Front fender is in pretty nice shape, has the projector lamp headlamps, the LED running lights, the cowl induction hood, passenger side fender is absolutely perfect, passenger side rim, no scuffs, no scrapes, very nice condition. And as you go down this side of the vehicle, you can see just how clean the body is, how reflective and mirror like that paint is, see all the body lines, the light reflecting off of it, something you just can't get with pictures. We take these HD videos so if you are far away or even if you're close by and just cannot make the trip down, you can still see the car, hear the car, and have confidence in the vehicle that you're looking at before you even get here. Back rims pretty nice, and the back tires have just as much tread as the front tires. Of course four wheel disc brakes, coming around to the back here, no major cracks or dents on that rear bumper, does have some aftermarket exhaust on it, sounds really good. Deck lid is in excellent condition, we'll get into the trunk in just a little bit. And as you go down this side of the car, just as clean as that passenger side. For full disclosure, this back rim, pretty nice condition as well. Didn't see any dents or dings on those doors.  We'll take a quick look at that trunk before we get too in depth inside the car, but the back trunk area is very clean, and it does have the tools and a spare tire and the jack tools underneath there. Those back seats do fold down, which we'll get to in just a minute. But getting into the car here, you can see that this car has 28,629 miles, the instrument cluster is nice and clean, you get a very nice leather-wrapped steering wheel with the thumb pads right here, got your Bluetooth and radio controls right there, cruise controls on the right. You do get an information center up top, gives you the time, outside temperature, you get the 7-inch radio. This is also where your backup camera shows up, let's see what we've got for different sources here. AM, FM, and Serious Satellite Radio capabilities on this car, got your climate control right there, passenger seat and carpeting and floor mat, very, very clean, no rips or tears on that. And the headliner is nice and clean, you got map lights up there. We'll take a quick look at the back seats and then check out under the hood. Back seats are just as clean as the front seats, no rips or tears. This car has never been smoked in, smells very clean inside, backrests are nice and clean, factory floor mats and carpeting is nice back here as well. And these seats do fold down like I said, four extra storage, they go almost completely flat which is nice. And we'll take a look under the hood, I'd personally like to thank you for checking out the video today, hopefully from this HD video, you'll have been able to tell just how clean this car is all the way around, inside and out, just got to find the hood latch here, there we go. Two liter four cylinder motor, 268 horsepower engine bay is very clean, runs very smooth, this car has been fully safety and inspected by our service shop, has a fresh oil and filter change, all the fluids have been checked and topped off, car has been completely gone through by our detail crew and is 100% ready to go. To see more pictures of this car or one of our other 450 new and used cars, trucks, SUVs, minivans, wranglers, sports cars, you name it we got it, go to our website, www.summitauto.com, full pictures and descriptions of every single vehicle on our lot, videos of every single used vehicle that we have all at summitauto.com, thank you so much for checking out the video. If you want to make this one yours, give us a call right now,<PHONE_NUMBER>, ask for one of our sales associates to make this Subaru WRX here today. Once again that number is<PHONE_NUMBER>, thanks again for checking out the video, if you'd like to check out more you can go to youtube.com slash summit auto remember to like, subscribe and share on this video and all the videos that you see there, in fact in a second you'll see a link to subscribe to our YouTube channel on your left, a link to more sports car videos like this one on your right and if you have not been to our website on the bottom link to this vehicle on our website, click those, check us out, like, subscribe and share and we really look forward to helping with this super clean 2016 Subaru WRX, thanks again.


Putin violates the International Criminal Court and visits South Africa. Russia's President Vladimir Putin has visited the Republic of South Africa, despite the international warrant of arrest on his head by the International Criminal Court. The current president of Russia is Vladimir Vladimirovic Putin, a politician and former KGB intelligence officer, who was born on October 7, 1952. Putin has held both positions continuously since 1999, president from 2000 to 2008 and since 2012 and prime minister from 1999 to 2000 and from 2008 to 2012. After the fall of the Soviet Union, this man, who has served as president of Russia for a considerable amount of time, promoted Russia to a higher level. Although he is a charismatic and dynamic leader, some members of his community and the Worldwide Committee do not admire or love him since they see his rules and policies as dictatorial and in violation of human rights. Hello there, welcome. I am James your host and you are watching Africa Reloaded. Before you continue to watch this video, please make sure to like and subscribe to our channel. Many enemies have been made of Russia and its leader, Vladimir Putin, as a result of their foreign policies and acts. Despite being an economic partner to numerous EU nations, Putin has turned against the nations and partners with whom he had previously done business. Why is there such hatred? Why is he being hunted by the ICC? Can the ICC arrest him in South Africa? Continue watching to learn more. Russia launched three military incursions into Ukrainian territory in February 2014. During the Euro-made-in demonstrations and the overthrow of Viktor Yanukovych as president of Ukraine, Russian soldiers without insignias seized command of key infrastructure and locations inside the Ukrainian region of Crimea. The Russo-Ukrainian War, which started in 2014, significantly escalated on February 24, 2022, when Russia attacked and annexed areas of Ukraine. Tens of thousands of people have died as a result of the invasion, which also started the biggest refugee crisis in Europe since World War II. The ICC has issued an international warrant for Putin's arrest due to the violation of human rights and the slaughter of civilians. On March 17, the International Criminal Court, ICC, issued an international warrant of arrest for Vladimir Vladimirovich Putin, the country's president, and Maria Alekseyevna Vova-Bolova, who has served as the president of Russia's commission on children's rights since 2021 for alleged war crimes in Ukraine. Illegal deportations of people, including children, and illegal transfers of people, including children, from occupied areas of Ukraine to the Russian Federation. Putin has defied the ICC and visited South Africa despite having an arrest order out for him. According to the South African presidential spokesman Vincent Maguena, Russian President Putin was scheduled to visit South Africa in August to attend a BRICS meeting. Thus, this trip appears long overdue. It should be emphasized that these countries have gotten along well with one another since the beginning of time. As the Soviet Union, formal diplomatic ties were established between the two nations in 1942. Both Pretoria and Cape Town are home to Russian embassies and general consulates. Since South Africa has an embassy in Moscow, their relationship is stronger than that of any other country in Africa. I am aware that everyone wants to know if Putin can be apprehended in South Africa by the ICC. First, I'd like everyone to know that since Russia withdrew its signature from the Rome Statue in 2016, it is no longer a member of the ICC and has no jurisdiction there. Putin can be held accountable for activities taken against a party as well as Ukraine, which is not a member but has acceded to the court's jurisdiction since 2014. Would South Africa therefore betray Putin? To stay informed about anything related to this, subscribe Africa Reloaded. I'll keep you informed on every step of this visit. We appreciate your dedication to Africa Reloaded. Please remember to subscribe, like, share, and leave comments on our channel. To receive notifications on newly added videos, be sure to click the notification icon.


Is anyone else think it's inappropriate that we're having a Ruby track inside the crystal ballroom? Okay. I'm very nervous. So this is a hamburger hat. And for those of you watching the livestream, this is a hamburger hat. And those of you reading the captions, this is still a hamburger hat. So my talk is pointers for eliminating heaps of memory. And yes, there will be a C code in this talk. This is a pun in case there was any question about that. But first I want to talk a little bit about Ruby's standard library. Sorry, this is a good one. There is a library which you can install called standard. It is Ruby's standard library. If you were at the game show yesterday, we were talking about the most popular gems. And I want to make this to be, I want to make Ruby's standard library one of the most popular gems. Basically what this gem is, it is an opinionated configuration of RuboCop. So you can't configure it at all. You can. So you install it and use it. It's an anti-bike shedding tool. You install it, use it like RuboCop, but you cannot change anything. That is it. You just go by those rules. Those are the correct rules. So go ahead and download Ruby's new standard library today. My name is Aaron Patterson. You may know me on the Internet as Tenderlove. If you don't recognize me in a burger hat, this is what I look like online. It's a little different. I have two cats. This is Gorbachev Puff Puff Thunder Horse. The other cat is SeaTac Airport Facebook, YouTube, Snapchat, Instagram. We call her ChooChoo for short. But I have stickers of my cats. So if you want to come talk to me, please come say hello and I will give you a sticker. If you want a sticker, you don't have to take one. But I have them. Anyway, I work for a very small startup company called GitHub. We were recently acquired by a very large company. So I had to change my desktop background to stay on-brand. Anyway, GitHub is the very first legit company I've ever worked for. I love using Git, but I will not force push it on you. Now, yeah. Now your pain feeds me. Now, this acquisition by Microsoft has really given me a chance to branch out. I'd say that it's opened a lot of doors for me. Did I say door? I meant it's opened a lot of windows for me. Ah. Oh, thanks, Shane. So one important lesson that I have learned. So you may have received some random airdrops of cats. If you recognize the cats in the slides, that's me. But I've learned one important lesson that is don't airdrop the people who are speaking, which is happening to me right now. So anyway, I just barely got my, yesterday I just got my Microsoft email address and I'm really, really excited about it. So I want to share it all with you. This is my email at Microsoft. So please, seriously, this is my email. Please email me here, like send me many emails. But much like my regular email accounts, this will go into an inbox that I do not read. So, but please email me here. I will check it when I figure out how to use it. And I hope that your emails will help to give me a better outlook on life. All right. So now let's get to the real technical content. I hope that you will enjoy this talk. I'm going to make many PowerPoints. Actually, Comic Sans and Times New Roman are the only fonts I'm allowed to use now. All right, no, okay, let's get to the actual content here. So I'm going to talk a bit about reducing memory usage in Ruby. Specifically, I'm going to talk about two optimizations that I wrote for Ruby 2.6. We're going to go through how, two patches I wrote. And we're going to go through how I came up with those patches, what tools I used, and how you can look up, do this same type of thing. So the first patch I'm going to talk about is a patch for the loaded features cache. And I'll talk about that later. The second patch I'll talk about is one I call directIC marking. IC stands for instruction sequence. But before we can talk about reducing memory usage, we have to be able to find what memory to reduce. So the first thing I want to talk about is finding, actually finding memory usage in your application. Now, the patches that I wrote, well, Ruby is written in C, MRI is written in C. So a lot of the heap analysis that I do has to be with the C programming language. So we're going to talk about techniques for finding memory usage in C programs. So there's two main techniques that I use. And the first one is a very bad technique. And it is called reading the code. This is an inefficient technique, and it does not work all the time. So but it's a technique that I sometimes have to use. The other technique that I really like to use is called malloc stack tracing. And I'll talk about that, how to use that in a minute. But with Ruby programs, we have to think about two different places where we allocate memory. One is in the garbage collector, and the other one is from malloc. So we allocate Ruby objects using Ruby's garbage collector, and we allocate other stuff, for example, strings or, I don't know, other things using the system's malloc. We actually have a lot of tools for profiling objects that are allocated in the GC. For example, object space and the allocation tracer gem. You can use these two, I encourage you to go look them up. But I'm not going to talk about them today. But these are very good for profiling Ruby object allocations. But they're not so good at profiling malloc allocations. So we're going to look at how to find malloc-based allocations. And the technique that I use is called malloc stack logging. And this is a tool that's available on OS 10. But there's other tools available on Linux and other operating systems. But I don't know all of them. I will step away from this topic now. So malloc stack logging, the way you use it looks like this.  And here what I'm doing is I'm starting up a Rails application. I print out the PID of the, oh, I have labels for these. So we enable the logger, print out the PID, clean up any garbage, and then just pause the process. And the reason we have to pause the process is because OS 10 uses address randomization. What that means is every time you run your program, stuff gets allocated into different addresses. So in order to know what those addresses map to, we have to pause the program and profile it while it's still running. So this just, that get seed just pauses the program. So we run this in one terminal.  And what this will do is it'll log every time a malloc or a free was called. Along with the stack trace for that malloc and free. Now, you need to have a lot of room available on your hard drive when you do this. Because if you have, this is just profiling a very basic Rails application. For a very basic Rails application, the log file is about 6.2 gigs. So you need to, like if you're gonna do this on your actual app, you need to have some free space. Now, the file contents look a bit like this. Where we have basically just one line per alloc and one line per free. And you can see where in memory the allocation happened, what size it is, the stack trace, and for the free, we can see what address was freed and the stack trace for that particular free. Now given that information, we can reconcile a live memory in the system. So this is a program, you don't need to read it too closely, but it's a very simple program to reconcile allocs and freeze. So first, we know how much memory the program was using at any point in time before we paused it. And second, we can know what's allocating the most memory. And we can also know exactly how much memory we have allocated at the time the program was paused. So that's cool, but when you look at these stack traces, you'll see that the very top thing is either malloc or free. And we don't really care about malloc or free necessarily, we care about who is calling malloc. Those are the places we wanna target in our code. So if we adjust that previous program just a little bit, instead of logging, like taking a look at what malloc we have, we take a look at the caller of malloc. So we know where to look at our profile. And to give you an idea of what this will look like, here's a pie chart of the top allocators in Ruby when booting up a Rails application. These are the top callers of malloc. So we don't read this too closely, just know that you can do this. So after doing a process like this, I will combine this technique with the other technique. I'll combine these two techniques, instrumentation plus reading the code. I'll go look at those functions that we're allocating a lot of memory, and then figure out how I can reduce the memory usage for that particular function. So with that, let's take a look at the loaded features cache. So this is our first, the first patch that we introduced. The loaded features cache patch that I wrote takes advantage of a technique called shared string optimization, and I'm going to teach you about the shared string optimization, then we'll look at the patch. So essentially, Ruby objects, Ruby strings allow us to share the same underlying C buffer. Every Ruby string is backed by a char star buffer in C. Well, not every one of them. Let's pretend that's true for now, mostly. In this example, we have three Ruby objects. And they're all being represented by the same underlying C string buffer. So we have X pointing at the head, A is a dupe that also points at the head, B is a substring that points at the next character all the way to the end. Now, we can only do this technique. We can only share strings like this if we're looking at some point in the middle of the string all the way to the end of the string. So for example, let's take a look at an example of where we can't share strings, like for example, this one, we have X equals some string, and then we take a substring from the beginning of the string to somewhere in the middle. We can't share those. And the reason we can't share them is because Ruby, the underlying C buffers need to be null terminated, so we have to share all the way to the end. So these are not shared strings. So our shared string rule is always copy to the end of the string if you can. That way we can represent more than one Ruby string while using the same underlying string buffer. So what does this have to do with loaded features, and what are loaded features? Loaded features is a global variable like this. It keeps track of every single file that has been required in your Ruby program. So if you do require foo and you look at loaded features before and after, you'll see that it's added a new string to that array. This array is used as sort of a database, so we know that every time we require the same file, like if we require the same file over and over and over again, it's only required once, it's only executed once. Ruby uses this loaded features array to determine whether or not a file has been required. Now, unfortunately, there's a little bit of a complication. What is the same file? When I say the same file, what does that mean? So here is a program. These all require the same file. You'll notice that the parameters we pass to require are different on each call. So this is an extreme example of this particular issue, but we expect that particular file to only be executed once. Now, that means that Ruby has to look up, oh, have I required this before? Have I seen this? Have I seen this particular thing? And it will have to search through that loaded features array in order to find it. But the problem is, arrays search is slow. We don't want to search the array for every single time you call require. Just think of all the files you require in a Rails application. It would take forever to start your application up. So in order to speed this up, Ruby creates a cache of every possible parameter that could be passed to require. I'll give you an example of this. So for example, let's say we require abc.rb. Ruby will, when you require that file, it'll create a cache that looks like this. This is every single key that could be passed to require that may map to the same file. That way when require is called again, we can quickly look up, hey, have we seen this key before? If so, let's go check it out. So the actual cache structure looks like this. It's all of those keys mapping to the array index of the file that we actually required. So when we require a file, we can look that up, look at the array, and see what actually got required and say, yes, we have this already, let's just skip it. So the way that we generate this cache looks like this. It's actually written in C. I have translated it to Ruby because this is a Ruby conference, not a C conference. And I think Ruby is a little bit easier to read. Don't read this closely. Please, please. We'll walk through this. So let's say we do this require abc.rb. And we have a string that looks like this. The way that the algorithm works is it puts two pointers at the end of this string buffer. Then it moves one pointer back to the first period. Then it moves the first pointer back to the first slash, and we take from the first pointer to the second pointer and the first pointer to the end of the buffer, and that's our first two cache keys. Then it moves the pointer backwards again, taking from one pointer to the next and one pointer to the end, and we get our next cache keys, and we keep repeating this until we get to the very beginning of the string, and now we have our entire cache thing, which I skipped over. Sorry about that. Let's see that again. Go. Go. Yes. Let's see if I can do this. Does anyone go to LA Fitness while you're here? I think they just call it Fitness here. I wanted to pick up some LA gear, but I think it's just clothes here. All right. That, okay, I'm distracting myself. So the problem with this cache key generation is that it takes substrings of the original string. So it uses this RB substring function call, which is the same function call we basically use when we're doing square brackets. And when we do this, it actually takes copies of that string. These Ruby objects here at the bottom, four of those get to point at the original long buffer, but these other four at the bottom, they have to copy the string because they're not going all the way to the end. So our first optimization we can do is we can reduce the number of mallocs we have here. We actually have to do four mallocs along the bottom there. So we have eight Ruby objects and four new malloc allocations. So we can reduce the mallocs by using this shared string optimization. And the way we do that, our first step is we take a copy of the string once. So we create a new copy of the string that just goes all the way to the period. Now when we take substrings of these two, we're able to share these buffers between all eight objects. So we have four objects pointing at the top buffer and then four objects pointing at the bottom buffer. So now we're down to only two mallocs where we had five before, I guess. We can also eliminate Ruby objects. Now this cache is only used in C. It's never exposed to you, the Ruby user. So you don't need to see these Ruby objects at all. Today, in Ruby 2.5, the cache looks like this. We have a hash that points at a bunch of Ruby objects. Those Ruby objects point to the underlying string buffers. But since we never exposed this, you don't need to see these and we can just have the hash point directly into the strings themselves like this. All right, so this way we can eliminate all of those Ruby object allocations. So now we're down to only two malloc calls. And I made a patch for this, this is the patch. It's a very, very simple patch. It's this, very simple, right? Just kidding, it was not simple. So we can measure the impact of this and we'll measure the impact of this by using allocation tracer. In this example, we just require a very long file and measure the number of objects allocated. So before we expect to see a bunch of string allocations and in the new version, we expect to see fewer string allocations. And in fact, when we output it, it looks like this. I have made a graph because this is not easy to read. But this is what the object allocations look like when we require a file. You can see that we have, the blue one is Ruby 2.5, the green one is Ruby 2.6. And in this case, we were able to reduce the number of string allocations by about 50%. So, but that doesn't mean that it reduces your program's allocations by 50%. So let's see what it actually does, how it actually impacts your application. So this is a graph of Malik stack logging for Rails application. The x-axis is the sample number and the y-axis is the amount of memory that we allocated. So you can see if it's closer to the origin, that's better. Before this patch, we're up there in the upper right after we're a little bit down. This is about a 4.2% savings in overall memory. Now the thing is, this absolutely depends on your application. If you require more files, you'll actually save more memory. So in other words, the more you load, the more you save. How much would you pay for this feature? $100, $1,000, you can have it today when you upgrade to Ruby 2.6. So I can't tell you how much this will actually save for your particular application because it depends on how many files you require, but at work we require a lot of files, so I expected this will have a good impact. Now after I got done writing this patch, as I said, this is a story, after I got done writing this patch, I was very, very proud of myself. I debugged the codes, I wrote the patch, I made sure that it worked, I had some nice graphs, I was really pleased with myself. So I submitted a bug, I was so happy. I posted the patch here, and then I got a comment on it, and the comment was from this person named Funny Falcon, and he said, did you compare it to this other one? And I was like, hmm, I don't know about this other one. I will click on that link. And so I did, I clicked on the link, and it turns out that he had actually found exactly the same problem that I was talking about, and submitted a patch as well, but unfortunately he submitted his patch five years ago, and it was not applied. So I applied his patch. Oh, thank you, yes. Now, the lesson from this story is always search the issue. All right, anyway, Funny Falcon is now a Ruby committer, so he can just do it himself next time. Anyway, all right, let's move on to the next patch I wanna talk about, this one is called Direct Instruction Sequence Marking. Now, unfortunately this technique requires that we know a little bit about how Ruby's virtual machine works, so I'm gonna talk about Ruby's virtual machine, and we're gonna implement a tiny virtual machine before we write this patch. So Ruby's virtual machine is a stack-based VM, and what that means is that we have a list of instructions, so we have a list of instructions like this, and we have a stack. And we can think of the instructions as essentially our program and the stack as our workspace. These instructions are, you can kind of think of each instruction as an array where we have the instruction, the particular instruction, and the operands for that instruction, so in this case, we have an instruction called push and an operand called three. And the way that the VM works is the VM keeps what's called a program counter, and the program counter points at the, always points at the next instruction that's going to be executed. And then it executes it and increases the, increments the PC. So in this case, we'll push three onto the stack, we'll push five onto the stack, and then finally, the add instruction will pop two off the stack, add them together, and push the result value back onto the stack so we get eight put onto the stack. So how do we get these instructions? Like where we see simply how the VM works, but where do these instructions come from? Your Ruby programs are actually compiled. Before your Ruby program has ever run, it's compiled into byte code, and it has to go through a few processing phases. The phases are something like this. We start out with some source code, which is the text, the code that you wrote, or the new standard gem you downloaded from rubygems.org. Then it gets transformed into an AST. The AST is transformed into a linked list, and the linked list is finally transformed into byte code. And we can kind of break these phases up into two main sections where we have parsing and compiling, and where those two kind of overlap, it's a little bit gray area, but that's kind of how I think about it. The linked list phase is where we have any optimizations applied to your code, so if any code is dead, it gets removed there, or other types of optimizations, like people optimizations, that happens in that phase, and it's because linked lists are easy to manipulate. Finally, the linked list is just turned into a byte code, which is our product, and that's the thing that we actually execute. So the data structures that are involved, we have an AST, which stands for abstract syntax tree. I'm not sure why it's called abstract, because we use it as very concrete, but that is what people call it. It's essentially just a tree data structure. So we take our source code, for example, this three plus five, and we convert it to an AST, which looks something like this. We have a plus node that points at two children, a three and a five, and if we look at how these are actually implemented, under the hood, they're implemented as Ruby objects. These are actually T-node objects. They're implemented as Ruby objects, you just never see them. Now these T-node objects are then converted into a linked list, and the way that we convert them into a linked list is by recursively walking each node in the tree. So we'll start out at plus, and plus says, oh, I have children, I need you to process my children first. So the recursive function says, okay, I will visit your children first. We have a three, the three has no children, so we end up with just a push instruction with the number three. Then we visit the five child, we end up with another push instruction. Finally, there's no more children, so we add a plus instruction to the end, and that's how we end up with our linked list. And if we were to convert this into Ruby, it would look something like this. This is kind of the high level way that we process this. So we process all the children's before we process the parent object. Next, we apply optimizations to the linked list, and I am going to hand wave over this. Emoji pun, yes! All right, I'm gonna hand wave over this part because we're talking about memory optimizations, not runtime optimizations, so we'll just not talk about these particular optimizations. So we start out with a linked list, and then we hand wave a bit, and this is our optimized linked list. They are the same, yes! So then we convert it into byte code, but let's talk a little bit more. What exactly is byte code? Bite code is binary code that's executed by the virtual machine, and if you look at the implementation, it's actually literally just a list of numbers. It is truly just a list of integers. So where did this list of integers come from? Well, we take the byte code, and we have to translate all these linked list nodes into integers, so in this case, we'll translate push three into some number that represents push, say one, two, three. And then we have the number three, which we'll use that to represent three. And again, we have a push five, so we'll use one, two, three for our push, and five, and then we'll have add, and we'll say we represent that as four, five, six. And now we've got our byte code, that's it. So this linked list gets translated into which are Ruby objects. Also gets translated into byte code, which is again a Ruby object. It's called an iMemo object. So all of these are Ruby objects. This is important for our optimization. We'll get back to that soon in less than 12 minutes, I hope. So let's make a simple VM. We know how this stack-based VM works. We need to be able to push something onto the stack, but instead of these arrays, we actually have just a list, so we can't just push our PC one at a time. We have to actually push it two, and then two, and then one. So we'll write our program to take that into account. We have here our simple VM, which all it does is exactly what we've described in this code. However, we increment the program counter by an extra one whenever we encounter a push instruction. This is it. This is our entire VM. We have done it. We've gone through it. We have learned how compilation works. We've learned how the VM works. And I think this is a really, really good point for us. We are doing well. But I want to look at one more program before we can get into this memory optimization, and that's a Hello World program. It's almost exactly the same as our integer-based mathematics program, but instead we're using strings. So in this case, we'll end up with an AST again, just like we did in the mathematics example. However, when Ruby builds this AST, it actually allocates Ruby string objects. This Hello and World, they are both Ruby string objects. They're stored in this AST. Then when we take the AST and convert it into a linked list, we get these push operations, and these push operations also have those Ruby objects. They are the same Ruby objects that we allocated when we parsed the code. Now when we translate the link list into byte code, we go through here, and we have to actually use an address for the string, so our byte code, remember we can only deal with integers, so rather than an actual object, we have an integer that's a pointer to the object, so we have the object address. So in this linked list, we have two Ruby objects, and we have the object addresses that correspond to those Ruby objects. So now, when we write our VM this time, obviously we don't have pointers in Ruby. These only exist in C, so for our example byte code, we're just gonna embed the strings themselves, okay? So we have our byte code here, we'll use our VM that we wrote before. Now, the thing I need you to note here, I know this code is very small, you don't need to read it, just know that we're executing the byte code twice, okay? This is important here. We execute the byte code twice, run this program twice, essentially. When we run it, we see a bug.  We see that printed out twice. Now why is that? The reason is because we allocated Ruby objects here, and when we push these Ruby objects onto the stack, we'll run through this again, we push hello on, we push world on, and then when we call the append instruction, this is a destructive operation. It appends world to hello, that mutates the objects, but those objects are the same ones that were in our instruction sequences. So when the object on the stack gets mutated, the objects in the instructions also get mutated. This is a problem. If we think about this, if we execute the program a third time, it's gonna print out hello world world three worlds, I think. So when we execute this again, we'll see too many worlds here. So if we run it again, we see this output. So how do we fix this? How can we deal with this? We have to change our VM a little bit, and the thing that we need to do is we actually need to copy the object before we push it onto the stack. So we add a new dupe here. All this does is just copy the object before we push it. So when we run the program again, instead of pushing the object itself, we push a copy onto the stack, then the copies get mutated and everything works the way that we expected. And if we think about this in terms of object allocations, this means at compile time, we're allocating two strings for the literals that are in our program. We allocate two strings at runtime because we have to dupe those strings before we push them onto the stack. Now as a side note, this is why the frozen string literal optimization helps us. In this case, this is telling Ruby, hey, we cannot mutate these strings. And if we cannot mutate them, it means that you can push the original onto the stack and not dupe every time. So if we change to use the frozen string literal, we'll allocate two strings again at runtime, but we only have to allocate one, or two strings that compile time and only allocate one at runtime, which is a result of the plus operation. So now that we understand how the VM works, we understand why this optimization helps us and I think that's really cool. So reducing memory usage, we've gone through all this background. We're actually going to, I think we understand enough details at this point where we can actually look at this allocation technique. So byte code, as we said earlier, byte code is stored on instruction sequences. Instruction sequences are just Ruby objects. I think I've said this a whole bunch of times, but remember, Iseq just stands for instruction sequence. So if you see that around, that's what it means. So if we look at these instruction sequence objects, we'll see that this Iseq object points at a list of integers. That's our byte code. Now, our Iseq layout, as we saw during compile time, since we have to point at, we only have integers, so we have to point at the address of those Ruby objects. So in this case, we may have some strings in here. It points to hello and world.  But imagine if these two strings were G seed, if they got freed and your program ran, what's gonna happen?  There has to be a way for the garbage collector to know about those particular strings. Come on, come on, KinoAnimate. There we go, yes, your program will blow up. Imagine I said that perfectly on time. Anyway, so how do we deal with this? How do we prevent those string objects from going away? Well, the technique that we used up until Ruby 2.6 was a thing called the mark array. What this was was the instruction sequence object would also contain a reference to an array. So when your program was being compiled, as the instruction sequences were being built, any time a Ruby object was created, like for example, those strings, the string would be added to the mark array. So it's pointed to by the byte code as well as this mark array. So you can see as we compile it, we add it to two places. So the reason this works is because when the GC marks the instruction sequence object, the instruction sequence object says, hey, I also have an array. Go mark the array. And the array says, oh, I have some stuff too. Go mark them. So it marks those strings and keeps them alive. And that way, your Ruby program won't blow up when you execute it. So this mark array has a couple of problems, and I think the first problem with it is just an organizational problem. In this case, we actually have what I think of as duplicate information. We have two references to each object, and the only reason we have the references from the array is to keep those objects alive. But if you just look at byte code being executed or the byte code itself, it's very difficult to tell that this byte code actually contains references to Ruby objects. So I think that's very confusing. It's confusing to me. So I think these two lines here what I like to call hidden references. We have references, but it's not obvious. The other issue is that we have array bloat. So whenever you add an object to an array, you know Ruby automatically expands the array for you to have more capacity. But when you add one object, it doesn't just increase the capacity of the array by one. If it did that, it would be very expensive for you to keep adding objects to an array.  So if we were to map that out, the array size, the actual number of elements versus the capacity, it would look something like this. So the X, well, I don't know, looks like that. I forgot what these axes are. You get it. So the difference between this green line and this blue line is actually unused waste. We're not using it until we start filling up with more objects. Now this isn't normally a problem in your programs because you'll use those arrays, mutate them, and then throw them away, and we don't need that memory anymore. It's not a big deal. It's functional, we use it. But this array in these instruction sequences, this array lives forever. It lives for the life of your program. So we have this empty space that's just sitting there unused, and that really bothers me. I like to use stuff. So how can we fix this? One way we can fix this is to remove array bloat. We can resize the arrays when we compile. So the other technique, I think, which would be better is to just remove the array itself. And we can, we can do that, and we can do that with a program that's almost exactly like the VM that we wrote. If we just had a program that could decode these instructions, and whenever it finds an object, mark that object. Yes, animations, go. Mark that object, then we could accomplish this without the array. So we can do this almost exactly the same way as our VM. So here we have something that's written almost like the VM, but rather than executing the instructions, we just mark something. We mark the parameters. That's entirely what this technique is. So if we use this, we can eliminate the array completely and be able to mark these objects directly. So we call this mark, these are, we're marking the objects directly, which is why I called it a direct marking technique. So in the real world, with a basic Rails application, we're able to reduce the array allocation right there. You can see the two, blue is 25, green is 26. In Ruby 2.5, we allocate about 35,000 arrays on boot in 2.6. It's about 8.5,000 arrays. This is a, overall, it's a 34% reduction in objects at boot time. If you look at, this is a map of the heap on Ruby 2.5. Black pixels are objects, white pixels are empty space. This is in Ruby 2.6. This is after Ruby 2.6 with GC compaction that I'm still working on. Talk to me about that later. Overall process memory reduction, we lose about 6%. Again, this is before and after. So this is a 6% reduction in allocations. Now again, this depends on how much code that you load. Remember, the more you load, thank you. Ah, I did it. How much would you pay for this? $100, $1,000, you can have it today by upgrading to Ruby 2.6. So this is where the patch is. You can go take a look at it. The actual code is right here. Again, it's a very simple patch. Okay, conclusion. We learned about VMs, we learned about memory management, but most of all, we learned about ourselves. Everyone, please upgrade to Ruby 2.6 coming in December. Thank you very much.


Good afternoon everyone and welcome. Welcome to Stockswish Show market review. The QQQ is reviewing this market here I'm just gonna go over the market call. I made this morning. It's playing out perfectly beautifully This was an impossible call that I made this morning Why because the market really just was neutral today And a lot of people probably thought the market was gonna fall and it broke the load twice But I called the market to hold and I said the market would hold I don't even know if anyone that watches my videos unless you're watching like every single solitary one where I talk about the market Or trailing me back however long or many months or years to listen to my market calls if you're getting all of this If you're in the live training room with me you get it every day And it's one of the benefits of being in the live training room with me is that you get my market calls every morning before the open You know, I can't wait to hear what people Think tomorrow morning when I get in the room about this because this this was an impossible call to make For the read on this for all intents and purposes I'm sure most people in 99% of the people out there thought the market would drop today And I said it would a hundred percent retrace the bar of yesterday This is exactly what I said I said this morning The the market is gonna hold today rally and a hundred percent Retrace the bar from yesterday and that is exactly what we're doing. I I So why was this an impossible call to make well, let's look at the let's look at the intraday chart first How am I able to see these things before they happen? I mean, I'm able to predict stuff before it happens So often it's not even funny and it's because I know how to read gaps It's it's it's all due to my gap analysis But you know which I created so I take credit for the fact I'm doing it But it's really just me reading the gas. It's just that most people don't know how to read gaps, right? So anyways the market open how drop broke the low rally rallying up rallying up And this could have been the low of the morning in here aggressive to go long it Many people shorted it okay shorted it in here the market drop broke the low broke the low actually before 10 o'clock That normally, okay, you would look at that and you would say You know, that's that's a good short. It's weak People then went more into the shorts in here. How do I know brock market broke the low again? Market broke the low again came in and held around 11 o'clock reversal time. That was the low of the day This was the low of the day here. Guess what 96 dollars 96 dollars a whole number and market has rallied ever since so You know the market broke the low twice this morning and And and still hell and it's past the target actually target was 98 today for the market I said in the run this morning target for the markets 98. It's a 98 15 It's 2 30 in the afternoon. This could go all the way up to 98 20 here It's gonna it's gonna go to 98 20 98 25 Markets gonna close strong marks and close strong and I don't know where we're gonna get tomorrow morning But I'm feeling we're gonna get up So here's everything I said in the morning if all the people that were there in the morning with me listening What did I say? I said I'm reading this gap. It's a neutral gap. It's neutral slash bullish and we're gonna hold I said don't think we're gonna come in. We're not gonna come in this is strong I read the gap today strong and that was a possible call Why because we were just sitting there like a boop and I said we're gonna hold and then I also said we're gonna 100% retrace the bar from yesterday. We did that too. So we're gonna go to 98 We did that too and I said don't be surprised if we make a new high sooner than you think and I said don't be surprised Why because people are shorting this market buy is gonna come in people are sure they're gonna get stopped out We could retrace the move that we had down in here in the last week or a couple of days We could retrace it. I said in one day or two days It's exactly what I said because so we could retrace it in a gap We could retrace it in one day in a gap or we could retrace it in two days and we've already actually retraced You know once we get up to here half of it. They're just keep running It's just rally all the way up into three o'clock here here past night 98 20 past 98 25 98 30 98 50 99 dollars We can just keep running running running running running market will close strong today Like this or more Okay, and people are still in the short So this is actually just the nice buying buying buying. This is all the buying coming in the market Shorts aren't out of this yet And no one should have shorted this market because it is nothing too short There was nothing bearish about any of this yesterday was a bearish day, which I called accurately to You could have you know shorted the market Yesterday, but I didn't do that and I don't do that But you could have But today was not a day for that. There was not gonna happen and uh So the other thing I said this morning in the room was that october is gonna be a very bullish month I did say that in the video yesterday and despite the fact I called the market short yesterday I said october is going to be a very bullish month between now and the end of the year We're going to have some big big rally in the market market when the next four to six months It's going to have and rally and hit some crazy number. So one of my friends texted me the other night I think it was last night. Yeah, he texted me as a stop in the market. I texted about nope He's a friend of mine. That's been trading longer than me in the market a stockbroker He's done it all longer than me and he's asking me my opinion That's actually very complimentary I have friends of mine now that are around and people in new york that are asking me what I think of things that have Been around way longer than me I know how to regapse and I am feel so grateful lucky that I do because that is how I'm able to accurately Read what's going to happen in stocks and the market and predict things ahead of time I read it in the morning. I read in the pre market And just make the call and do it you can take the Application of the system I have for the 26 point rating system and you could rate at ETFs, you know, that's I mean I don't rate the market every day. I'm reading it I'm reading it because I have a good eye now because I you know, I know all the stuff I know but you could actually rate the keep you use the spy every morning, too You guys so you could play ETFs based on the rating system to get the direction, right? It's another application of something to do that You know, again, it's it's it's not the reason I created that I created it to trade stocks In the right direction to read the gap, but you could use my system to read the market ETFs or any ETF actually And uh, that's the reason I've been calling this market very well very accurately Well, this was this was an impossible call today though because I know that people thought we were going to break and we even even for the first hour and a half of the day Even for the first hour and a half of the day it looked like that So we'll see what everybody says tomorrow morning in the room You know, I hope no one's shorted this market. It wasn't no go Today and the market is higher market could make a new high before the end of the week today's only Wednesday You got Thursday and Friday left. Do I know this can happen for certain? No I I don't know until I get up in the morning and read the gap But we're probably going to gap up tomorrow morning. I mean You know unless something happens where some data is out tomorrow morning before the open which I really love to say and that could change that but We're going to close strong 9850 is the next number wouldn't put it past the market to hit that in here and close like that today Really going to have a strong close no matter what happens here today So nice call I made in the market this morning everyone in the live trading room heard me make it and uh just one of these things where This is I'm even a little speechless here myself I said I said 100% you trace a lot from yesterday Anyways, if you'd like to learn how to read gaps or take my class to learn how to trade email me and melissa at the stocks whoosh dot com The class is this weekend october 11th and 12th email me if you'd like more information Melissa at the stocks whoosh dot com arc. It's higher arc. It's going to make a new high Higher higher higher have a great day everyone


My name is Don Creipel. I'm currently Director of Eye Detect Services with the Capital Center for Credibility Assessment, C3A. Also a member of the Converis Technical Advisory Board for Eye Detect. I have 30 years of federal service, all of it in the credibility assessment arena, primarily in the area of polygraph but more recently other technologies as well. The 30 years, the first 20 years were spent with the Central Intelligence Agency as a polygraph examiner, researcher, and manager. And the last portion is Deputy Director for the National Center for Credibility Assessment, which is the government's Center for Research and Education on All Credibility Assessment Technologies. I was first introduced to the technology at that time called the Ocular Motor Deception Test in the early 2000s when I was climbing Mount Rainier with Dr. Hacker and Dr. Kircher. It was an idea that they were formulating between the two of them and their interest was, would the U.S. government be interested in this technology? And I being a U.S. government representative at the time doing research for the U.S. government, I had two questions for them. One, is it valid and two, is it practical? And at that early stage, they suspected that it was going to become valid when their research was completed and they did know that it was going to be practical based on the state of technology. And the subsequent research that followed over the next decade, they did in fact find out that it was valid and through the development of engineers in the sensors and the display and in the percol development, it has turned out to be quite practical. At that time I was naive enough not to know what was involved in the technology and not knowing what the state of the research was. But I had great faith in Dr. Kircher because for the last 30 years the U.S. government has relied very heavily on his research for the development best practices among polygraph examiners in U.S. government programs. So there was a reason to have faith in Dr. Kircher's judgment that this might turn out to be a very promising technology. While I was still with the government and with the National Center for Credibility Assessment I actually monitored a variety of technologies for those that might most be promising for the government problem set. Among them the most promising was the research being done at the University of Utah on the ocular motor deception test which eventually became eye-detect. And over the course of 10 or 12 years it became more and more clear that this technology had a great deal to offer. I had monitored this technology over the course of the last decade and found that the research was pointing more and more to a particular accuracy perhaps in the mid 80 percent. And they were refining the protocol they were finding where it would work best and some things that became confounds and managed to eliminate those. By the time it became a commercial product it became very very clear that this had a great deal of potential for applications that I was interested in in the government. For those agencies who have not yet had an opportunity to see the eye-detect system it is certainly worth your time to arrange a demonstration.