Are there any opinions about whether or not to extend NMT across the JDK? This blocks https://bugs.openjdk.org/browse/JDK-8296360, and I had a PR prepared as https://github.com/openjdk/jdk/pull/10988. Originally I was hoping to get this into JDK 20, but I don't think that is realistic anymore. I am fine with postponing my work in favor of a baseline discussion, but so far there is very little discussion about this topic.
How should I proceed? Thanks, Thomas On Wed, Nov 9, 2022 at 8:12 AM Thomas Stüfe <thomas.stu...@gmail.com> wrote: > Hi Alan, > > (replaced hotspot-runtime-dev with hotspot-dev, since its more of a > general topic) > > thank you for your time! > > I am very happy to talk this through. I think native memory observability > in the JDK (and customer code!) is sorely lacking. Witness the countless > "where did my native memory go" blog articles. At SAP we have been > struggling with this topic for a long time and have come up with a mixture > of solutions. The aforementioned tracker was one, which extended our > version of NMT across the JDK. Our SapMachine MallocTracer, which allows us > to trace uninstrumented customer code, another. We even experimented with > exchanging the allocator (using jemalloc) to gain insights. But that is a > whole different topic with deep logistical implications, I don't want to > touch it here. Exchanging the allocator does not help to observe virtual > memory or the brk segment, of course. > > And to make the picture complete, another insight we currently lack is the > implicit allocator overhead, which can be very significant and is hidden by > the libc. We also have observability for that in the SapMachine, and I miss > it in OpenJDK. > > As you noticed, my original intent was just to instrument Zlib and > possibly improve tracking for DBBs. Although, thinking beyond that, another > attractive instrumentation target would be mapped NIO buffers at least. > > So I think native memory observability is important. Arguably we could > even extend observability to cover other OS resources, e.g. file handles. > If we shift code around, to java/Panama: data that move the java heap does > not need to be tracked, but other memory will always come from one of the > basic system APIs, regardless of who allocates it and where in the stack > allocation happens. Be it native JDK code, Panama, or even customer JNI > code. > > If we agree on the importance of native memory observability, then I > believe NMT is the right tool for it. It is a good tool. The machinery is > already there. It covers both C-heap and virtual memory APIs, as well as > thread stacks, and could easily be extended to cover sbrk if needed. And I > assume that whatever shape OpenJDK takes on in the future, there always > will be a libjvm.so at its core, so we will always have it. But even if > not, NMT could be separated from libjvm.so quite easily, since it has no > deep ties with the JVM. > > About coupling JVM with outside code: We don't have to directly link > against libjvm.so. We can keep things loose if the intent is to be runnable > without a JVM, or be JVM-version-agnostic. That could take the form of a > function-pointer interface like JVMTI. Or outside code could dynamically > dlsym the JVM allocation hooks. In any case gracefully falling back to > system allocation routines when necessary. > > And I agree, polluting the NMT tag space with outside meaning is ugly. I > only did it because I planned to go no further than instrumenting Zlib and > possibly DBBs. But if we take this further, my preferred solution would be > a reserved tag range or -ranges for outside use, whose inner meaning would > be opaque to the JVM. Kind of like SIGRTMIN+SIGRTMAX. Then, outside code > could register tags and their meta information with the JVM, or we find a > different way to convey the tag meaning to NMT (config files, or > callbacks). That could even be opened up for customer use. > > This also touches on another question, that of NMT tag space. NMT tags are > very useful since they allow cheap tracking without capturing call stacks. > However, tags are underused and show growing pains since they are too > one-dimensional and restrictive. We had competing interests in the past > about tag granularity. It is all over the place. We have coarse-grained > tags like "mtThread", and very fine-grained ones like "mtObjectMonitor". > There are several ways we could improve, e.g., by making them combinable > like UL does, or allowing for a hierarchy of them - either a hard-wired > limited one like "domain"+"tag", or an unlimited tree-like one. Technically > interesting since whatever the new encoding is, they still must fit into a > malloc header. I opened https://bugs.openjdk.org/browse/JDK-8281819 to > track ideas like these. > > Instrumenting Panama allocations, including the ability to tag > allocations, would be a very good idea. For instance, if we ever remove the > native Zlib layer and convert it to java using Panama, we can do the same > with Panama I do now natively - use the Zlib zalloc interface to hook in > JVM memory allocation functions. The result could be completely identical, > and the end user looking at the NMT output need never know that anything > changed. > > And that goes for all instrumentation - if today we add it to JNI code, > and that code gets removed tomorrow, we can add it to Panama code too. > Unless data structures move to the heap, in which case there is no need to > track them. > > You mentioned that NMT was more of an in-house support tool. Our > experience is different. Even though it was positioned as a tool for JVM > developers, and we never cared for the backward compatibility or > consistency, it gets used a *lot* by our customers. We have to explain its > output frequently. Also, many blog articles exist documenting its use. So, > maybe it would be okay to elevate it to a user-facing tool since it seems > to occupy that role anyway. We may also open up consumption of NMT results > via java APIs, or expose its results via MXBeans. > > If this is to be a JEP, okay, but I'm afraid it would stall things a bit. > I am interested in getting a simpler and quicker solution for older support > releases at least, possibly based on my PR. I know that would be > unconventional though. > > Thank you, > > Thomas > > > On Sun, Nov 6, 2022 at 9:31 AM Alan Bateman <alan.bate...@oracle.com> > wrote: > >> On 04/11/2022 16:54, Thomas Stüfe wrote: >> > Hi all, >> > >> > I am currently working on https://bugs.openjdk.org/browse/JDK-8296360; >> > I was preparing the final PR [1], but then Alan did ask me to discuss >> > this on core-libs first. >> > >> > Backstory: >> > >> > NMT tracks hotspot native allocations but does not cover the JDK >> > libraries (small exception: Unsafe.AllocateMemory). However, the >> > native memory footprint of JDK libraries can be significant. We have >> > no in-VM tracker for these and need tools like valgrind or our >> > SapMachine MallocTracer [2] to observe them. >> >> Thanks for starting a discussion on this as this is a topic that >> requires agreement from several areas. If this is the start of something >> bigger, where you want to have all allocation sites in the libraries >> using NMT, then I think it needs a write-up, maybe a JEP. >> >> For starters, I think it needs some agreement on using NMT for memory >> allocated outside of libjvm. You mentioned Unsafe as an exception but >> that is implemented in the VM so you get tracking for free, albeit I >> think all allocations are in the "mtOther" category. >> >> A general concern is that it creates more coupling between the VM code >> and the libraries code. As you probably know, we've removed most of the >> dependences on JVM_* functions from non-core areas over many years. So I >> think that needs consideration as I assume we don't want >> memory/allocation.hpp declaring a dozen catagories for allocations done >> in say java.desktop module for example. Maybe your proposal will be >> strictly limited to java.base but even then, do we really want the VM >> even knowing about categories that are specific to zip compression or >> decompression? >> >> There are probably longer term trends that should be part of the >> discussion too. One general trend is that "run time" is becoming more >> and more a hybrid of code in libvm and the Java libraries. Lambdas, >> module system, virtual threads implementations are a few examples in the >> last few release. This comes with many "Java on Java" challenges, >> including serviceability where users of the platform will expect tools >> to just work and won't care where the code is. NMT is probably more for >> support teams and not something that most developers will ever use but I >> think is part of the challenge of having serviceability solutions "just >> work". >> >> In addition to having more of the Java runtime written in Java, there >> will likely be less JNI code in the future. It's very possible that the >> JNI code (including the JNI methods in libzip) will be replaced with >> code that uses Panama memory and linker APIs once they are become >> permanent. The effect of that would to have a lot of the memory >> allocations be tracked in the mtOther category again. Maybe integration >> with memory tracking should be looked at in conjunction with these APIs >> and this migration. I could imagine the proposed "Arena" API >> (MemorySession in Java 19) having some integration with NMT and it might >> be interesting to look into that. >> >> So yes, this topic does need broader discussion and it might be a bit >> premature to start with a PR for libzip without talking about the bigger >> picture first. >> >> -Alan >> >> >> >>