All right. Well, hi everyone and welcome to the guest the last day of the conference. So you made it congrats We are going to talk today about how Spotify has used flight to revamp their financial analytics platform and My name is Heitham Abouftou. I am one of the co-founders and maintainers of the flight open source projects and And joining me today is Delin Wilder from Spotify, but unfortunately Due to personal circumstances, he wasn't able to be here in person But he was gracious enough to share his thoughts in a recorded video So without further ado, I let him introduce himself and talk about what Spotify has been trying to do My name is Dylan I'm an engineering manager on a team called Vivaldi within Spotify. We work in the finance department And I'm also the tech lead on a project called one model. And so that's what this is about and one model Is really powered by flight. I just want to give some background on What we're talking about. So this is really one model is a financial forecasting problem and quickly what financial forecasting is is Every quarter is part of compliance objectives Spotify is required to project two years into the future what we think our profit and losses are and that's part of just being a public company And so it's basically a projection across all of Spotify's various business processes What revenues do we think will take in? What costs do we think we'll have to spend in order to get there? As in addition to just being part of you know requirement. It also forms a Big part of Spotify's business planning. You can imagine this is useful for investment investors It's just as useful internally for the people making decisions the C-suite, etc Unfortunately, you know, it's organically evolved over the years To be a bunch of different Heterogeneous processes across many different teams as you might imagine Spotify is a pretty complicated company We have a lot of different products. We work in a lot of different markets We deal with licensors music law stuff like that And so the expertise in order to kind of run this system is scattered across a lot of different domain experts And so as it stands this process takes about three to four weeks every quarter Span as many as eight different teams these teams work in silos some of these pieces are Excel models And then at the end of the day, you might imagine team one is handing off a Google sheet to team two to start running You know if the number of subscribers we get is input to the amount of revenue We think we're gonna get team one has to hand that off to team two And so it's a complicated process and so Goal number one that we're really trying to accomplish. It may be obvious, but it's an automation problem We want to fix these manual handoffs. We want to speed up the the feedback time to do this process And we want to you know reduce for errors and The secondary piece of this is that because it takes so long to run we can only really do this once per quarter That's too much of an effort investment And so if we think by automating this we can really unlock the second piece of the problem Which is business case against scenario analysis if we can run this problem and to end, you know within a couple hours then These people making the decisions can come in and say Well, what happens if we increase, you know our subs by 20 million people in India Versus what happens if we open a new market in Eastern Europe or something like that? So you can start to ask these questions more frequently without having you humans in the loop in order to answer them There we go So this is high-level overview what it looks like there's again It's a complicated process each of these nodes in this graph is actually, you know, this isn't one flight task per se It's a bunch of different things. These are just high level Logical pieces to Spotify's business model And as you can see here each individual one of these might be owned by a different team And there's lots of you know complex dependencies between teams And there's no I mean this is our best shot at what this thing looks like There's no like person who is in charge of like the overall end-to-end thing who knows exactly what this looks like It's it's very much a distributed ownership model So, yeah one model automating all the components And once we do that we can kind of unlock this scenario this business case and analysis scenario And you know, we think that'll be really cool All right, and thank you didn't So I thought this you can think of this part as well, this is our sort of requirement gathering phase now We have a problem statement and this is Spotify, right? You can imagine that problem replicates to a lot of other even smaller companies that don't have the capabilities they do the infrastructure they do and I thought before I talk about how flight has helped them and has been used in lift as well I will go just quickly through how we got here So it was not very long time ago when that was sort of the software mantra You develop software and ship some golden image on a CD and throw it over the wall to you know poor ops engineers who have to deploy and scale and service your application and handle incidents and all of that And in 2009 That the term div ops was coined and it's sort of skyrocketed sense and the you know coining of a term doesn't really mean we Finally figured it out or we solved the problem. I think it's more of a Recognition that there is a problem or a set of requirements for a problem to be solved And you know over the years We have built quite a lot of tools right as an industry There are a lot more, you know, CI systems and monitoring and you know all of these things Incident management and responses and you can see a lot of them in the showcase floor downstairs if you have been to And a couple of years after that this term came to be again another term got coined RPA robotic process automation And it was more of the the business side of you know A lot of companies looked at you know these The DevOps and you know what all the innovation that has been happening there and they were like well We want some of that But their problems are a little bit different the problem that the data they deal with and the people who need these Automations are not necessarily developers who will write codes for it So they also needed slightly different set of solutions for it and I think by 2018 or something there were like the most number of RPA solutions out there right now things are sort of converging and in 2015 ML Ops term was coined so that was already six years after DevOps or so and Again there these are like the dates don't mean a whole lot But one of the signals you can deduce from this is the the industry understanding or recognition of the difference in problems and requirements for ML and data only really sort of matured around that time and since then again, we have been developing tools and and processes and trying to make you know the life of ML engineers and data scientists better I You know maybe before then I would say that what a lot of attempts to sort of force Some of the dev tools DevOps tools onto ML engineers And they conceptually sort of work If you want to you know deploy your model Yeah, you can write a CI system for the or the CI use one of the existing CI tools for it If you have you know multiple steps and training and pulling data you can You know overimpose it into onto an existing CI tool but you know it Didn't really quite work a lot of engineers found themselves fighting with infrastructure a lot to get anything really done And I found this sort of meme I guess very applicable because you know if in a few months it will be exactly seven years since Coining that term and it pretty much feels like an an hour Apologies about that An hour has passed since sort of the the progression of Of us solving this problem I wanted to summarize a little bit some of the the key differences I see between the requirements for you know the DevOps and then the ML ops data and ML ops And you know again from a 10,000 foot view they look pretty much the same set of problems But the when you look at the details the inputs for example for a data or ML Pipeline a training model might be it's not just the code you wrote to train a model It's also the terabytes of data you want to train the model and when those changes your outputs change In the dev world you just have code and it's you know usually in megabytes And it's okay if you have you know 10 or 100 different CI pipelines that just check out the code every time Right because it's it's it's cheap. You can't really do the same if you are running an ML job You want to maybe share as much as you can the the you know the tools of the tasks and the steps that Do the heavy lifting or or query out of data or a compile a lot of data? Similarly for the actual job that runs in in the dev world. Yeah, the CI system. Maybe it takes minutes to finish I know 20 minutes if it's a bit slow and you start Getting Grumpy and start optimizing it In the ML world if you have a training job, you know, it's very normal for these to take hours Even days in some cases. We have cases where They run at lift Training building the map of the world essentially and that gets refreshed You know every couple of days and takes a long time to build and a lot of regions and a lot of You know slicing and dicing of the data and so on and it's a massive amount of information to process So it's expected that these things take time and when you when they start taking time You start seeing problems that you haven't experienced in in you know the in the simpler use cases Things like machines can die You're right like there are some fundamental issues that you just don't even think about in a typical CI system And you can't really run rerun things when when you know system failures happen You'll you need to be able to checkpoint cash stuff and rerun exactly from where you You know failed last time. There are a lot of other requirements that stem from just this one change in the requirements Whereas in for the iteration for example, they people still want pretty much the same flexibility, right? They want to make a change want to test it locally right unit tests somebody else makes a change I want to make sure their change is validated before it runs You want to be able to you know promote things that succeed to production So you want the same semantics you want the monitoring parts you want the incident management and alerting all of these things you want the as goals the trick is to make sure they We offer them or make them available to you in Where you are where you are writing your code or where you are developing your workflows and Obviously the stakeholders are different between the two And I want in the next few slides. I will talk about how Like flight addresses some of these concerns. It's really our take on on the problem Flight has been developed at Lyft We open source flight two years ago and since then there are tens of companies now that adopted the open source flight for for various Different platforms inside companies from building ML platforms on top data and data ops on top To just purely using flight those companies that sort of resell flight or repackage flight With the you know vertical integration in certain fields And and and flight would power, you know the underlying orchestration parts flight is a workflow to mission platform for business critical data and ML processes It's my sound mouthful, but I hopefully it will it will be clear as we go on We have a ton of integrations and I think at this point It's probably fair to say most of these are built by the community More than you know the original authors of the platform So they were all built to be used. They were not just built to you know Somebody's keeping count of how many integrations are on the platform They were built purposely for certain to solve certain business use cases And we we worked quite hard to make sure the platform is extensible through plugins or safe And isolated exclusions of these plugins and you know So it's it's quite easy to to expand that list as business Needs arise These are a list of some of the companies and I think we just added a couple more yesterday So this lift spotify Intel and bunch of other You know bigger and other startups This is our And and you know any any product I guess starts with some assumptions And this is our assumption for how we think an ML engineer You know go through the process of developing a Workflow or a pipeline or training model or data scientists does the same They start on the left here with some idea. So they have some You know, they want to write some business logic to try out something maybe query some data process data a certain way Train the model you know things like that And they want to write it locally. They want to start up the laptop open up their favorite IDE or Jupiter notebook Or what have you and just write it there if you start asking them to well, you can't do that You have to go somewhere else to start writing then things fell apart They want to be in their favorite tools there or the comfortable environment where they can pull in requirements that they have or they want the Library requirements and just write their code you want to take You know restrictions on which versions of libraries they can and cannot use because some other You know person in the team is using an older version now. They cannot upgrade, you know things like that They just want to sit down write the code. They want to write and test it right there But at the same time once they exceed the capacity or maybe of their laptop Maybe they are just running on like sample data on their laptop and now they want to run on the full data sets They should also be able to Very confidently run the code that they wrote in a remote environment where they can you know leverage bigger and more beefier machines and you know larger compute environments to process bigger and bigger data sets And that process should give them should be should guarantee to a certain degree That the code will behave exactly the same if it worked on my machine It should work remotely, you know all the problems of well, you have a mismatching Requirements or mismatching versions of some dependency like all of that should just not be a thing that they think about Once they are ready once, you know things start Shaping up they usually connect some of these steps together. Maybe somebody else in the team wrote You know a task that queries the data that I need I can just use it and connect a few of those and you know end up with a workflow And you want to then run that in again a remote environment Reliably that can scale that can do things like paralyze my the steps that can be paralyzed Without me having to think about that too, right? I'm just running if I'm running in Python Python is like single threaded. I shouldn't have to do additional work to then you know make it a parallel Get into parallel execution optimize it this way it should just work You should also be able to Promote the successful workflows, right or things that produced the artifacts That you can you deem, you know goods maybe through running other tests and so on You should be able to promote them to production just like we do with services You know, you're deployed to staging environment and you're like Multiple versions and the version that passes all the end-to-end tests integration tests and so on you promote that to production You should give you the same semantics, but again within an environment that looks familiar to them Once again those things happen, you should be able to run on a schedule Right, especially for data processing Pipelines we see that very often right data keeps coming in from external sensors from, you know External sources and you want to keep processing the data as they come in So you want to trigger those pipelines on schedules or based on events and you want to monitor them You want to get notified when things fail alerts and write like all of the convene all the things we take for granted As software engineers like they need to be offered for these pipelines as well And again the key point here is we should meet them where they are shouldn't ask them to like adopt all of these you know Different tools for to make this work And finally as things that you have more and more workflows running in production You will start, you know, maybe seeing failures for from schedules or maybe you want to do some introspection for You get some bad predictions and you want to figure out where where did things go wrong? You should be able to introspect any execution or any artifact and trace it all the way back to Ideally even the version of the table that you know came in that caused us to produce a model that produced this bad prediction and The platform should that this is where we started like that the platform should give you all of these tools as much as we can Without you having to do anything This is an example of Python codes annotated to be flight code So the there are three functions here. They're just no more Python functions. You write your logic in there The one thing that may be not It's currently optional. I guess in Python are types We do require types for the inputs and outputs. You see the pay multiplier in top here You have fixed two inputs produce one data frame We do require you to declare those and we think I know it's a Contentious point, but my take is any production code should really be strongly typed I know types are optional in Python and in many cases when you prototype you don't necessarily care about them But if this is code that you are writing to be, you know, Productionized I think they should be you should declare the types and flight uses the types in various other ways We'll we'll talk about in as the as we progress to ensure, you know tasks fit together and to ensure You know caching works and so on So once you have the your function, right? You can run it locally can write unit tests It's just a Python function. All you need to do is add this top annotation the add task And now it becomes a task a flight tasks now flight knows that this is a sort of an atomic Execution unit it knows that it can take this plus, you know, of course any other function it cool And run that in separate hardware send box environments It can run in parallel if it needs to it's like a you know, it's a standalone sort of function or task in our language And we wrote a couple of those and then the third one here again a function But we marked this as a workflow what does what that does It tells flights that for when you execute this workflow to the body here Don't really call the tasks, right? So we you see me calling pay multiplier and total spend It will not really call these functions. All it will do is it will record That's you want to call these tasks. This is the data flow You want to pass the inputs that come from You know the workflow are sent as inputs to this task and the output of this task is sent to this Right, so it's it builds up the tree of the graph or the DAG based on Executing the code you write here and yes in this example, it's just a one line But this can be arbitrary complex And we will just execute that once Statically with no inputs to understand the graph of execution and from that point on With it gets transferred into our own representation of graphs We use protobuf to represent the typing and the graphs and all of these information And it enables flight to be targeted through different SDKs We started with Python but Spotify contributed the Java SDK and a scholar SDK And you they can all interrupt, right? So some people write like a spark Java task to process things But then their teammates write Python tasks and Python workflows and they call this Java task This is they are called all completely addressable and uniquely addressable and run in complete sandbox environments So we don't care about your you know different Requirements or dependencies versions. This is all completely isolated and personalized In this example everything here is going to be in one container. So you will care but But yeah in in a real environment these things could be spread over multiple GitHub repos like it just completely independent on each other And then lastly even after you know marking things as this you can still Obviously call them as Python functions because they are Python functions So you can write, you know, you can use py test frameworks and like all the testing you can do Locally in Python so you can add as many checks as you want for you know For anyone else who comes in and will revise this code to make sure, you know it behaves as you expect it to give in the inputs and There are a couple of Nefty features here you can add on top right? There's this on top I added cache equals true to this one task And this is me telling flight that I know this task is deterministic I know the behavior is deterministic if I pass it, you know one and two it will always produce three kind of thing And that enables flight to automatically cache the outputs or memorize the output of this task For giving inputs and outputs and given signature and so on So if somebody else in my team or in the company calls exactly the same task With the same version with the same inputs, I will not run it again flight will not run it again It will just say well here's the output somebody else, you know Saved you the time and and ran this and again all of this is tracked So you can always go and see well which execution exactly produced like ran the first time For this input and you can go there and look at the logs and all of that. So it's all tracked in the system Once, you know things run locally and you are happy with what you see And you want to maybe run in a remote environment with more resources We give you, you know capabilities to define or ask for more resources for given tasks Maybe one task needs GPUs the other tasks don't need that So you don't really need to be paying the cost of a GPU machine if you are running code that doesn't need GPU So you can isolate that part into a task and just say for this part. I need GPUs you can also The second one here to the spend I converted this into a spark task All you had to do is say well the task config is spark And flight will take care of or the spark plug-in in flight will take care of initializing or setting up a Spark cluster for you controlize spark and Initialize the spark context and the connectivity and all of that and then your function will start running And you will have that spark context if you you know need it in this case I it will automatically convert. We also have type transformers that will automatically convert from You know appendice data frame to a pie spark data frame So you don't have to do anything you just take this and start running your code Your spark code right here And you can see I still use it exactly the same way right I still am calling total to spend in the workflow Exactly the same way nothing changes here, but instead now it's a spark task and you can do all the map reduce Magic that spark lets you do And finally at the bottom we run we have this concept called launch plans most plans are That can overlay on top of a workflow where you can define certain behavior for certain inputs You can also define Schedules you can say we'll run this every hour on the hour or you know, you can have scrum schedules or Fixed rates you can have notifications when things fail so you can integrate this into your existing maybe Incident management systems and maybe slack notifications email locations all of that It will integrate well into your existing infrastructure and Finally flight also Integrates well into your existing github's tools right if you have a CI system And you want to maybe at the end of after merging a new workflow into you know You the github repo you want to kick off the run of that workflow. You can you know use this flight CTL cube cuttle inspired CLI That can do pretty much everything like the API layer in flight Exposes as you can create exclusions register, you know, all of that you can wait for exclusions Like consume or download the outputs of exclusions. You can do exactly the same thing with Flight remote the middle here. This is a Python library that just is a wrapper on top of the again the API So it lets you kid interact with our back end Little bit nicely than just calling, you know rest or gRPC endpoints So you can script it yeah, we have people use this in in other Jupiter notebooks To you know script some interactions with or schedule some interactions with with our back end Also have a UI and I wanted to show a couple of screenshots. It looks very low resolution from here So on the top left here that once you register a workflow with the back end You can see a rendering of our understanding of the execution graph So you can tell which parts were running in parallel and which parts will have dependencies on other parts And how the inputs and how the data is flowing between these You know execution units on the bottom left. This is the Like home page of sorts for a workflow or a task. There's a histogram that shows you You know the past few runs how long they took and whether they succeeded or failed is a list of versions So every every change you make to a task or all flow is tracked as a separate version So everything is immutable and that's that enables us to always be able to go back to the exact Version of the code that produced, you know certain artifact And and that's obviously applies to all of your new dependency tasks and everything else you call On the right here is a launch form so you can launch, you know executions also from the UI And this is you know auto-generated One of the users of the inputs the input types we you know ask users to add in So we can render the rights like controls for for these inputs, right? If it's a Boolean will you have a toggle if it's a string you get this There's one foot arrays and so on and this is also pluggable You can enrich this if you have you know new input types Once you run or you start an execution you get a Big graph of you know, what's happening and you can see how much is being what the progress is what tasks succeeded what failed That you can see there are like boxes inboxes here because this is one of the more complex graphs we have that That uses Composition right so we have a workflow that's calling other workflows It's calling other workflows and with like branching and if conditions and so on and the UI is able to like render the nesting Level multiple nesting levels here. We are experimenting with a few different ways of rendering the nested graphs that Because this looks a bit more complex than you can you know easily Understand but but you know will feedback is always welcome. So let us know When things go bad and as they you know Will at some point or another flight also tries to pull in the logs looked traces Stack traces or as much information as we can up bubble that up in the UI You can get exactly the same information obviously from the CLI or you know, you were the library I showed you the remote library So we try to make this as actionable as possible You know, if it's an image pool failure from Kubernetes, you will see that right up here Whatever the actual error is bubbles up all the way to the top layer in the UI and you will just see that right in front of you and these are just some of the Features I wanted to share that we hear here quite often that you know people like using once they start using the platform It sounds like there are a few people here who are more on the infrastructure side We'll be happy to share more details about how these things run or deployed afterwards, but But I want to take a second and just share what Dylan heard from his own customers right within the Within Spotify about how things are going with flights So let me Go here Really quickly. I thought this slide was fun Why did we pick flight? This is actually Written by our data science team. So this is not from us, but we think it's really cool Because as engineers a lot of this might be kind of table stakes for us But for the data scientists being able to get in up and running on flight and getting all of this stuff for free Has been a really big win for them and they've been really excited about it You know the ability to share models with each other and compose things easily Out of the box parallelism. I mean again may not seem like the biggest deal But for them when you're writing Python scripts and everything runs and takes a certain amount of time Whereas now for free we get parallelism across tasks. I think they think that's really cool the caching Just connectivity with GCS all of this stuff They've been really excited about it Yep, so we talked about composition. Yeah, you can call, you know workflows from one another You can share we haven't really talked too much about this but everything in the system is tracked and addressable globally addressable within a deployment and You can other people can start using your tasks and workflows One of the teams we worked with they their infrastructure team of platform team built You know one flight project with just Common tasks that everybody else uses Things like you know query table blah with you know dates or you know things like that In Paris and as Dylan talked about it caching we talked about in storage and yeah compile time validation that we are Also very big. We feel strongly about that that most of the errors you get Should really surface as early as possible So you get you know type checks Like he does this task produce a type that can the next task can consume or not You know things like that. We try to surface that as early as possible Just a couple more things The if you have a MacBook might be the easiest way to just try flights You can brew install flight CTL and flight CTL sandbox starts will give you a single Container that starts up a cake a 3s cluster with all the flight components running You have a server You know you can play with UI and you can run start writing flight code and against Start with flight work can show you a very simple like a lord examples. You can use and Lastly October 1st. It's a an event Happens in October for a lot of open source tools to to ask, you know the community to contribute We have I'm fine, you know good first issues kind of thing you can play with and October fast flight at org is you know where you can go check out what issues are available and start you know contributing and Coolest thing is you will win swags, so I know you know I know we had probably enough swags from the conference, but you know, there are swags who can say no to that So go check it out and that will be all I will be happy to take your questions now Oh Thank you Say again streaming data do we handle streaming data? Not natively But we one of the one of our customers wrote a flink plug-in for flights so and It lets you do that But it doesn't so so that I guess the question really is can can you execute these workflows? In a stream or can it consume a stream and just run the workflows, right? The execution that requires workflows to run in you know seconds, right? Very quickly in overhead kind of situation and most of the workloads we saw run in in Containers and there's always the container startup runtime and so on so at the moment the answer is no But but it is something we are thinking about how to how do how can we integrate well with streaming Solutions and how do we offer more importantly? How do you offer you sort of a unified dev experience? Yes Yeah, so Are the to repeat the question are the task execution environments are they just individual containers? Can they be more than one? Right that the question. Yes. So this this behavior is Controlled by plugins. So even the single task like I demonstrated Runs through a plug-in that couldn't what we call it a pod plug-in. So in in Kubernetes world will run as a pod But we have plugins that do the distributed pytorch right and that starts up a couple of forgot what but like sort of master nodes and Cluster right and it distributes the data that way and does the training So there are different spark also starts driver pod and some Executor pods So depending on the plug-in the environment will look different But we do take care of annotating and tracking the resources created by them So we make sure things get cleaned up And we make sure when we have retries. That's another feature. I did not talk about you can declare retries on individual task level and Flight make sure you start from a sort of a sandbox environment. We have the data Separated right so like the next retry will not sort of Read Like corrupted data because of the previous retry, you know things like that So we we do a lot to make sure these start up individually, but but yeah, they can be arbitrary large number of containers Yes, this session has ended. So if anyone has questions, they can come directly and see our speaker But otherwise you're welcome to go to your next session. All right. Thank you


