Re: [diamon-discuss] Follow up on SFrame in JIT applications
Brian Robbins <[email protected]> Thu, 16 Nov 2023 15:58:49 -0800
| Newsgroups | dev.linux.lists.diamon-discuss |
|---|---|
| Message-ID | <20231116235849.GA24039@linuxonhyperv3.guj3yctzbm1etfxqx2vob5hsef.xx.internal.cloudapp.net> |
On Wed, Nov 08, 2023 at 11:00:23AM -0800, Indu Bhagat wrote: > [Re-sending. Apologies for duplicate copy in your inbox. Previous > message did not make it to the mailing list.] >=20 > On 9/28/23 10:39, Brian Robbins wrote: > >>Hi Indu, > >> > >>On 9/26/23 22:24, Indu Bhagat wrote: > >> > >>>I would like to follow up on your question around using SFrame in > >>>JITed code. I recall you mentioning that looking at MS exception > >>>handling may give us some insights. Unfortunately, I dont recall > >>>other pointers/references made in that conversation. Can you send me > >>>a brief summary and any pointers that you may have around this so I can > >>read up? > >> > >>Thanks for following up on my Tracing Summit question. I am adding the > >>diamon-discuss mailing list in CC so we can keep a trace of this conver= sation, > >>hopefully it's OK with you. > >> > >>I am also adding collaborators from Microsoft to this discussion. Those= were > >>present in a 2019 meeting held at Microsoft Redmond offices where I've = been > >>told about the shortcomings of the way integration between JITs and the > >>backtrace infrastructure is done in Windows. This was discussed in the > >>context of improving the backtrace infrastructure on Linux. > >> > >>Here is a link to your presentation abstract as reference to others: > >> > >>- > >>https://urldefense.com/v3/__https://nam06.safelinks.protection.outlook.= com/?url=3Dhttps*3A*2F*2Ftracin__;JSUl!!ACWV5N9M2RV99hQ!PXCZnoInFiL0_ATh0jN= Tdnr7pMAM7f6iODT-lcbI07-m5gK8GIk7Fx0pRDm9aGYmF98vgt9Ef_texEZmZ-LdFurfow$ > >>gsummit.org%2Fts%2F2023%2Fsframe%2F&data=3D05%7C01%7Cbrianrob%40 > >>microsoft.com%7Cd3d3f9d6f1864e61e02808dbbf382d7c%7C72f988bf86f141a > >>f91ab2d7cd011db47%7C1%7C0%7C638314020881735122%7CUnknown%7CT > >>WFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJ > >>XVCI6Mn0%3D%7C3000%7C%7C%7C&sdata=3Dfp2ECCRPbnsCP9WvNmV4GM% > >>2Bd1pkkG8vc8dUtFqNQGEw%3D&reserved=3D0 (abstract) > >>- > >>https://urldefense.com/v3/__https://nam06.safelinks.protection.outlook.= com/?url=3Dhttps*3A*2F*2Ftracin__;JSUl!!ACWV5N9M2RV99hQ!PXCZnoInFiL0_ATh0jN= Tdnr7pMAM7f6iODT-lcbI07-m5gK8GIk7Fx0pRDm9aGYmF98vgt9Ef_texEZmZ-LdFurfow$ > >>gsummit.org%2Fts%2F2023%2Ffiles%2FSFrame_TracingSummit2023.pdf&dat > >>a=3D05%7C01%7Cbrianrob%40microsoft.com%7Cd3d3f9d6f1864e61e02808dbb > >>f382d7c%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C6383140208 > >>81743792%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoi > >>V2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7C&sdata=3DwI > >>JwUw4fktvyJ5Rcnn%2F5j38TcRFr8wSWSr5omF8OlQU%3D&reserved=3D0 > >>(slides) > >> > >>For context, I've been discussing with Indu how we should extend the SF= rame > >>section (generated by GNU binutils, currently designed to augment the E= LF > >>binaries with additional sections which contain relevant frame informat= ion > >>permitting fast backtrace without frame pointers) to JITs. > >>Or at least define an ABI between applications, libraries, and the Linu= x kernel, > >>which allows populating frame description information efficiently. > >> > >>I recall from our discussion at Microsoft that the way it was done on W= indows > >>ended up being a performance bottleneck for JITs. If my memory serves me > >>right, every time the JIT emits a function, it pretty much calls into t= he kernel to > >>register its existence immediately. > >> > >>I would rather see a mechanism on Linux which is similar to the rseq(2), > >>io_uring(2), and perf_open(2) system calls. Those are implemented with a > >>memory mapping between kernel and user-space. We could do something > >>similar for a JITted sframe section: Populate an empty memory mapping o= f a > >>given size, with a header which describes how many entries are populate= d. > >>Then as the JIT appends a functions, it increments the populated size w= ith a > >>store-release semantic. Mutual exclusion between multiple producers > >>updating a mapping would be left to userspace. > >> > >>I wonder if it would be acceptable for JITs to successively provide the > >>functions in increasing order of memory addresses within a mapping, so = they > >>are already sorted. > >> > >>We would also probably want to plan a tombstone bit that would be set by > >>the JIT when it needs to reclaim a function. > >> > >>Hopefully our collaborators at Microsoft will be able to provide more > >>background information on that topic, especially references to the Wind= ows > >>side of things. > >> > > > >Your recollection is correct that there are win32 APIs that are used to = register the existence of new jitted code in order for the OS unwinder to k= now how to handle the code. The functions that get used are RtlAddGrowable= FunctionTable [1], RtlGrowFunctionTable [2], RtlDeleteGrowableFunctionTabl= e [3]. > > > >The idea is that you create a growable function table in userspace that = is an array of structures that point to unwind information. When you do th= is, you're registering the array with the operating system and a range of m= emory in the process that does/will contain code. Then, when you JIT new f= unctions, you tell the OS about them by calling RtlGrowFunctionTable. As l= ong as the new functions are located at memory addresses that are higher th= an the last entry, then you can just initialize the next structure in the a= rray and call RtlGrowFunctionTable. If you do an out-of-order insert, then= you have to delete the old table, create a new one, sort the data, and reg= ister the new one with the OS. This sounds somewhat similar to the proposa= l you've specified above. > > >=20 > Its not clear to me why there is a need to tell the OS about each > new JIT function. If a "GrowableFunctionTable" is registered with > the OS, so long as the space and ordering constraints etc are > satisfied, why is there a need for the OS to know about each new > function. >=20 =46rom a review of the code, the GrowableFunctionTable has two sizes - a cu= rrent size and a maximum size. The current size is representative of the c= urrent number of valid entries in the array. When jitting a method, we gen= erate unwind information for that method and store it in the next available= slot in the array. To publish it, we call RtlGrowFunctionTable and tell i= t the size of the table (including the new entry). You could imagine a des= ign where you don't use a call into the kernel to implement this, but that'= s the way it's implemented here. >=20 > >One thing that is worth calling out is that a process can effectively ca= ll RtlAddGrowableFunctionTable to create as many tables as it wants. This = (or something that replaces this functionality) is important when it comes = to thinking about the lifetime of dynamically jitted code. For jitted code= that represents code stored in assemblies (DLLs) on disk, the lifetime of = the growable function table is generally long, and the table often doesn't = have to be re-created. However, there are cases, such as dynamically gener= ated code, where the lifetime of the jitted code is quite short, and oftent= imes, the address range gets re-used over and over by newly generated code.= In this case, it is often worthwhile to create a new growable function ta= ble for the method or set of methods that were dynamically generated togeth= er. This allows the process to delete the table when the code destroyed wi= thout having to re-create a new table for code that wasn't destroyed but ha= ppened to be part of the table. All this to say, the design point of suppo= rting multiple tables per process is an important one. > > > >If you'd like to see how the .NET runtime does this, here's a pointer to= the code that adds new entries to the existing function table: https://url= defense.com/v3/__https://github.com/dotnet/runtime/blob/7e6bd94c52b6f4d75f8= e5098e814b4ffacdd5e02/src/coreclr/vm/codeman.cpp*L228__;Iw!!ACWV5N9M2RV99hQ= !PXCZnoInFiL0_ATh0jNTdnr7pMAM7f6iODT-lcbI07-m5gK8GIk7Fx0pRDm9aGYmF98vgt9Ef_= texEZmZ-Iz4eMDQw$ . > > >=20 > Can you share what is the format of "Unwind Information" kept per > function ? Also, is a subset of information used for backtracing > also kept in the frame of each function ? >=20 Here's a pointer to the best article I can find: https://learn.microsoft.co= m/en-us/cpp/build/exception-handling-x64?view=3Dmsvc-170. If you have more= questions, I can reach out to some colleagues. I don't believe that anything is kept in the function itself. The stack wa= lker will use the IP as an input to lookup the unwind information directly. Thanks. --Brian > Thanks >=20 > >Happy to answer any questions. > > > >--Brian > > > >>Thanks! > >> > >>Mathieu > >> > >>-- > >>Mathieu Desnoyers > >>EfficiOS Inc. > >>https://urldefense.com/v3/__https://nam06.safelinks.protection.outlook.= com/?url=3Dhttps*3A*2F*2Fwww__;JSUl!!ACWV5N9M2RV99hQ!PXCZnoInFiL0_ATh0jNTdn= r7pMAM7f6iODT-lcbI07-m5gK8GIk7Fx0pRDm9aGYmF98vgt9Ef_texEZmZ-I2kCGKTw$ . > >>efficios.com%2F&data=3D05%7C01%7Cbrianrob%40microsoft.com%7Cd3d3f9d > >>6f1864e61e02808dbbf382d7c%7C72f988bf86f141af91ab2d7cd011db47%7C1 > >>%7C0%7C638314020881749505%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC > >>4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000% > >>7C%7C%7C&sdata=3Dv6XfK7SLrOAn50bL1xt78Ul1uCzcsky0vGFt3sP6vmU%3D&r > >>eserved=3D0 > > > >[1] https://urldefense.com/v3/__https://learn.microsoft.com/en-us/window= s/win32/api/winnt/nf-winnt-rtladdgrowablefunctiontable__;!!ACWV5N9M2RV99hQ!= PXCZnoInFiL0_ATh0jNTdnr7pMAM7f6iODT-lcbI07-m5gK8GIk7Fx0pRDm9aGYmF98vgt9Ef_t= exEZmZ-KJ7TjPBA$ > >[2] https://urldefense.com/v3/__https://learn.microsoft.com/en-us/window= s/win32/api/winnt/nf-winnt-rtlgrowfunctiontable__;!!ACWV5N9M2RV99hQ!PXCZnoI= nFiL0_ATh0jNTdnr7pMAM7f6iODT-lcbI07-m5gK8GIk7Fx0pRDm9aGYmF98vgt9Ef_texEZmZ-= KpAAd9Ww$ > >[3] https://urldefense.com/v3/__https://learn.microsoft.com/en-us/window= s/win32/api/winnt/nf-winnt-rtldeletegrowablefunctiontable__;!!ACWV5N9M2RV99= hQ!PXCZnoInFiL0_ATh0jNTdnr7pMAM7f6iODT-lcbI07-m5gK8GIk7Fx0pRDm9aGYmF98vgt9E= f_texEZmZ-K63L5WoQ$ >=20