I didn't know because it was just that I drank Pulchinsky wrong, so I didn't know how to guess. So I thought that he had a C.EV, his action. He actually has a C.EV, which is what we had. So there was no confusion between them. Okay, so our discussion for the point particle last class was accurate. We're looking at it just now. It just looked like it broke. Fine. Okay, so now, so today's class was going to go on. Now we're going to generalize our discussion of this point particle to the string. Okay? The discussion proceeds basically an exact analogy to the discussion we had for the particle. And I'm just going to give you the final answer for the BRSA transformation laws from which we will deduce a comment. And we look at the answer to C.EV. Okay, so the answer, so, you know, I'm going to give you a final answer by which I mean I'm not going to go through the intermediate step of introducing metric and the ground-multiply integration. Okay, so first we have to say what dx mu is. So remember, dx mu changes out of the gauge transformation equation. The gauge transformation equation can have different forces. C is the different forces in the field. So how does it change? Well, it has an i times epsilon, which is the anti-commuting parameter, plus c times del plus c power times del r. Okay. The change of the scale of field. Okay. Now what about the change of B? Now you remember that in our general discussion the change of B was proportional to the ground-multiply. Remember that the ground-multiply is what multiplies the metric. Okay? And we solved for B by the equation of motion from the metric. So when you differentiate with respect to the metric, you get two terms. You get B and you get whatever else you get. But whatever else you get is by the equation of the stress tensor under there. Okay? So the solution of B is to set B equal to the stress tensor. Okay? So this just gives us the stress tensor, which we divide out into two parts. For convenience, the part that comes from the matter piece, and the part that comes from the basic process. So dm is the contribution of the stress tensor in the matter piece, dg is the contribution of the stress tensor from the basic process. Okay? And what about c? What about change of c? But last time, remember, we had c times c power. There's an obvious extension of that. The obvious extension of that is this. There was no half, because there was a half in f, but then f had two terms. That's a half, and then you write the formula, and then you evaluate it as two terms. Okay, great. So this is the matter piece. Okay. We got this symmetry transformation, which you can check if you'd like to directly by, you know, this is the symmetry of the theory. But we do it in more sophisticated way. You see, we know that out here, this is the geometry of the theory. Okay? And I should, of course, say it by the way that there are analogous rules for db bar and dc bar. Right? You just replace this by d bar, dg bar, and we're going to say it by c bar. Right? I'm not writing it down. It's the obvious extension. Okay? So now, the question I'm going to ask is the following. Can I write down... So, let's suppose that I do the usual thing. So I should try to write down brst transformation in a charge as a modulation by ai times dz of jz minus dz bar, dz bar. Let's call it, let's call it jj tilde down, b for brst. So I'm writing the usual thing. I try to write down, but there's a charge and it's an integral over a current. And I'm going to try this out. I'm going to make the assumption to start with that we have an analytic current, you know, the jb is analytic, jb bar is analytic. And we'll see if that's correct with the answer. Okay? So the question I'm going to ask, the question I'm going to ask is, what is... Yeah, again we write down, look at these transformation properties, let's look at the transformation properties one by one. The first thing we want is that the change in x mu is that, it's just the derivative of x mu. So that's the analytic part first. We only want to generate this part. Okay? So the change in x mu is the derivative of x mu times the same thing. We know that... that we know that on general problems, that the change in a field is obtained by looking at the pole, the residue of the pole, which creates the generator question and the field. We derive this and use this many times. Okay? So we want some term in jb, such that the product of this term, and x mu has a pole, which is c times del x. Okay? But we know what that is. It's c times the stress tensor. Because we know that the stress tensor, active on any function of the matter of fields, has a pole part, which is derivative of that matter of field, that function of the matter of fields, back by pole. Then we know that it's true for x. For instance, for x we can change it explicitly. Quickly remember the stress tensor is proportional to del x del x. We have active on x, xx for the log, del xx gives you the pole, proportional to del x. The residue is proportional to del x. We would also want to see that. I'm just doing the analytic part. So that goes on through g1. Okay? So I'm just trying to find the analytic part. This is g1. Great. So we've got one piece in the realistic column. It's c times g1. Okay. Now what? Now let's move on here. Whatever else we have, shouldn't have any non-singular opinion with matter of fields. Because we've got to get all the transformation of the matter of fields from this part. So the simplest assumption remains that all the remaining parts function with the coarse fields. Okay? So we want the coarse fields to have this problem. Now to get this, to get this straight, let's remind ourselves what the coarsest stress there is on this. You remember we worked this out in generality when we started the BC system. And we worked out that in general it was tg was equal to del b times c minus lambda that is del of bc. In our situation as we've discussed, lambda is equal to 2. It's up to you to remind me why lambda is equal to 2. It's simply the way of saying lambda is equal to 2. So lambda equals 2 gives way to 2 to b. It's minus minus c. Why is that the correct answer?  The c insertion gives you way to minus 1. The simple thing to say is that in our generation of what b was, remember b was something with two ANDs that came out of the water, and therefore we had to do it. Whereas c was something with one AND that came out of the top, and that one came out of the top. You remember c was negative, b was a 2 times. That's the basic sense. Can't be seen in that question that c is negative and b, this was the vertex operator, which was the derivative integral of b squared. Yes. So it had to be consistent, this had to happen. But you see, that's the consistency of the final answer. Where in logic did it happen? It came from this index function. You remember we wrote this action in terms of b with lower indices and saw that the action was explicitly wider than that. So the rate under conformity transformations which in general is the rate under derivative operators plus wide transformations was purely the rate under derivative operators which now is the decision that can't be made. And that was our variation. Okay fine. I should have said by the way that this room was needed in 313, so it's going to be a brief class. We should have it. There's some chocolate, something. Okay. So the course system in the concentration had this stress answer. So let's see. So what we want for b, for the change in b is that del b is equal to let's drop the i epsilon. So what we want for the pole. So we want jb times b to have a pole on the right end of the left pole piece. We want that to be so now that's simplified. So this is del bc with a minus 1 minus 2 b del c and we call this z and this 0. We want this from here we want that from here we want that jb of z and c of w times c of w of w goes like c del c of z. So now let's try to see if we can come up with a guess for a comment that will do this. So let's write down the answer and check if it works. So consider bc del c also this thing had to have of course there have to be a plus k because there is this part Now the plus dm is trivial because we already have from the part that we added already to the post column we've got to term that c times b. So c times b is 1 over z minus w so the dm is automatic. So this part is automatic for what we already have. The new part is to give us this. So let's see first let's see roughly we want this new term to have an op we want this new term to have an op with we want the new term to have an op with b that has one b and one c. So clearly the new term has two c's and one b's because it's c and b that are not trivial contract. So we also want one derivative between f and b so it looks like a reasonable thing to start with. So now let's check. So what we want to do is to look at bc del c at z acting on bs of c. So what is the op? We can have either this guy contracting or that guy contracting. This guy contracting that has no minus sign but it has one over z minus w the whole thing squared with a minus sign because that differentiating produces a minus sign times dc at z. Now what we are interested in is the pole which goes like z minus w and we want the operator to take rest at the point w. So we need to cancel one zero so this gives us the contribution of this contract first contract. Minus del of bc by z. First we have minus sign because the c goes through the del c. But then there's nothing else. b del c times one over z minus z and the minus sign because the c is constant del c since the sum of these two so we add them up and what we get minus b del c with a factor of two minus del bc and this term is del of b times c. I added a factor of this and a factor of this so I would think there's much. So if we didn't try just the pole part we've got exactly one. Is this clear? Okay, let's also check that this thing that's what I think we'll see. Is that jb times c is equal to c del c divided by z. This is the z, this is the z. Okay, so this one's very easy because we take b at the end that goes through two and you can see that it picks up no sign then b with c is one over z so what we get is jb with c is c del c over z minus w. Exactly. We've got the moment of the current because we've got a current that has light poles with everything so that's a fun fact. So a provisionally final answer is that jb is equal to c times dm plus bc then c. There's a fancy way of writing because of c times the cost current. It's not very useful. This is the same thing as c times the cost stress tensor divided by 2. That's because the cost stress tensor has two terms. One which is c del b, the other is del you know b del c. The term that is c del b is when multiplied by c is zero. So all that remains is the term that is b del c and then so that it's getting proportional to the cost stress tensor the fact that it happens to be half. That's not very useful to me. So let me just write it down as tm plus tg ctg by 2 that's not very useful to me. Now as far as transformation properties go as far as generating the right transformation properties go there's nothing more to say. However, it turns out to be that you have to add a total derivative to this definition. Because it's a total derivative it doesn't affect the q, b, r actually. Again, because it's a total derivative precisely because it never affects the polar germs in the in the OP. Let me write it down first. All terms are any singular OP between c and anything is already a total derivative of it becomes 1 over z minus w cubed. So this is the polar way of saying that it doesn't affect the total charge. So it does but as a total derivative if you want a current that generates a particular cement you can always add total derivatives to that current because it doesn't affect the charge therefore it generates the same cement. However, we chose this so that in the critical dimension the costant will become a primary operator. It turns out that without this term that would happen. It's a convenient choice of additional total derivative that affects nothing physical if it requires an activation. I'll give you the answer. I won't give you the answer. Okay, great. So at the moment it's just some choice of compute that we fix in a particular way that we find. Okay, great. This is the current and now we can ask is the current observed? Is the current observed but the answer is obviously yes. Why is it always that it's a non-conservant current? Is that right? So what's the current conservation equation? And is it picked out for the start probability? Okay. So why is it obviously concerned? I don't know if it's a hydrophobic field but it's a hydrophobic current. When you work out the same algebra for G bar that's obviously an hydrophobic current. So without saying anything else it's a concerned charge. That's very nice. That's a nice operator. But there are a few more things we want to we want to ask. The most important of these is the question of whether Q is a question. Okay. Now how do you address given the current, how do you address if you know the contents of a charge how do you compute but Q is an anti-commuting object so the square of the operator is the anti-commutator of the operator itself. So now what kind of thing you do to compute an anti-commutator from charges? Remember what we had and what about the OP tells you the answer? You look at the you look at the operating session and there's a thing there and then you remember what the other what terms I think matter which is the four, the rest of you also. Okay. So the question of whether Q is quest to zero or not is a question of whether Q comes in or addresses you to the JBG okay. So so there's a bunch of OP that we should calculate for the service current. Now we've got a lot of OP calculations in class all of this is pure algebra I'm not going to do it I'm just going to present a lot of answers for you and leave it for you to check for these things. So let me read out a set of some time through this course it can't be that part of it we've compute the whole parts but at some point we have all the singular terms. So let's look at JB times B you remember we've already found that the whole part is one by Z so this is at Z and let's say zero okay. On the other hand the whole part is one by M plus DG one by Z because there were more singular terms than there was G the cost current by Z squared okay. What's the dimension of the left-hand side? What's the dimension of JB? What's the dimension of the cost current? What's the dimension of any kind of space? It would have been two had energy but this is What's the dimension of charge? Zero expression for charge in terms of current? Right. So the dimension of JB must be one comma zero because integral dZ JB gives you zero. DZ is minus one comma zero. So it has to be dimension one comma zero. So we've got the sanity that has dimension one comma zero let's confirm this explicitly count from this term del C is one what's the dimension of B? give me all that B is one two C is one del C is one at the left one what about C times TN? C is one okay good one by Z two is dimension what about the cost current? What's the cost current? two minus one one one one by Z squared is dimension two plus one is three dimension one by Z is dimension one stress tensor is dimension two and dimension three this is the kind of thing you should become routine through you see it on TV first thing you do is check it you make basic sense that okay let's do this one what's the dimension of the right contact? zero zero because del C is zero C is minus one one by Z is one and so on okay so these are actually very easy to derive they take commotion of work now we've done most of the derivation see this part this part we've already derived this part we've derived the rest or any any tensor made out of matrix it would take a volunteer to derive this that's why it's a primary operator a made out of matrix of weight in which C times Tm times Lm is what? Tm times Tm times minus minus two so this is why I wanted an h which is okay so let's put this as Z let's put this as W and now this is what? okay first an h go on Z squared good what do they do? wait what do I have to do? where are they located? they're under here is Cw or? oh C is it now you extend it and get the Z minus good we'll do that C is Z and then Lw is W and then perfect and now as you said we can expand this and we get a del C which has a pole which is h times of okay so it's all that simple we've done this a hundred times we must not get useless okay I could ask you okay we're wasting time okay good let's just stretch more there's one more P that will be of the two more algebraic factors what you did with the first term what? this also gives the first term yeah exactly I want to do one more P it's for practice there are two more that will be algebraically useful in the last okay so first let me write down the last two oh the last two will be Jb and Jb has Z Jb, Jw but let's see every operator has a zero minus now I'm not going to try any more to do any more deriving with your PAs okay let's just take these answers as given and exact the only important thing to look at in this OP is the coefficient of the pole the coefficient of the pole the term Cm the matter central charge minus 26 okay so that tells you that by classically you can check that the transformation rules that we we specify classically square to zero but classically this is Q something that squares to zero in any dimension quantity taken Q squares to zero only when the matter central charge is 26 so from the BRSC point of view this is how you this is another way of getting the critical dimensions frequently the BRSC can't square to zero in terms of the co-energy problem only with the critical you'll see as we go on everything was only one thing creates one supposed to be like that okay correct there's another related statement but every statement that will be important for us and that's this you remember we started the ghost we found that it was not quite it was not quite a conserved current it wasn't that but it wasn't quite in curved space because and that was related to the fact that the t j OP didn't have only a one by z squared but also had one by z cubed okay we had an exercise in which he was supposed to relate this one by z cubed piece to the failure of current conservation in an archery curved space it's quite a general statement that the only way that current can be conserved in an archery curved space is that it's a primary operator okay so this only here at the C L minus 26 over 2 z to the 4 okay which would make this a knockoff primary operator was one zero but in the critical dimension there were many fathers that had the OP with a primary operator so in the critical dimension j is a primary operator of dimension one and therefore it's a conserved current on any matter this would be important for us because we will be when we do string theory on higher genus remand surfaces that we have a conserved cost current not just in transfer so we've seen two interesting things from the OP's cost current firstly q squared is equal to zero but this works on critical dimension secondly the cost current is the primary operator of dimension one point zero this also works on critical dimension that's all I can say about I think that's all I want to say about the cost current oh no there's one more thing we have to add the the binding yes yes so the last thing I wanted to say was just an algebraic fact but maybe I should say two more things well first let's look at this algebraic fact we've seen that jb with b has an all part which is dm plus dg by z the anti-computator we've seen two fields related to the recipe of the code so this statement directly translates into qprsd anti-computator b b0 which is the chart b0 is equal to m0 plus lg and by appropriately multiplying both sides z to the appropriate power it also implies the slack also implies qb times bm would somebody okay I'm not need to derive this statement for me carefully something I wouldn't be tempted to do if I was sure you guys were practising opus at all okay but I'll leave it to you please you know go when we make statements like this without proof in the class please go and check if you have any problem with the writing please calm down I'll just move on assuming that you guys are doing well please do it okay very good it's the statement that we will find out immediately in our discussion okay and finally if anything else we would just say so now the next thing that I wanted to okay questions, comments questions, comments about everything now the next thing I wanted to do was consideration you see, it's all brsd quantization business and an essential element in it is the recovery of the physical spectrum by the construction of brsd go home, okay so now in the remainder of this lecture what I want to do is to prove for you that the brsd go homeology on the world sheet of the string is isomorphic to the spectrum we obtained from my book on this this prove, plus certain extensions that we will also explain when we study in multi-day the S main things okay has fancy names called the no host theorem so in multi-day I want to prove for you that if you look at the brsd go homeology on the world sheet of the string you have some sort of correspondence with the states that we obtained through quantum quantization not just in number, but also in in your product the last state was very important because we have demonstrated through this process that there are no negative norm states on the world sheet of the string you remember that when we just did like old quantization, there were negative norm states before we fix like old gauge because there were oscillators of x0 however when we went to the like or the only oscillators were in the 24 clock transverse n inches there were no negative norm states so what I'm going to prove is that we have the same spectrum that we get from like on quantization and the spectrum that we get from brsd quantization is cost free the sense that all the states that we have obtained are states with positive norm states and it's certainly not true that we didn't restrict the states that were of the form that were in the artistic homology that we would get cost free states we'll see negative norm states off of the place as we as we proceed with our analysis okay so my plan is first to give you the form of our result and then to demonstrate how it works at the first end of the string okay so let's start let's start by looking at the form of our result and let's see how far this goes my discussion of brsd quantization has wholly been mirrored in the Polynchian scheme anything you don't understand what a real Polynchian scheme is it's already a real discussion I'm not seeing that anywhere else it's very clear let's start so the first thing when we use brsd homology of string theory I mean brsd homology plus the additional extra input that is the analog of the additional extra input that we had for the quantization of the Polynchian maybe it will also require b0 one of the states you see because in particular if we just restrict the string theory to the zero mode we really recover the quantization of the Polynchian so just to get every oscillator mode gives us a new part but the zero mode part is isomorphic to the quantization of the Polynchian so just to get the Polynchians to get not to get doubling of the spectrum we must have eliminate half the modes so what is the state this is the state no this is just okay the level of quantization we've been doing for the spectrum so far so what will we since it works with one particle we want to do this it's clear we must put the same condition here b0 plays the role of the operator that we had before remember that in string theory also we've got the c0 and b0 that generate the two state system in a c0 once we've got this two state system which commutes with the energy operator so we would have had two states at a level we impose this addition so the first thing I do calling Polynchians is to define a restricted input space I divide a restricted input space in the worksheet for string as we the state of all of see we want the side to be 0 on size but we also on size so it must be qp on size but therefore it must be qp then the commutator be on size but we just compute the word qp and the commutator qp with b0 is it's the stress it's the well the l0 in matter and coast in matter and coast therefore it must be that where by a 0 I mean l0 matter plus l0 coast on size equal to 0 let me do the find a restricted input space we had to be consist of those states such that b0 on size is equal to 0 but cuts down to the original input space by half in the two states of the space and also such that l0 on size restricted input space has good action of the BRST operator because the BRST operator maps this input space itself now check that we know that qv that l0 is equal to what somebody BRST operator has a conserved charge and therefore it walks to the amateur to me and qb times b0 as we see is equal to 0 so this commutes when of light to the sector of states that I am okay so the if you act qbrst on a state belonging to HAC you recover a state belonging to HAC so qbrst is a good restriction to the subspace HAC okay so in all the discussion from now on we will be restricting our attention to the subspace HAC right from the discussion the discussion that we are going to perform now is a little abstract and it is very clear but because it is clever the motivation for what we are doing would be clear until we reach the argument so you have to have a you know until we reach the conclusion okay so the first thing we do is about let us go to the space oscillators and let us choose the time oscillator alpha 0 and the particular space direction alpha 1 and let us do the this set of oscillators now we will make linear combinations of these oscillators so we define alpha 0 m plus alpha 1 and then probably part of it and part of it as we are talking about minus the goal is to demonstrate is to define the co-opology of the qbrst operator acting on the the subspace HAC and I am sure that you will see this as light co-optization now because we are going to show this same light co-optization remember in light co-optization we chose the time direction and space one space direction to be special okay so we have to make a special let us make the same special choice so this is time, this is space and we are looking at the oscillators in those special directions which we want to make so what we want to show is that the bbrst co-opology is one to one correspondence with states obtained by acting only with oscillators in the other directions and no bnc oscillators okay but now it is a predatory work for this so hang on for a moment we are going to do this from idea of combination relations of these oscillators alpha 1m with alpha 1 minus m was equal to m times delta m plus n 0 which and the sign here was the statement that the positive ends were annihilation operators whereas the negative ends were creation operators and annihilation of creation is possible no in very good minds which is dead back then but remember the normalization of oscillators was such that m is equal to m times delta m now but remember that when we did canonical quantization the combination relations actually appeared with a g mu when you want to write it it is a predatory work because we want time in this nation so we hang on the same relations here for alpha 0 again and alpha 0 again because the same thing is minus because canonical quantization and additional minus from the fact that the time is equal to the metric that is okay so now let's take the reason and add them out to see what the combination relations of alpha plus minus plus with alpha minus suppose we add an m such that things click alpha plus m alpha plus minus m we get a plus m from the alpha ones but a minus m from the alpha 0 so you can see similarly with alpha minus and alpha minus so the thing is that if you have known 0s alpha plus alpha minus the combination relations are from these guys are alpha plus m alpha plus m is equal to alpha minus m alpha minus m is equal to 0 but alpha now let me read it out and check that it is correct alpha plus m alpha minus m is minus m let's check that out immediately alpha mu alpha mu mu mu that's right exactly that's exactly another bit of this and this minus sign is silent this minus is the main trick okay great so now let's consider the following let's consider the operator sum over m not equal to 0 okay alpha plus minus m this operator has a name it's called hs okay I want to understand what this operator does okay so let's see what this operator does we are acting on alpha minus k minus k of let's say minus of m okay yes it's a number operator that measures the number of negative photons in the minus direction minus the number of photons in the plus area let's take this okay you see suppose we act we look at a state with a minus photon so k is the positive now if we act on this operator we get something normal 0 only if we have alpha plus with a positive so m is negative in that case we get the stop mutator which gives us negative number the numbers cancel and then we replace it by the same state you see we got an m here the answer is the m here the two negatives we got are positive okay so hlc on this so let's go to the side hlc on the side is equal to alpha minus k over plus okay we can say the same thing but the opposite side so hlc on the side is equal to minus okay and in general what this operator does is measure the number of minus photons minus the number of plus see this operating is very close to being the boost generator the generator of boosts in in on the worksheet of the stream there's no role in what we're doing so I want to analyze the detail but I recommend you do the following exercise compute the no-thread charge corresponding to the generator of boosts in the one zero direction in comparison to this operator okay if I go up and over our constant it's exactly this for one fact you see here we demanded that m was not equal to zero okay the generator the no-thread charge that generates boosts in the one zero plane includes contributions from the zero so it doesn't have this m not equal to zero it doesn't have this m not equal to zero so apart from the contribution of the zero mode this is essentially the Lorentz generator of boosts in the one zero okay now so let's move on we don't have much time okay that's for one now the next thing that we want to do is a problem we want to take a beyond sd operator take qb so why I introduce this hlc at the moment totally empty it's going to be a formal object that will be used the player used to know so now let's take qb and decompose it it's hard to beat okay anyway there's chocolate in ten minutes okay let me just give you we may need many weeks from now so I probably have to repeat this but let me just tell you where okay you can take qb of brsd operator and decompose it into operators of different hlc network if you want to try this yourself check that the three hlc numbers that appear are zero minus one and one take the brsd charge a brsd charge does not have a definite quantum number on the hlc but you can split it up in the sum of three pieces each of which does have a definite quantum number and you can see clearly that the quantum numbers appear as zero minus one and one but the argumentation is that the brsd charges the range is very okay we'll continue next time okay so let's stop now