discretion is a thread running through the whole of part 4 of the bill, consistency and certainty are fundamental to effective enforcement and to gain public trust in the fairness of that enforcement. Allowing discretionary powers for local authority enforcement officers to permit pavement and double parking in undefined circumstances would be far too subjective and approach and in my view would threaten to seriously undermine the policy intent of a national ban and public acceptance of it. Finally, Jamie Greene's amendment 309 seeks to require the Scottish ministers to consult with local authorities and other persons as they consider appropriate when modifying any of the exceptions in section 47. As the committee will be aware, the Scottish ministers ensure that all local authorities and interested groups have been consulted via the parking standards group, which was set up during the consultation process for the parking provisions in the bill. That group is continuing to meet regularly to consider the parking standards guidance and the Scottish Government is fully committed to that process. I am not persuaded that a statutory consultation duty would add anything to that well-established process. As I mentioned at the outset, the many issues raised by the amendments in this group are important. I am grateful to members for their careful work in bringing them forward and for their contribution to this debate, but, for all the reasons that I have set out, I can only support the amendments in this group lodged by Mike Rumbles. If those are pressed to the vote, I would urge the committee to support them too, and I would invite other members not to press their amendments in this group. If those amendments are pressed, I would ask the committee to vote against them. Thank you, cabinet secretary. Can I ask Jackie Baillie to wind up please and press or withdraw your amendment? You will be pleased to know that I do not intend to respond to every amendment in the group. I think that that would test the committee's patience somewhat. I note the cabinet secretary's comments in relation to amendment 4. He seemed to suggest, if I picked him up right, that the provisions already exist and therefore there is no need for my amendment. That being the case, could I practically make a suggestion that he is likely to be providing guidance to local authorities and the police about pavement parking? If he would include in that guidance reference to the question of over-parking, I would be content to not press that amendment. I think that that is a practical solution. Thank you very much, cabinet secretary. That concludes my comments, convener. I am not pressing. As Jackie Baillie wishes to withdraw her amendment 4, can I ask if any member objects? No member objects. Therefore, the amendment is withdrawn. I call amendment 1 in the name of John Mason already debated with amendment 4. John Mason to move or not move? Not moved. Thank you. Amendment 116, in the name of Graham Simpson, is not moved either. Therefore, that takes us on to amendment 287. Therefore, the question is that amendment… I think that I have to ask that. Yes. Sorry, who has moved that? Oh, sorry. As to ask if amendment 287 is to be moved by Mark Ruskell, I think that you are going to do that, Ms Finnie. Mark Ruskell does not wish to move amendments 287, 288 and 289. Thank you. Therefore, the question is, I call amendment 290 in the name of Mark Ruskell already debated with amendment 287. Moved or not moved? Moved, convener. Therefore, the question is that amendment 290 be agreed. Are we all agreed? We are not agreed. Therefore, there is a division. Those in favour, please raise their hands. Those against, please raise their hands. There are five votes, four, six votes against. Therefore, amendment 290 is not agreed. I call amendment 291 in the name of Mark Ruskell already debated with amendment 287. Mr Finnie moved or not moved? It moved, convener. The question is then that amendment 291 be agreed. Are we all agreed? We are not agreed. There is a division. Those in favour, please raise their hands. Those against, please raise their hands. There are five votes, four, six votes against. Therefore, amendment 291 is not agreed. The question is that section 42 be agreed. Are we all agreed? Yes. Therefore, I call amendment 292 in the name of Jamie Green already debated with amendment 4. Jamie Green to move or not moved? Not moved. OK. I call amendment 293 in the name of Jamie green already debated with amendment 4. Jamie Green to move or not moved? Not moved. Therefore, I call amendment 117 in the name of Colin Smith already debated amendment 4, Colin Smyth, to move or not move. The question is that amendment 117 be agreed, are we all agreed? We're not agreed. Those in favour, please raise their hands. Those against, please raise their hands. There are two votes for, there are nine votes against, therefore amendment 117 is not agreed. I call the amendment 294 in the name of Jamie Greene already debated with amendment 4, Jamie Greene to move or not move. Therefore call amendment 295 in the name of Jamie Greene already debated with amendment 4, Jamie Greene to move or not move. Amendment 118 is not moved and therefore I ask if we agree section 43, are we agreed? We are agreed. Amendment 119 is not moved and therefore the question is section 44 be agreed, are we all agreed? I call amendment 296 in the name of Jamie Greene already debated with amendment 4, Jamie Greene to move or not move. Therefore call amendment 297 in the name of Jamie Greene already debated with amendment 4, Jamie Greene to move or not move. Therefore call amendment 120 in the name of Graham Simpson, which he is not moving. Therefore, the question is that section 45 be agreed. The section that 46 be agreed. Yes, just to be clear, amendment 121 in the name of Graham Simpson is not moved. Cabinet Secretary, just please, I wondered if, without being rude, I could ask you if you are the only one speaking on this group, I believe, unless members wish to speak which they may well do. Could you give me an indication of how long you think it would be to put your points on this? Three minutes. Okay, then I am going to press on and I'm going to call amendment 122 in the name of the Cabinet Secretary, group of amendments as shown in the groupings. I would point out that amendment 129, not already debated in previous group, has agreed to, if it's agreed, I cannot call amendment 130. Cabinet Secretary, can I ask you to move amendment 122 and speak to the other members in the group? At this committee stage 1, report expressed concern that the issue of parking across drop kerbs at pedestrian and other recognised crossing places was not included in the bill when it was first introduced to Parliament. Evidence from stakeholders highlighted that parking at drop kerbs is perceived to be a significant barrier to accessibility in many streets. As you will know, I consider inconsiderate and obstructive parking a serious problem for everyone, which puts the safety of pedestrian and other users in jeopardy. As explained at stage 1, we have received powers via the Scotland Act 2016 to legislate on parking at drop kerbs. However, we need to be clear that the impact of introducing such a ban in urban areas and to explore whether that could be introduced via secondary legislation. We have listened to reviews of the committee, parliamentarians and stakeholders, who have highlighted the wider impact that the issue is having on vulnerable road users, as well as the local economy. Amendment 141 prohibits the parking of vehicles on dropped footways. That encompasses both where the footway has been dropped and where the carriageway has been raised, where the purpose of either is to assist pedestrians or bicycles across the carriageway. Amendment 142 makes it clear that the new parking prohibition does not apply to kerbs that have been dropped for the purposes of accessing driveways or garages, both residential and commercial. The ban will also not apply where the vehicle has been parked for the purposes of saving a life or responding to a similar emergency. Amendment 144, 147, 149, 151, 154 and 156 make provision for the implementation and enforcement of the new prohibition to match the existing prohibition on pavement parking and double parking already in the bill. That includes enabling local authorities to issue penalty charge notices when motorists have contravened the ban. Finally, the remaining amendments in this group all flow from the new prohibition. Amendment 122, 123, 125, 127, 130, 132, 135, 136 and 137 are to make it clear that the exception to the parking prohibition outlined in section 47 of the bill only applies to the pavement parking prohibition and the double parking prohibition, not to the new prohibition. Amendment 157, 156 respectively provide a definition of drop-loop footway parking prohibition for the purposes of this part of the bill. Therefore, I ask the committee to support all of the amendments in this group, and I move amendment 122. Thank you. Does any other member wish to speak in this group? Cabinet Secretary, I'm not going to ask you to wind up. I'm going to move straight on on the basis that you will have said all that you want to say. Just say to members that there are a series of votes now, and once we have completed those votes, that is where we'll be stopping. I'm going to go through them carefully to make sure that I get them right as we come to the end of a very long day. So the first question is that amendment 122 be agreed. Are we all agreed? I therefore call amendment 123 in the name of the cabinet secretary already debated with amendment 122. Cabinet secretary, can you move it formally, please? Moved. The question is that amendment 123 be agreed. Are we all agreed? I therefore call amendment 124 in the name of Mike Rumbles already debated with amendment 4. Mike Rumbles to move or not move? Moved. The question is that amendment 124 be agreed. Are we all agreed? I therefore call amendment 125 in the name of the cabinet secretary already debated with amendment 123. Cabinet secretary, to move formally. Moved. The question is that amendment 125 be agreed. Are we all agreed? We are agreed. I therefore call amendment 298 in the name of Jamie Greene already debated with amendment 4. Jamie Greene to move or not move? Bear with me. Not moved. Thank you. I therefore call amendment 299 in the name of Colin Smyth already debated with amendment 4. Colin Smyth to move or not move. The question is that amendment 299 be agreed. Are we all agreed? We are not agreed. Therefore, there is a division. Those in favour, please raise their hands. As we get closer to the end of the day, committee members, could I ask you to raise your hand clearly and with purpose to avoid confusion? Those in favour, please raise their hands. Thank you. Those against, please raise their hands. There is one vote for, 10 votes against, therefore amendment 299 is not agreed. I call amendment 126 in the name of Mike Rumbles already debated with amendment 4. Mike Rumbles to move or not move? Move. The question is therefore that amendment 126 be agreed. Are we all agreed? We are agreed. I therefore call amendment 127 in the name of the Cabinet Secretary already debated with amendment 122. Cabinet Secretary, can I ask you to move it formally, please? The question therefore is that amendment 127 be agreed. Are we all agreed? We are agreed. I therefore call amendment 300 in the name of Jamie Greene already debated with amendment 4. Jamie Greene to move or not move? Not moved, can you? Thank you. I therefore call amendment 301 in the name of Jamie Greene already debated with amendment 4. Jamie Greene to move or not move? Not moved, can you? Amendment 302 in the name of Rachel Hamilton is not moved. Therefore, call amendment 128 in the name of Mike Rumbles already debated with amendment 4. Mike Rumbles to move or not move? Move. Thank you. The question therefore is that amendment 128 be agreed. Are we all agreed? Yes. We are agreed. I therefore call amendment 129 in the name of Colin Smyth already debated with amendment 4. Colin Smyth to move or not move? Despite Mike Rumbles being a passionate advocate of this throughout the entire process, I will not move it and I am sure that he will be disappointed that he will not have an opportunity to follow through on his previous support. I therefore call amendment 130 in the name of the cabinet secretary already debated with amendment 122. Cabinet secretary to move formally, please. The question is that amendment 130 be agreed. Are we all agreed? We are agreed. Therefore, I call amendment 131 in the name of Mike Rumbles already debated with amendment 4. Mike Rumbles to move or not move? Move. Thank you. The question therefore is amendment 131 be agreed. Are we all agreed? Yes. We are agreed. Therefore, I call amendment 303 in the name of Jamie Greene already debated with amendment 4. Jamie Greene to move or not move? Move. The question therefore amendment 303 be agreed. Are we all agreed? We are not agreed. There is a division. Those in favour, please raise their hands. Those against, please raise their hands. Thank you. There are four votes. There are seven votes against. Therefore, amendment 303 is not agreed. I call amendment 304 in the name of Colin Smith already debated with amendment 4. Colin Smith to move or not move? Move. I therefore call amendment 305 in the name of Colin Smith already debated with amendment 4. Colin Smith to move or not move? Move. I therefore call amendment 132 in the name of the cabinet secretary already debated with amendment 122. Cabinet secretary, can you move it formally, please? Move. The question therefore is amendment 132 be agreed. Are we all agreed? Yes. We are agreed. I therefore call amendment 133 in the name of Mike Rumbles already debated with amendment 4. Mike Rumbles to move or not move? Move. The question is therefore the amendment 133 be agreed. Are we all agreed? Yes. We are agreed. Therefore, I call amendment 134 in the name of Mike Rumbles already debated with amendment 4. Mike Rumbles to move or not move? Move. The question therefore is amendment 134 be agreed. Are we all agreed? Yes. We are agreed. Therefore, amendment Maen nhw'n gwybod hwnnw yn effiolion i ddechrau Cymru cwm ni ni ni ni wedi'i gwybod ei ddechrau eich Cymru, oedd dwi'n gwybod ddim yn ffrwng. DOedd gweithio y ddarhwynt a'i ddechrau'n gwneud yn dweud eich gwwn, roedd yn dweud, a'n dweud o'r ddweud o'r ddweud. Rwy'n dweud am Fyll diffniau Cymru, a'i ddweud o'r ddweud i ddechrau Fyll, jamey greasu, wrth mawr yn ei gweithio ddiwethaf. Ym mwrth gyntaf? Rwyf ym mwrth gyntaf yma. Rwyf ym mwrth gyntaf yn ddeichydd, rwyf ei gweithio gyd dim. Rwyf i'r gweithio'r ddweithiau, jamey greasu, wrth mawr yn ei gweithio i amendment 306. Rwyf i'r gweithio, rwyf i'r amendment 136 i hynny y mae'r cabinat cyfisio. Cabinet Secretary, can you move it formally please? Moved. Therefore, the question is, amendment 136 be agreed, are we all agreed? Yes. We are agreed, I therefore call amendment 307 in the name of Jamie Greene, already debated with amendment 4. Jamie Greene to move or not move? Not moved. I therefore call amendment 137 in the name of the Cabinet Secretary already debated with amendment 122. Cabinet Secretary, can you move it formally please? Moved. The question therefore is amendment 137 be agreed, are we all agreed? Yes. We are agreed, therefore I call amendment 138 in the name of Mike Rumbles, already debated with amendment 4. Mike Rumbles to move or not move? Moved. The question therefore is amendment 138 be agreed, are we all agreed? Yes. We are agreed, therefore I call amendment 139 in the name of Colin Smyth, already debated with amendment 4. Colin Smyth to move or not move? Not moved. Thank you. 140. 140. Hold on. I therefore call amendment 140 in the name of Mike Rumbles, already debated with amendment 4. Mike Rumbles to move or not move? Moved. The question therefore is amendment 140 be agreed, are we all agreed? Yes. We are agreed, I therefore call amendment 308 in the name of Jamie Greene, already debated with amendment 4. Jamie Greene to move or not move? Not moved. Thank you. I therefore call amendment 309 in the name of Jamie Greene, already debated with amendment 4. Jamie Greene to move or not move? Not moved. The question is that section 47 be agreed, are we all agreed? Yes. We are nearly there, committee members. I therefore call amendment 141 in the name of the Cabinet Secretary, already debated with amendment 122. Cabinet Secretary to move formally. Please. The question is that amendment 141 be agreed, are we all agreed? Yes. Therefore, I'm not going to call amendment 143 because it's not moved. I call amendment 144 in the name of the Cabinet Secretary, already debated with amendment 122. Cabinet Secretary, can you move it formally please? Moved. Moved. Moved. Moved. Moved. Moved. Moved. Moved. Moved. Moved. Moved. Moved. Moved. The question therefore is that amendment 144 be agreed, are we all agreed? Yes. We are agreed, and therefore the good news is that this is as far as we can go, hold on let me make sure I get this entirely right, this is as far as we can go today. We will continue next week. I would like to thank everyone, committee members and those people who have been attending oeddaeth hynny ar hyn o'r ddweud o'r seглиodau o'r ddweud. Roedd gennych hyn o ran ar meddwl yr oedd Diolch yn mae'r ddweud yn sgiliau. Roedd gennych hyn o ran o'r seглиodau o'r ddweud o'r ddweud o'r ffioedd... Gwm mwynt yng Nghymru. Roedd gennych hyn o'r se opacity i ddweud o'r ddweud yr oedd, roedd gennych hyn o'r se patio gyda hiwymiadio yn bobwysig i Hollwyddon Orange i Elm ag�ion Llywodraeth? Balwydden, rydym eich cyfffyngad, oedd yn fblwyddynfaCSL a family wedi dwyn y cychwyner i Llywodraeth, wrth fyowejad, yn gwybod i fy ngy encontrar i ym incorrectly a mag education phryscaid amortalisederon, ond mustulion a'in fy efectio i bywydau ystyried. Rwyf yn ddeu入yd isnach a'r i dyfodol mwy oedden yn fwy. Rwy'n fawr iawn i'r bobl, oes fawr i'r drwng i ddysgu waslawyddio ar gyfer amser. Ar draws, rai'r mwr yn fawr. Rwy'n fawr, wrth gwrs, rai'r mwr yn cael ei fodfawr, ar yr amser. Rydw i'r ddechrau rydw i'r grannodau agor yma. Rydw i'r ddechrau'r mwr yn cael ei fodfawr, ac yn ôl yn cael ei fodfawr, ac yn cael eu bodfawr yn cael ei fodfawr. Oes hyn amser o cwbl ond? mawr y byddai bwyd y llwedd gwahaniaeth y ffordd o'r arddangol yng Nghymru? Ify, mae'n gwanfaeth y ffordd yn teimlo o'r tyg ffordd, wedi'i fel ddydliadol a'r byd, mae'n gydig? Gwylech ar ddweud, mae'n trwy. Dwi'n fwy cantyniadau a nhod ddangos o'r cyffin. Rwy'n gweithio. Rwy'n gweithio, mae'n gweithio. Rwy'n gweithio gynnydd yn ddwy ymwysig. Dyna sy'n gweithio i ddechrau i'r gyffredinol, a gwnaeth ddim yn gweithio gyda'r cymdeithasol i gael amser yma'r cyfan. Rwy'n gweithio i gael i'r gyffredinol, Mr Laid.


With all the controversy surrounding Shane Dawson right now, I thought this was the perfect time to make a video about why you should be more like Shane Dawson to improve your mental health. Stay tuned to find out why. What's up everybody this is Chris from the Rewired Soul where we talk about the problem but focus on the solution. The other day I made a video about how to handle an existential crisis and here's a quick clip in case you missed it. I just laugh when I hear people talk about this existential crisis. I'm like wow like all you got to do is make your purpose about helping others and not only you're helping yourself but you're making this world a little bit better of a place. So when I made that video it was talking about how people are searching for this meaning this purpose right and I talked about how like my purpose is just to help people. It gives me something to work towards every single day and I think Shane is a prime example of that. Recently, recently he has done things that are just so inspiring to me. So let me let me lay down some groundwork real quick. Being a new YouTuber you know I've been at it about six months like it's rough especially with the uphill battle I'm doing trying to talk about mental health addiction you know all these like subjects that nobody really likes talking about so it's very uphill and you know I reach out and I've met a lot of fantastic people. So this is actually requested by my friend Chris from the Rewired Soul Soul. He does a lot of videos on mental health and things like that so credit goes or shout out goes out to him thank you for giving me this idea because I'm really happy with how it turned out so go check his channel out doesn't know I'm saying this but go check him out and tell him pink up and he sent you and I keep hitting the tree oh my god but like it it's difficult it's still difficult to grow and gain an audience and get your name out there and all that kind of stuff but recently like looking at people like Shane I'm like man like more people should be like Shane and not to help me out like I'm going to touch on this in a minute but not for selfish purposes but anyways like so those of you who haven't been tuning in to Shane's channel like so this guy Bobby Burns this dude Bobby Burns makes a hate video just straight up bashing Shane right bashing his conspiracy theories and Shane watches it hilarious video by the way him watching it but then he invites this dude out to his house so Shane's already had practice confronting people like yo like what's up let's let's talk this out like holy crap like if only more people could do that most people on this planet they're either super aggressive right or they're very passive aggressive like not just on the internet and the internet it's its own monster but just with the people in our lives right like you just don't you don't like Janet from accounting or you don't like that neighbor right and you do these like terrible things but Shane brought Bobby onto his channel and showed what it's like to just have this conversation and even though they didn't fully agree they came to terms and they developed this friendship but in the meantime while Shane was doing that he got to know Bobby a little bit more in his struggle and Shane was able to empathize with Bobby knowing that Bobby wanted to grow his channel and Bobby kind of had to do what he had to do and some of the videos he made was just blasting other youtubers just so it would get views and then Shane rather than holding on to this resentment towards Bobby Shane helped Bobby out and did some collabs and Bobby's channel exploded I was watching I think he was at about like 300k subscribers and now he's like almost doubled it right but even more recently and it's so disgusting and sad that this this other channel when they did this video that is accusing Shane they used Shane's most recent act of altruism to try to slander him but those of you who didn't see Shane was just chilling with his boyfriend Ryland and he came across a video of this amazing young woman amazing young woman on YouTube and he's sitting there he's like this girl's awesome why doesn't she have more views and just out of nowhere like Shane's just like yo I'm gonna hit this girl up and I'm gonna promote the heck out of her like she deserves this right so one of the one of the hardest things to teach one of the hardest things to teach to people and it's something I try to teach my clients every day is to get out of self-seeking so many of us our default mode is to only do things if we get something in return and it's this crazy kind of tug-of-war that we play with our fellow humans all the time like think about it real quick think about it like what did Shane really gain from bringing Bobby on his channel what did Shane really gain from bringing Sophie on his channel not much it was all for them you know and he just did it out of the kindness of his heart and you know what's amazing about it and this is the reason why I'm saying what you can learn from Shane Dawson check out this clip because this is exactly why so as you saw right there like do you see that did you see that look in his eyes did you see that feeling he got like he felt good he felt good about doing it like the way the brain works our brain is set up on this cycle to chase rewards like when you're reward when you realize that a great reward for your brain is to do nice things for other people just because you start to want to do it more and more and more and like it really sucks that you know Shane you know he got pushed a step back with the recent rumors and everything going on about him but like I don't even know if Shane realizes that he is progressing in his mental health which is something that I try to teach people at a drug and alcohol treatment center and Shane is doing it naturally he is giving without expecting anything in return and you know I felt it necessary to make this video because I don't think many people understand you know how important this is and like and with with 11 11 million subscribers on his channel like the inspiration and the message that he's putting out there like basically all summed up go out there do good things for other people don't expect anything in return like it's it's amazing it's amazing and a lot of people should be looking up to him so as I mentioned in my last video I know Shane's gonna get through this he has awesome support all day on Twitter I've just seen his fans tweeting out stuff and things like that so like I'm really impressed by with what Shane's been doing and if you're a fan of his like you know I hope that you truly appreciate everything that he's putting out there to kind of show you show you how you can become a better person too all right but hey like I'm trying to get Shane's attention and be like yo dude hey you're doing great right so if you're a fan of his and you stumbled across this video go ahead and tweet it at him I'm not trying to get no popularity off it I just want to help this dude out but I was telling somebody else on Twitter earlier like I don't really care if he sees this or not you know if if people just randomly come across this video or even my current audience comes across this video I hope they check out his channel and you know what I'm actually going to link it on the end screen so I'm just here purely purely purely to try to help as many people out with their mental health as possible all right but anyways if you like this video please give it a thumbs up and if you're new here all the videos on my channel they're meant to help you out with your mental health I also do some stuff about addiction recovery so make sure you hit that little round subscribe button so over the left of me there is a link to Shane Dawson's channel if you want to check out some of the videos that I've been talking about if you haven't seen them or you can click or tap on that thumbnail check out another video on my channel thanks so much for watching I'll see you next time