do what you like is my main advice. If you're doing what is fun, you'll be able to do it more and to do it consistently and to suffer very little. And I think that it's possible to do things that you like. I mean, it took me three years to get the money, to get into medical school after being accepted into medical school. And I thought it would be impossible for me to come and do the things that I do. But I think that if you, it sounds really cheesy, but if you really want to do something, you can absolutely make it happen. It'll be a whole mess of a thing, but it will be the thing that can materialize. So that would be my advice. Follow your fun because you're going to have to do things you don't want to do anyway and work. So you might as well, you know, work hard at the things that you enjoy and not settle for jobs or degrees that you don't want to do. That would be my little advice. Nice. Follow your fun. Excellent. Follow your fun. Exactly. Nice.


Okay, so getting full user stack paste traces. So, user space stack traces could be used for profiling, so things like perf, I was gonna make sure it's still there. Perf, when you want to profile your applications to see how long to make nice flame graphs that Brandon Gregg always shows off, requires full stack traces. And that's something useful for things like perf. Ftrace also uses it, so when you wanna do system calls, you wanna know where the stack happens, you wanna use stack trace. BPF can use it, in fact, I'm sure you could probably even add a filter to BPF to say trace things when a certain function within the stack trace is there, so lots of useful applications. Now, acquiring the user space stack traces where it gets interesting from doing it within the kernel. Right now, it requires frame pointers, which means that you have to have frame pointers within the kernel to, or within the applications have to be built with frame pointers so that the kernel knows where the next stack frame is, so when you go up to the user space where you entered the kernel, or into the kernel, you have the registers, you can look at the stack, the frame pointer, or actually the stack pointer to find out where this frame pointer is to find the next stack and everything. When the frame pointers are not enabled, Perf, written by Yuri, does this huge copy of the stack and then post-processes it later, I believe, using the Dwarf on Winder to be able to find out where in the stack, so just as every time you take a profiling thing, it will record what, 16K of the stack into the ring buffer, so I could use quite a lot of data within the ring buffer. The problem with frame pointers is that it has overhead and LWN had a nice article when Fedora enabled frame pointers and I'll actually talk about more about that, but frame pointers require a setup of each function which means there's more instructions to execute. It also requires another register to keep track of the current frame pointer, so now you put more pressure on the registers that are used and as I mentioned, there was a good LWN article that talks about this, that gives, when Fedora enabled frame pointers, there was complaints that the build increased by 2.4%, the blender test case increased by 2%, and there was even some Python programs that increased up to 10%. There, all from, I don't know, I didn't do these tests, I just read LWN. So, how the stack frames work? Here's just a little idea, you have the stack pointer and you have the frame pointer that points to the previous stack frame and then from there you could get, whoops, you could get where the next frame was and then it'll show you where all the return addresses and then you get a nice little output. So, inside the kernel, we have this thing called the orc unwinder, which means oops, rewind capability, but we all know they were just throwing that in because of dwarf and elf. So, it's much simpler than the dwarf format which remember how many people had done like assembly program inside the kernel where you had to put those CFI annotations all over the place and how many people got that wrong. I was notorious with that. I did a lot of the assembly code and I tried in vain to get these things right and I would constantly get complaints from people saying, oh, this is totally broken. To me it was just black magic. I had no idea how those CFI annotations worked within the kernel, it was just crazy. In 4.14, live kernel patching required accurate stack traces. Reason being is there are certain cases where you don't wanna patch the kernel if that function is actually being used. You may not wanna switch it, there could be race conditions I could add. So, when live kernel patching would go in it would kinda like do a, I believe it did like a stop machine or did something to check to make sure that, and then it checked every single task and it had to do a stack unwind of all those tasks to make sure that what the functions were running was not something that was about to be patched and cause a crash in the kernel. Because the whole point of live kernel patching was to make sure that the system could run and you could update the system without having to reboot. So, if live kernel patching crashed when you enabled it, that kinda defeats the purpose of the live kernel patching and people would be kinda upset at you. So, I remember when this came up we were saying we need really accurate stack traces. Josh, I'm not gonna pronounce his last name cause I know I will mispronounce it. It's French, it starts with a P. He came up and developed the Orc Unwinder to solve this. Which was the tool, if you go into the tools, OBS tool it does this and it actually can define the Orc Unwind section at compile time. The way it does it is it has two tables. One table is the Orc Unwind, which is the information about the frame point or basically where the return address is and a few other little things. And there's another table that just is the IP addresses, that's a range. And to explain this, how it works, is let's say you have your stack pointer that points some place in memory with your return address and variables and you have your instruction pointer someplace else in the function. So, you wanna do a stack Unwind. The Orc Unwinder, you look at the table for Orc Unwind, it's a sort, the IP addresses are there are sorted. It's basically a sort of like ranges. And so it's not every single IP address basically, it's the start of the function, end of the function. So, you can easily find, with a binary search, the IP address. And once you find that, the index of the Orc Unwind is equal to the Orc Unwind IP table is equal to the Orc Unwind table as well. So for every entry you just then go to, once you know where the index is, you then you can find the entry with more information on there. And one of the things is the stack pointer offset, which then you take the current stack pointer and you add the offset to it, it gives you the return address. That gives you the second instruction pointer. And now you start doing the whole thing over again.  But then you find the stack pointer, I find the offset, gives you the second one to the next function and you get a nice little stack frame out of that. Which brings us to S-frames. S-frames is based off of Orc Unwind, same concept. But this time it's for user space. What's nice about S-frames is now you could do, when you compile with S-frames, you actually could do from the kernel, if this is implemented, a full stack trace without enabling a frame pointer. Which means we're sacrificing disk space for speed. We actually have none of the performance penalties of frame pointers, but it requires more data to be stored to hold these tables. The section is an L file, and it has the two tables. It says one of the things we have to require is to compile it in. Ideally I would love to have this be like almost by default, or at least if you have the dash G option or something like that, that these are created. So basically everyone will have this by default. But once we get this done, it will be possible to read this in the kernel. And that perf, ftrace, bpf can all benefit from this. So my idea for this solution, because the data that needs to be read is just located in a file, I have to be able to read it. And obviously perf triggers a lot of times from NMI context. So I'm thinking if we could do it from the ptrace path. We also have to find a way to handle the offsets. Because what it gives you is an IP address, and the problem with the IP address is the fact that it's relocatable. So yes, you get an address in virtual address space. Now how do we map that back down to something that I actually, if I do a ftrace trace, and I get a stack trace, a bunch of addresses, I want to actually point these addresses to actual functions, or maybe at least file offsets that these came from. So then I actually could find out where in user space that these were. Otherwise it's kind of useless for me. One thing I'm saying, wouldn't it be nice to know we have this information already in the kernel, and that's if you just cat proc maps and gives you the nice address of where everything is mapped, files are mapped to the address spaces. So the way this would work would be, so you're in user space, NMI triggers let's say, jumps down to perf. Perf says I want a stack trace. Currently it just says okay, I'm gonna read the, it actually does this from NMI context. It will actually read the stack from NMI context with a don't page fault option. So if you do take the option, it doesn't do anything, it just says okay, you faulted. And in case if the stack just happens to not be in memory for some reason, memory pressure, and it was kind of swapped out into the swap disk space, or you hit a section there, too bad it just will not even trace that patch. You just drop your thing and continue. I want to change this, and I've been talking to Geordio about this, about okay, instead of doing the full stack trace, it's going to ask for an S-frame. And then, on the way out, so it returns them NMI context. This could be from internal context or anytime. But just before we exit back to user space, there's a flag that could be set inside the task struct that says is there work to do? And if it's not set, it just says okay, no, go right back. It's in a fast path. We don't want this to do anything. It's a very simple bit check and goes right to user space if there's no work to do. But if there is work to do, then we go to the P-trace path. Reason why it's called the P-trace path. And in fact, P-trace is PT-regs and everything else we know is based off of all the P-trace code that GDB uses to trace other applications. So in this P-trace path, F-trace does stuff, Perf does stuff, this is where all the tracing happens. What's great about the P-trace path also is that it's in the normal context. We can sleep. We can map in pages. We could do whatever we want at this location. So we are guaranteed that we can get the pages back in if we have memory pressure or whatever. But we can actually get the full stack trace without losing it due to something not being mapped in. So then what Perf would have, Perf, F-trace, or BPF, whatever, could have a way of registering to the S-frame infrastructure that says, okay, I'm gonna get the stack trace for you and then send it off to Perf so Perf could again record this chain. This will require changes in the Perf user space tool. The reason why is because you may want to do profiling of the user space as well and you go into a system call that takes a long time and you get, say, three or four hits with the NMI while you're inside the system call. Each of those hits is just gonna do the kernel stack trace, but then it has to do some sort of flag or something that says we're gonna add a user space stack on top of this. But it won't do it in this ring buffer. The ring buffer will actually just say stack with a flag or something that says I want a user space on top of this and keep going and maybe it has to be a tag so we can identify it. And then on the way out, it will actually do the record. And when it goes back to user space, user space will have to go back and say, oh, we see these kernel stack traces without the user space stack, but there's gonna be a flag or something saying we want one so it's gonna actually have to keep going and says there's one coming up and we'll just have to store that information until it finds it and then it could re-append the user space stack trace, yes. Mike? Yes, Steve, I was wondering to kind of make Perf work out of the box. Is it possible to reserve some space below the kernel stack? Okay, actually this is a second benefit from this process. Smaller Perf. Why are we wasting this space on the ring buffer when it's just duplicated? Once you're in the kernel, the user space stack is not going to change. You could wait to whenever you want to do it. So the idea is it actually has two folds. One, to fix it so we could make sure we guarantee to get it. And two, let's save the space or ring buffer. Ring buffer space is high real estate. It costs a lot of money to use that. So then it's done, it goes back to user space. So the other thing I have is relocational addresses. This is, oh yes, yes. Yeah, I have a very quick question about the stack that's been swapped. So like, do we want to know that that stack was swapped at the moment when it was actually profiled? I don't care about it. I don't know, I don't think Perf wants to know if the stack was swapped out. We have trace events that can tell us about it. But it is swapped out and we actually have to map it back in. It's going to actually, yes, it may happen and yeah, actually that's another issue that we have to think about with this whole thing. When we get to this location and I might want to talk about this. This is kind of like some of the things I should probably want to talk about right here. The work I want to do is much more likely to require memory paging in at this point. Where the old point, we're just looking at the stack, copying the full stack. It's highly unlikely that the stack is swapped out because the stack is used a lot. So in the LIRU algorithms, it's going to be always the most recently used, whatever. So the idea here is this. When we ask for a stack and we go into the ptrace path and this is where I'm going to need input and discussion and maybe discuss it here offline. And if someone wants to please email me that would like to be involved in this. We are going to now do that lookup for like the Orc on Wine lookup. The problem here is that table is a elf section. So there's a few things about this. Now we talked about just get user pages. You know what? Honestly what I would love to have is that the S frame section is a loadable address and this is where I don't know how it works. In user space, from what I understand, when you execute something, it will just say, okay, here's where everything's mapped but doesn't update the page tables. When you go to execute and the page table doesn't exist, you take a page full, goes into the kernel, the kernel looks at the VMA and says, hey, this is code from this file, goes finds the file, maps it in and into that location and then goes back to user space and it just keeps going on until it falls off the page and then does it again. Maybe you have optimizations that pull in more than just one page, who knows. The idea here is I want the same feature with S frame. So the S frame will not be mapped until it's used. So we come into this point. Now yes, it will cause that Heisenberg effect where the tracing will slow down the application. The thing is, once it's mapped in it's seldom likely to be mapped out. So it will only have an initial hit. And yes, if you're doing profiling you might see a little blurb and then maybe we could write some code to say just let it go for like a little bit and then everything else. I mean, it just sounds like such a rare event that the stack gets swapped out. But that's not what we're having a worry about. That we probably want to know about that. I mean, I'm not saying that no, don't fall to just like keep it swapped out. That's fine, let's take a slow trace event but get the stack. But I'm just saying that we should give this information to the user so that like, so they know that this stack will stop talking to them. So this happened, we could do that. Okay, no, that's actually a good point. That's actually something we get added to the infrastructure. We get added to the perf infrastructure or whatnot. Saying that if we do take a page fall that we record it and time it and then actually send that information up to perf and the user space can then say, oh, this little blurb here is due to our tracing and try to fix it. So that actually is a very good point, John. Please mark that down because I'm not gonna remember it. So, hey, it's recorded, right? See, what are you just trying to do? Is this going to get rid of that awful patch to add build IDs to every struct file? So the build ID, oh wait. There was a patch that wanted to add build ID to every single struct file. Please tell me what you're working on, we'll get rid of that. Well, there's a struct file for, or which struct file? Oh, I know that guy. Every single struct file. They wanted to add a pointer to store a build ID. Yeah, I saw that. I never understood the purpose of it. And I don't know if this is good. Was it by Google? Was it? It was Giri also. Yeah, I know what it is. So, okay, so, yeah, yeah, yeah. Would you want to pass the mic over? Do you want to respond to that? Sure. Sure or no? So, yeah, I guess the reason for the build ID and the file object might be for bigger discussion, I guess we covered it in that email discussion. I'm not sure if this could be actually, this could help with that in some way. The problem is that we would like to have the build ID information like available in the context where it's really hard to get. Like in NMI, we can try to read it, but it's not reliable. So, the reason for that was that we tried to read it at the page loading time, BMA loading time, and store it in the file where we can access it later. Yeah, I'm not sure where this is going for this table if that information will be available then at some point. The point with the build ID, we would like to have it prepared so we can actually have it available in the context where it's really hard to get. Was this build ID for something to do with mapping, knowing which, so build ID is like this unique ID of the application. So, later on, you can actually identify like debug info directly for the application that you are on. So, would please give Mike the mic. Thank you, Steve. So, if Steve builds this infrastructure to go to the ptrace pass, you can access the build ID from there, right? It's not in any of my context, it's normal kernel context and you can do pretty much whatever you'd like to. So, okay, do you want to continue this conversation or are you going to continue with this S-frame? Yeah, yeah, okay. I'll go with the S-frame. So, my dream thing for this point right here is that the S-frame, which is a section in ELF is treated almost like normal text sections and data sections that are in the file so that I don't know how the kernel would work. Is there, how is that done in kernel? I know there's get user pages, but if I want to simulate a, like this is actually an execution that actually maps in and I could actually do something like user space where this code I'm wanting to touch and I want you to map it in. I think you're making these two complicated. I think all you really want, you don't necessarily need to use get user pages, right? You just want to access some bytes which are in a file somewhere. Yes. You can just go to the, you can ask the page cache, please read these bytes for me and it will do that. Okay. And it never gets mapped into user space at all. We don't play with the page tables. You can just get those bytes out of the page cache. Okay, so that's actually pretty good but it's going to have some tricks that's coming up. Okay. But no, actually this is the thing. I might actually actually ping you about more information about this. I'm more than happy to help you with this. Thank you, because that's the whole idea. I have to do that binary search in a file that could be huge. I mean this will be, I plan on having Chrome built with this. And that's going to be a several meg S-frame section that's going to have to do a binary search to find things for these lookup tables. And it's going to be sparse. It's not going to pull in everything. So I don't want the full page locked in. By the way, Indu did do, she's the one that by the way, I just want to let you know why she's up here. She implemented the S-frame logic on the GCC side so in Benutil. So she's completed that. I was so excited to see it. I've already compiled and she's done it. And she even has a proof of concept on the kernel side. So that's, so she sent it that and it does things, but it's just to see if it works. That's all it did. And she designed the format too. Yes, oh, and she designed the format of the S-frame file too. So that's, she's done a lot. So appreciate it. Well it's not going to replace optitool. Optitool, well actually, technically we could make S, the kernel use it. That's actually something we could, instead of having an optitool do it, we could actually, since it's a big build thing, if the compiler is already making this frame, then I know you want it. Yeah, so I think the kernel has these two things which will be problem, inline assembly and handwritten assembly. So even if, so good thing is that if you do write CFIs correctly for these stubs, then you will have correct S-frame information generated for it. But as far as I understand, there are non-standard stack usages in these, and so if there is non-standard stack usage in the sense that there is a specific register that you're using to say that this is where my stack, stack pointers are going to be stashed, that's not something that S-frame can represent. It has to be, so S-frame doesn't say that I identify the stack pointer register for you. Across ABI's, it just says, the unwinded will find out whatever that ABI is, the unwinded knows what that stack pointer is. So cutting it all short, no. For kernel space, we'll have to see whether unwinding through these portions of the kernel where you're using the stack in a non-standard way is it very important? If not, then yes, it could be used. If it is important, then it will not be able to cover those parts in the form it is. And I think it will be harder to even, even if we go that route that if we do want to support it in S-frame, I think it will bloat up the format. But again, we can talk more depending on how important that part of the kernel is. It could maybe simplify S-tool. So we could actually build a S-frame and then S-tool could just look at the S-frames instead of having to do its own analysis. So from where it is used, S-tool could actually say, hey, S-frame, I'll just use this data and create my tables with that. And then throw it out because we don't need to keep it. So yes, I need to have that so we could do the quick search. Question? Or is this question, yes? Yes, so Steve, I was just thinking like, I like Matthew's idea of the calling the address space operations, find us a page cache. Another like plan B, if we don't want to complicate the ptrace path could be on the first NMI. Obviously, you're getting the kernel stack, but you need the user. So you could store in the perf ring buffer itself that you need information about this file. And then in perf, you could have perf call back into the kernel and load the S-frame. How's that going to help F-trace? Oh yeah, F-trace. I thought you were dealing with perf and... No, actually, I know. F-trace, BPF, anyone else using it? No, this is something that... You could make trace command... No, but how does Echo and Cat do that? Yeah, busybox is gonna... Yes, never, this is going to work for busybox, yes. Yeah, I was wondering, you said that there could be megabytes and you're doing a binary search. So if we did that by calls to some page cache API it wouldn't be that much slower than if you could just go through the page tables. Oh, it should be a lot quicker. And the advantage of doing it by calling into the page caches that you can control directly is you can control the page caches. You can say, hey, please do read ahead for these things. So you could actually submit not just one IO but if you're doing a binary search you could say, I'm gonna want these three pages. Please start IO on all three of them and basically you're prefetching a level ahead of where you want to go. So there's lots of interesting options once you're playing some of those kinds of games. Okay, and since we got the five minute thing I'm gonna try to go a little bit. Some of the, there's a lot of things here. This is the first thing. If we get this in, this is great. But then we have this issue, the file offset issue. So in the file, so where main is, and this is actually real numbers, I actually did a little program and ran it. I do a file offset in the text file or whatever. It says, text file offset or whatever in the section is one, one, three, nine. And the main actually printed the address of main. So I just ran it and printed it and I got that memory offset from there. Of course, you know, it's one of those things if you have the relocatable every time. So I ran this every time and you got a different number every single time. The one, three, nine stayed the same but everything else changed. I want, this is the one that, that crazy, the crazy number here is going to be what is going to be in that stack trace. How do I convert that to main? You subtract it from the, you subtract the VM, VMA, VM offset from it and you get the answer you want. Oh, do you? Yeah, I can get you that. That's a line code. So it's like from this? Yes. Or I have that. I can do that for you. Awesome, that actually great. So I don't know if you wanna go over this at all. Yeah, I had these two quick comments. I think the second one can be left out in interest of time. The first one is that this format is unaligned on disk and I know Colonel has a very specific thing around unaligned accesses. So there are three main components to the S-frame section. There is S-frame header, function descriptor entries and frame room entries. Oh, we flipped to the next slide. Yeah, so going back, you know, S-frame header, there is no problem because the members of this structure are naturally aligned and the function descriptor entries are 17 bytes. So you start off in the memory and at some point these will be unaligned accesses. All these accesses can be managed. I mean, you could write the API so that you know that if you are doing unaligned access, you go by it and then you could still read for when they are naturally aligned and so on. So it is possible to do it, you know, in these APIs. But I did want to point out that this will be done something like this. You will have meme copies and weird looking casts and stuff, but so, and the, because there is no other alternative. If you go to the route that this has to be aligned, I think it will blow it up the format because we really try to do many compactness related optimizations that if it is just a number like 16 that I have to encode, I'll use only one byte in the format. So it is natural for this format and it is best, it is in the best interest of this format to be unaligned. So I think it should remain like that and we plan to handle all of this in the APIs that we have. That's it, I think. Yeah, and that, I think we can handle it. She just wanted to make sure we pointed that out and let me know that. Here's some little things that we have to look out in the future by the time, but this is like I said, if I could just get this part in, that would be awesome. But we need a way of handle DL open. That is, we not quite have a file, but we may have to have a system call to say that here's the S frame for this file, you know, to tell us that. JIT, how do we handle JIT? So that's going to be very interesting because that's, we have to find a way of saying kind of like here's an S frame for this logic that has no file back, backing stuff. One thing I'm like saying is like, is there, you know, maybe passing the file names into the trace buffer, but I don't think you guys really care so much about that, but here's another thing, is could we actually get the symbol names somehow? So if we have the symbol L file, or if we could do some sort of logic to say, hey, I got this address, can I actually look up in the symbol team or I don't know if this door for something or if we could have another extension to S frame or something, maybe this is on your side that we could say, here, by the way, here's also the functions, not only is that the, yes, someone's back. So if I understand correctly, you already have to parse like the L format to even identify the section in the file and then do the binary search, so you already have to identify the section somehow, so you could identify the other ones, right? Well, yeah, but that's done already at the loading of the L file. So binLF parses it, so we just have to add the S frame, that's another thing I would say, we need to actually add the code in the bin function or something right now, automatically, yes, so. We'll be in the map info of G-Lipsy. So basically, G-Lipsy will load a shared object or whatever and then G-Lipsy internally it keeps, it has a linked list of map descriptions. So what you need is the kernel to have access to the map. Yeah, that's true, yes. So you don't have to parse there. But we have to define a form, like I mean this is something that the kernel and G-Lipsy does not have any defined specifications, so there has to be a specification that we could follow, that we don't break user space. One thing I think I don't think you mentioned or any of that S frame that she implemented is a versioning, so we can actually, actually if we wanna add to it, we can actually increase like the version of S frame and let the kernel know like, oh, this is a different version, so we actually can change the S frame format if we need to in the future. So that's basically I think I covered pretty much everything. Any other questions? And yes, Matthew, I'm looking forward to working with you, so we really, really want this in, yes. Actually, talking about the map info and everything, the S frame information, it lives in its own segment and the segment is typically in a shared object, right, in a library, is that a problem? At least shared amongst, you know, actually it's better, right, I guess. If the loader has discarded it, I mean, I can't work magic, I can't bring it back to the dead. So I'm looking forward, hopefully anyone wants to help out, we're gonna try to like keep track and this is why it's here, so thank you very much for your time and listening and thank you, and also thank you, Indu. Thank you.