Going on everyone Sam here with late sports cards. We've been one box of 23 tops definitive baseball hobby for Niko C Good luck here Niko. Let's do it buddy Thank you, let's go come on Actors of the plate or Ooh, that's sick 17 of 30 Trevor story game used city connect. That's awesome Grats on that Niko Ever story game use city connect J-Ram that is gonna be at 38 or 39 a 50 on the helmet relic game used helmet Relic s1 there. Thank you Eric picking up the boils in a break tomorrow That's pretty sweet 22 of 25 is Christian yellow On the patch auto three-color game use patch 22 of 25 Rookie auto of Alec Burleson 11 of 50 for the Cardinals Burleson, hey, it's Kyle. That is Dennis Ackersley 40 for the eight game use Jersey auto nice one coming up here Mmm, that is gonna be 9 of 15 for the Yankees mr. Aaron judge Congrats on that one there Niko 9 of 15 of the captain Aaron judge Sam action here. Oh, yeah That one mag for you as is a sandbox for sure followed by a Or an Anthony Rizzo 21 of 25 for the inks recolored game use patch Anthony Rizzo W Riz and then we've got a defining rookie patch autograph card green parallel of Grayson Rodriguez Nice one there. Congrats on that That'll do it for your personal there Niko. Thanks again for the support buddy get him right out to my man


Welcome folks. This is Tom O'Brien a TFNN. We have five days a week. We go seven hours a day We go 24 hours a day in the internet at TFNN.com Always remember folks, whatever you think about you bring about whatever you focus on grows up Everyone's having a great day safe day. Let's make a great week folks to begin a great relationship. Know what you want Know what the needs of your body are and what the needs of your mind are and what fits well with you There are millions of men and women some of them make a good match for you and others won't the two of you only need to be like I'm cool tealock a match that works My advice, let's take a look at it out here. We have the now industrials down 76 Nasdaq's off 56 S&P's down 14 gold contract trading up Two dollars 70 cents at 1706 an ounce. We have silver up 17 cents 18 dollars 67 cents an ounce lights recruit up five bucks 102 48 notes and bonds the 10-year note down six ticks trading one 1814 the 30 year down 28 at 139 05 and King dollar King dollars down 733 ticks trade at 107 330 You're always 101 yen is that one 38 British pounders at 119 to one US dollar Have phone numbers eight seven seven nine two seven six six four eight It was call folks. I know what's going on in your world the world of the S&P's Let's take a look at them. What do you have you have the spy got up to 389 you tried trading a 383 couldn't hold price This is though how you make actually a longer term bottoms folks So this is going to be really intriguing my take is that we're going to get a heck of a bounce The reason I'm saying that is that you know first off we you know, we kick this baby off. We we get on hard on The 17th of June we went straight down from the you know, March 29th. We come back down again Tested rejected come back down again tested rejected back down again tested rejected that's saying a market wants higher price This in particular today is really cool. It was really deviant I mean and the cool part about it folks is that this is what normally markets will do when they want to go higher and The deviant part about it is it's very unusual when you can have Europe hold price And we don't have hold price Europe is in a lot more situation. We are folks So I kind of like the setup. I actually do like the setup because of all those deviations that are inside it Gold gold contract once again sold off as it got up to these 17 22 area We holding out up to box 143,000 contract You're gonna need a lot more contract volume than that and it's gonna take us some real strength to get back inside this 1730 area now that being said The dollar and this is the one to keep your eye on folks. Okay, the real question is gonna be How much further will the dollar go lower or is this like a one-day window? You know what I mean that it pulls back 727 ticks We'll see, you know the top of the strength You know the dollar the dollars had quite a bit of strength period, but on the 5th of July That's when the the dollar went up by 1700 ticks Okay, well the top of that is the 106 792 and this held that today It actually didn't even get to that point. It's it could trade it changed at 106 892 Not that it went up a lot, but bottom line It was it was enough that the market itself was saying okay You're gonna go back up on me because you go back up me man I'm gonna sell this market off as quick as I can and you're gonna see the correlation is direct the low of the dollar was Established at 11 o'clock this morning It's been trying to go up since then and each time to that each tick that that dollar goes higher the bottom line Markets go lower and the story Some of the high volume equities out here. What do we have? We got advanced micro right now up 58 cents Apple's down to 60 getting video up three bucks. We have Tesla up $6 Freeport Mac brands up a buck 84 Let's go look at the carpet contract because this carpet contract you talk about having you know Some real volatility man. This thing is like wild so up seven and a half pennies out here today It's been a straight line move down, you know for the last month from 458 a pound Hit a low on Friday at 313 a pound I will see you get some track to traction here Let's possibly get some traction. This is the first day up. Let's get over to the oil contract We take a look at the oil contract oil contract trading up 473 you're at 102 132 71,000 contracts. That's not a lot of contract volume. That's for sure get the price going with it Now one oh Yeah, this is good. It actually gets guys getting by ice man one one oh one fifty-three is ice So that's saying that this thing can you know get up there into the 111 it's gonna be really hard. It's digging into that monster bar That's when we we had come down $14 in one day that we came down from the 111 to the 97 area We'll see how that's gonna basically shake out. Let's go take a look at the Amazon the king dog out here and see what that's doing after You had the Prime day so Amazon start pushing with some volume Friday giving up today 11690 it went to 117 23. Oh, this is cool. Okay, so you're at 45 million chairs versus 57 million That's not that bad We'll end up doing probably around 50 million out here today and that's gonna be enough to bust the swing point We know we get over the swing point today hasn't held price But that's gonna be enough to get over it and if we go to the SMH is what you're gonna see folks You've heard me say this many times the SMH just drive you up drive you down Drive you all over the place bottom line the SMH is today got to a higher high now The difference is the SMH is gonna have volume in it the swing point There's 4.47 million we're at 3.4. This is still gonna be building a little more cars on Friday We did the 3.8 today or it's 3.4 and we need Maybe like 4 4 no 4.4, so you know we're not gonna get that in an hour But we're gonna probably get a 3.8 or something which isn't bad because the first day That only had a 2.7, but then it came down to 4.4 So in that context you want something like in a 4.2 Somewhere around there, so it's eating some of that supply line.  We have gold out here at 1706 silver at 1865 You stay right there folks to become back with our mammoth to Steve Rhodes come right back


OK, so let's get started. Welcome to lecture five of Tiger Tools. Today we're going to talk about program introspection followed by package management. And after a break, we'll talk about less customization followed by remote machines like SSH and things like that. So yeah, to start off with program introspection, the kind of opaque title. But what we're talking about here is understanding a program, like debugging a program. So one technique you can use for debugging programs is print depth style debugging. You have a program, something's going wrong somewhere, and so you stick a bunch of print statements all over the place just to kind of know what's going on. Like you print out values and variables, things like that. And that's actually an excellent debugging technique. But sometimes it isn't quite good enough. And that's when you bring out more powerful tools, like debuggers. So debuggers let you interact with the execution of a program. Don't worry about reading this code for now, but this is the program we're debugging.  And then at that point, you can, once the program's frozen, poke around it, what's in memory, print out values and variables and things like that. And you can even do other sophisticated things, like execute the program one line of code at a time, getting to stop after every line of execution so you can poke out what's in memory and things like that, just to inspect the state of the program. You can inspect values and variables and there are all these other advanced features that debuggers offer. And so, basically we're going to go through a demo of GDB, the GNU Debugger, which is a debugger that supports many C-like languages. And this is just to show you what kinds of things that debuggers use for. And then after that, I'll briefly show you some other debuggers, one for Python, and then show you graphical debuggers in the context of debugging JavaScript programs in the web browser. Okay, yes, so to start off with, we're going to be looking at this program over here on the left. Now you may be familiar with C, you may be not familiar with C. It doesn't really matter. This is a really simple program that the product execution runs main. And what this does is it loops through the integers i equals one to 10 and calls this function save with the integer i as an argument. And I've compiled this program already. And if I run this, it will just print out the integers one to 10, just in tech form. This is kind of an interesting program. It doesn't really have any bugs, but we're going to demonstrate debugger features in the context of this program. So the way you use GDB with C programs is when you compile, you go special flag to the compiler to get to include extra information in the binary that the debugger will use to present you, well, more information as it's running. And so that's done with the dash G flag for DCC, for example. And depending on your environment, depending on what compiler you're using stuff, this might be slightly different, but the general idea is the same. Like when producing the final binary of the executable in the code, normally you want to strip out all this extra information like what line number corresponds to what instruction in the code or things like that. There's just extra stuff that makes the binary larger. But when you're debugging a program, you want all that stuff there so the debugger can use of it. And so here we pass the dash G flag and so if you want to output to the file example and then compile example.c and we'll run this. And okay, now we have a binary example that we're going to debug. So the way we invoke the debugger is just called gdv with the name of that file and it prints out a bunch of stuff. Basically we get a gdv prompt. And now we can do some things like run the program. The transfer that is just run and we see like, okay, it does the thing and prints the output we expect. So now to show you some of the more advanced functionality of the debugger that gets a little bit more than just print out style debugging. So one thing you can do is you can get execution to halt when it reaches a certain line. And you can do that in terms of line number or you can even do it in terms of specifying names of functions. So you can say, okay, when I run this program I want it to start running and as soon as it hits main I want it to stop so I can do b for breakpoint main. And now I see like, okay, I've set a breakpoint. This is the address of the function in the file example.c on line 24. And now if I run this program what will happen? It'll start running and then as soon as execution reaches the point where I set a breakpoint the program halts execution and the debugger returns me to this debugger prompt where I can now interact with the program. So like now I can do things like print out states of variables and things like that. So I can try to print i and it's like i is zero right now because it's actually, well, in this case, referring to a location on the stack has not been set to one yet. I'll show you a little bit more of a printing in a moment, but I'll show you one other type of breakpoint. Here we did a breakpoint based on the name of the function. We can also say that when we reach a certain line number in the code we want to stop execution and give us our debugger prompt. So we can say breakpoint example.c and this is line 18, so I can say okay, when you reach line 18 start running. And I'll show you another debugger command. If I type it c for continue, I can even type in the full thing. This means resume execution when I've stopped execution or paused execution. So now the program keeps running till it hits any breakpoint I've set. If I do info breakpoints, it'll list all the different breakpoints I've set. So here I have one breakpoint, the first one I set in main. So that's not the one that triggered it this time. This time what triggered is the breakpoint I set and say not when I set by giving a line number example.c of i18. And so now my program's run until this point and the first time it hit that line and the program now is halted and I got this debugger prompt again. And now I can do things like inspect the arguments to say I can do print i and since this is the first time it's called it will say okay, like i is equal to one and so on. And now at this point I can do stuff beyond just inspecting values and variables. Like this I could have done by sticking actual printout statements in here, right? I could have put in printout i equals something like that, right? And I could compile that and run my program and it give me some permission about the values and variables. But here I can do other stuff too. I can actually step through execution line by line so I can do, there's a couple different commands. There's step to continue execution by single line of C code. There's the command next to go to the next line of C code and this kind of skips function calls. So if I was on this line of code for example and I don't want to go into the code of printout but I kind of want to skip over that and keep going through the lines of my program I can use the command next. And then there's finish which is to step out of a program. Oh, sorry, step out of a function. So like if I've called a function and I'm going through line by line and I don't care about this function anymore but I want to go back to the caller and start stepping through line by line I can use the finish command. So like in this context for example if I type in step it'll say okay now it's on this line of code. All right if I do step it'll go, oh it doesn't have the source code for this so it's doing some kind of garbage output. But it would have been showing me the code for printout. But I don't really want to debug printout because it's part of the library and code is probably correct. And I want to go back to my code so like here I can use the finish command and it goes back to the calling frames like now I'm back to debugging save. And so I can for example keep typing next again and again and again. If I just press enter my debugger it does the same thing as just repeating the last command. You can see it just prints out which line of the program I'm on.  And at any point I can inspect the value of these different variables. So like now I'm on the for the iteration of this loop. Okay so that's some debugger basics. Some other neat things that you can do with debuggers. You can set up this tool to basically like look at a variable and stop execution when the value of that variable changes. So like I can say okay I want you to run this program and whenever like I changes for example stop execution or another thing you can do is you can set it up so that whenever you read from a certain memory location the execution falls. So let me quit this debugger just to get rid of the break points I've set. There are other ways of doing that and start debugging again. Here I can use the command say our watch that says stop execution whenever I read from this value and I can say it like say the third element of this numbers array. And now I can run my program and it will run to the point where I print i. So I'm inside say the argument to say is for and I'm about to do this memory access that's right here. So this is pretty powerful stuff that you can't do just with print hostility debugging. Right. And so I can probably give you like a many hour long tutorial on GDP commands but we don't really have time to go through all of that. So this is just to show you that debuggers are a thing and they can do a lot more sophisticated stuff than print desktop debugging. Just one last thing I'll show you with GDP. GDP has this kind of command line interface that I've been working with right here where I can do a single command at a time print values of variables and things like that but it also has a slightly nicer user interface. So there's the layout command which can take a couple different arguments and you can look at the documentation to see what exactly it can do. But you can put GDP into this text user interface mode where it kind of has a split window thing and it can show you different things in these different panes. So you can for example get to show you C code in one window. The assembly code corresponds to another window and then have this prompted through window. Let me maximize this just a little bit easier to see. And here I can instead of stepping through this program with step going one line of C code at a time. See here it's even highlighting which line of C code I'm on and what assembly that corresponds to. I can do things like step by individual instructions of the assembly. So if I do SI for example, that's for step instruction. I can go through this one line of assembly at a time. This still corresponds to this for loop here but I can see that I'm going through this assembly line by line. And there are other types of layouts here that I can look at. I can try not to see what's in the registers for example while this program's executing. I can switch to a different layout that shows me that. So here I can see like what's in some of the general purpose registers and so on. If I make this bigger I'll see even more registers. So basically it's a pretty powerful interface that'll let you inspect a lot of things as the program's running. This will even highlight whenever a value in a register changes just so it's a little bit easier to tell what's going on. Like here I'm about to subtract a value from EAX and if I run that instruction I can see my AX registered value has been documented by one and GDB highlights that for me just so I can see what's going on. So any questions so far? This is a rapid fire introduction to what a debugger is and what kinds of things it can do beyond maybe whatever you were using for debugging before this. Yes? What other languages does GDB support? It's mostly C style languages. For example. Sorry what? But like, sorry could you give me an example? Oh so like go for example for C++ or Objective C and we're all supported by GDB. So technically it supports anything that is assembly which is all binaries but to get the mapping to source code lines you basically need a language to produce a binary that has that mapping. So that tells you basically what the debug symbols tell you is for any given address in the memory space in the binary what is the corresponding source file and line and as long as you can produce that file the language will be supported by GDB. Of course GDB has a particular notion of variables and functions where if you have a language that's very different like Haskell for example then GDB will not work very well because it doesn't have the same concept of how a program is running. But if you're using C++, go, rust, not quite Java either. Basically anything that doesn't have a very heavy runtime with the exception of go will work very well with GDB. Any other questions? Yeah. Where do you use the hour watch? Does it scan through the full C file for like the variable of that name? Like you're asking about the argument to the hour watch. Yeah. It's in the current scope. In the current scope. So it understands the C, basically looks at the scope in that C file or whatever function you're in using the debug symbols. Any other questions? Also a random cool side note, you might wonder like how is something like hour watch implemented? Do you interpret the C program and go through instruction by instruction checking for access to that memory location? Things like that would be very slow and there's actually hardware support in your processor for watching specific memory addresses in this way. Like there's specific support for this kind of debugging. It's kind of cool. There's also a layman's version of watch called display, which if you set a display, then every time you step to another instruction, it will print whatever you set to display. So that way you can monitor whether something changes over time. This would be a handy for monitoring registers, for example, like for every instruction I execute, display the following word distributed. Are you gonna mention RR? I was not going to, but you can talk about it. Okay, then I will mention RR pretty briefly. Notice that here the commands you have are things like you can do next and you can do step. RR is a really, really cool debugging tool that lets you step backwards through the execution of your program. So it gives you the operations R step and previous. And it does this by basically keeping track of all the system called the memory operations that you do and then giving you a way to step backwards through your execution. So for example, you can set a breakpoint for what a particular value reaches something or what a particular bug triggers. Let your program run however long it takes until it hits that and then step backwards through the execution to figure out why a particular value became that value. So you can do an inverse watch point, for example. Say give me the last point at which a variable changed before you hit this bug. It's a very heavy debugging tool. It's especially useful for programs where you have non-determinism. So you have a multi-threaded program and there's a race condition that triggers very rarely. Well, it's really nice to be able to let your program just run, maybe run multiple times until that race condition hits and then go backwards and figure out exactly why that happened. Well, any more questions about GDB? So I also want to show some other debuggers that offer slightly different interfaces. So GDB's for these programs that are parallel to a binary and sequence of assembly instructions like C-like languages. But what about, say, interpretive programs like Python programs? Well, so most programming languages have pretty decent debuggers and they kind of more or less work like GDB, but just to give you a little bit of a demonstration of Python's debugger, which is called PDB, this is in the context of some random program and you don't really need to worry about this running program, but I just want to show you what you can do with this tool that you can't exactly do with GDB. So here, the way you use the Python debugger is you import PDB, which is the debugger, and then you call PDB.setTrace. So you can basically stick this line anywhere in a Python program and then whenever execution gets to that point it'll give you a GDB light prompt. So don't worry about all the surrounding stuff, but anyway, I run this program and once the execution reaches that point, I get this prompt. And now what's really cool here is that it's kind of like GDB where I can step through execution of my Python program, but it also lets me do other things, like this is basically a hybrid of this debugger command line and a Python shell, so I can kind of like write Python code and it just runs in this context and I can go and manipulate values of variables in my Python program, things like that, in addition to doing the usual things like printing values of variables. So this can be a really powerful way of debugging, which is really nice for these dynamic, interpretive languages. Yeah, basically I just wanted to mention this tool and say that it's kind of more than GDB, it's a hybrid of an interpreter for the language and also a debugger. I'm not going to go into the details of PDB, but any questions about this? It's this concept that this exists. So quick mention, if you like interactive Python, I Python, there's also like an IPDB, this is the IPython cell inside. Oh. It can be really, it's really convenient because like auto completions, knows a lot of like the dog strings of functions, stuff like that. Yeah, yeah, so basically like every language you'll have some debugger and it will give you this pretty sophisticated way of understanding what's going on with the program. And now beyond just these command line interfaces, you also have graphical debuggers and one really common one to look at is the web browser. So if you go into your web browser, and I think this will be covered more in Thursday's lecture, so I'm not actually going to go through the details of how to use this, but basically here I have a graphical tool that'll let me do more or less the same set of things, but maybe it's a little bit nicer to use in some ways. So using this tool, like if I was looking at a piece of JavaScript, it's a JavaScript code here, and then there are buttons for say halting execution or, let me just worry about what exactly is on the screen, but there are buttons for doing the equivalence of next and step and finish. And there are these panes which will show the values of lots of different variables so I don't have to type out the print command and things like that. So if you prefer graphical user interfaces, there are GUI debuggers too for a lot of languages. Your IDE might have a built-in debugger that'll let you set breakpoints on lines of code just by double clicking on the side on that line of code rather than type like breakpoint, name of file, colon, line number, or things like that. So that's what a graphical debugger is. So that's all we have to say about debuggers. And now we're going to mention a couple other useful things. Next thing is particularly useful if you're doing any kind of systems programming. So this is a command called strace and what this will do is it'll run a program and while the program is running for every system call that that program makes, it'll print out what system call was made and what arguments were passed to that system call. And so this is another kind of tool that can be useful for debugging. So for example, what happens if I just run the echo command and you look echo high? Well, at a high level, the real guts of this is a single system call that calls write with an argument that's like the string that's just the word high. And if I run this with strace, you can see all the other stuff that happens when my shell executes this program and it gets set up. And eventually it gets around to issuing that single system call, write system call to file the script or one, which is standard out, which contains the actual contents of what I want to print. Just wanted to point out this tool is like something that we use to debug system calls or programs that do system calls. And after that quick mention, I think the next main topic we wanna cover is something called profiling. So GDP, like debuggers are useful for, well, debugging a program, if something goes wrong, like it's producing the wrong output, I wanna go and understand why I'm doing that. But another way a program can be wrong is it can be too slow or use too many resources or something like that and these kinds of debuggers aren't really good for understanding that.  And so that's what profilers are for. And so again, this is a general kind of tool that can be applied to any language and you'll find specific programs that are used for profiling code written in specific languages. But this stuff we're going to demonstrate to you in the context of Go programs in the Go programming language. And a couple types of profiling we'll show you are CPU profiling and memory profiling. So one thing I might wanna know is, okay, my code's running for a long time, what is it spending most of its time doing? And so here, this is just some of the random program, you don't need to worry about what's being profiled here, but I can instruct my tool to record a CPU profile and it'll basically instrument the process that's running and figure out where it's spending all of its time. And so again, this runs for some time and it produces some output that contains the CPU profiler information and then there'll be some other program that'll be used to visualize or analyze the output of my profiler. And so in the context of the Go programming language and the Go tooling, it can actually produce kind of like this interactive webpage where you can see a call graph along with annotations for where it's spending most of its time. So like here, I ran some program. And you say, okay, here's a function that took a bunch of time and highlights it in red. It actually took up the majority of CPU time spent running my program that I ran. And I can see the breakdown, okay, this calls this function, this calls a bunch of different functions and some of them actually don't end up taking up too much time in terms of total program execution time, but this function, for example, here does use up a lot of the execution time. And so I can follow this call graph down and figure out which is my code, which is runtime code and so on. And based on this, I can go and read my source code and try to understand why it's slow. And basically this will tell me what to focus on when I'm trying to optimize my code. Another thing I might want to look at besides CPU usage and how many cycles my CPU's using is how much memory my program's using. Like maybe my program is super bloated in terms of memory usage and I want to optimize that. Well, then I should know where I do a lot of allocations or what kinds of objects take up a lot of memory. And so the tool used, there's a memory profiler. For Go, this is one way I can do it. So I'm running all my test code, but also recording a memory profile while that runs. And then a couple of seconds later, I'll have the results of that. And then I can run a similar command to what I ran before, except analyze that memory profile. And here it'll show me, okay, here's a function that allocates a whole bunch of memory, and this is actually a breakdown of where in that function it's allocating a memory. And okay, here I'm copying a bunch of objects and that's actually the majority of memory usage in my program. And so again, a similar thing to the CPU profile, by looking at the breakdown of where I'm allocating memory, it'll basically help me figure out where I should spend my time reading and understanding my code and trying to optimize it. And again, for every programming language, the exact commands we use and the exact way the interface looks will be a little bit different, but the general idea is the same. Like profilers instrument the execution of a program and let you understand those results in some useful way. And one last thing we'll show you, just showing that you can do this, of course, for different programming languages. Here I'm using a different tool, something called PERF to do a CPU profile of a different program called AG. This searches files in the current directory for files that contain the character X and will produce a count of them and whatever the program produces in output. But this tool has instrumented the run of this program. And now I can go and analyze this. And here I can see a list of where I spent most of my time and what exactly was the function being grown where I spent that much time. And I can go into here and look at more details and so on. So just to show you like there are different tools for doing these sorts of things. You can also get just high-level summary information if that's all you want. Like the PERF step command, for example, can tell you, oh, I spent these many cycles running this program or how many instructions I executed in the run of this program or things like that. And that can also help you understand the behavior of a program and figure out where you should spend your effort in terms of optimizing it. And also one thing I forgot to mention is kind of the simplest profile that there is. This is a program that's already installed on your machine and it's something called time. And it will give you basic information about the execution of a certain program. So like they go back to this program I reported earlier and it starts to do time. It'll tell me how many seconds I spent running this program and how much of that time was spent running code in user space versus how much time I spent running system calls. It's kind of useful for debugging certain things. So that is a very quick introduction to what profiles look like. Any questions about that? If you're curious about learning more about profiling, there are a lot of good guides and tools online. I also recently did a, so I ported a tool called Flame Graph that shows you really nice like performance profiling graphs to Rust. And in that video, we also do a lot of just discussing how profiling works. So if you just like searched on YouTube for my name, then it's on the website, it's easier than spelling it out. If you search my name there, you'll find the video and then you can have a look through that if you're interested. That is in a lot more detail than this, which may or may not be what you want. But there are really cool things to do with profiling. It really is useful to figure out what is worth optimizing a new program and what is not. And we can also add a link to that in the resources section of this page so you can find it more easily. Okay, so that's what we have for program introspection. So hopefully that's a quick introduction to how you can understand more about what's going on with the program deep reading. So any questions about debuggers or profiling or anything else in general in this area? Okay.