byte-buddy icon indicating copy to clipboard operation
byte-buddy copied to clipboard

How much time will byte-buddy slow down when one class is loading?

Open furaul opened this issue 2 years ago • 5 comments

I am using skywalking in my application, that the skywalking is based on byte-buddy to enhance my classes.

I have an application, its starting costs about 230 seconds, when I use skywalking(byte-buddy) in it, its starting costs about 400 seconds.

I have profiled my application, and I found that most of the time was spended on net.bytebuddy.dynamic.ClassFileLocator.ForClassLoader#locate(java.lang.ClassLoader, java.lang.String) java.lang.ClassLoader#getResourceAsStream in bytebuddy.

for exapmle, `---ts=2022-05-07 19:18:19;thread_name=main;id=1;is_daemon=false;priority=5;TCCL=org.springframework.boot.loader.LaunchedURLClassLoader@265c1a7c

---[4.686784ms] org.apache.skywalking.apm.dependencies.net.bytebuddy.dynamic.ClassFileLocator$ForClassLoader:locate()

    ---[4.659699ms] org.apache.skywalking.apm.dependencies.net.bytebuddy.dynamic.ClassFileLocator$ForClassLoader:locate() #419

        ---[4.631381ms] org.apache.skywalking.apm.dependencies.net.bytebuddy.dynamic.ClassFileLocator$ForClassLoader:locate()

            +---[0.004835ms] java.lang.StringBuilder:<init>() #438

            +---[0.007523ms] java.lang.String:replace() #57

            +---[min=0.006941ms,max=0.007374ms,total=0.014315ms,count=2] java.lang.StringBuilder:append() #57

            +---[0.004243ms] java.lang.StringBuilder:toString() #57

            +---[4.465411ms] java.lang.ClassLoader:getResourceAsStream() #57

            +---[0.031116ms] org.apache.skywalking.apm.dependencies.net.bytebuddy.utility.StreamDrainer:drain() #441

            +---[0.008337ms] org.apache.skywalking.apm.dependencies.net.bytebuddy.dynamic.ClassFileLocator$Resolution$Explicit:<init>() #57

            ---[0.007969ms] java.io.InputStream:close() #443`

I think that getResourceAsStream is an IO operation, is costing 4ms the duration expected?

I have thousands of getResourceAsStream that costs more than 1ms, the classes in my application is about 10000+, the TypeDescriptions in my application is about 100+, is the time that slowed down by byte-buddy expected?

furaul avatar May 07 '22 11:05 furaul

Besides, I found that most of Matchers that spend more than 1ms is HasSuperTypeMatcher(maybe 80%) and DeclaringAnnotationMatcher(maybe 20%), is this two Matchers spend more time?

furaul avatar May 07 '22 11:05 furaul

HasSuperTypeMatcher needs to load the class files of all super types of a class and this requires I/O as you state. I am not sure if Skywalking uses caches. The only approach is to cache previously looked up classes but unfortunately, Byte Buddy cannot speed up the JVM's IO. This would be something to explore with the Skywalking team.

raphw avatar May 08 '22 15:05 raphw

I have communicated with the Skywalking team, https://github.com/apache/skywalking/discussions/9005, it seems that booting performance is not their focus. And I have confirmed that the caches are enabled.

image

Since that we cannot speed up the JVM's IOs, could the times of IO be decreased? I found that the cache only effects in one class loading cycle, for example, `

interface Inter{}

class A implements Inter {}

class B implements Inter {}

` When class A is loading, getResourceAsStream(Inter) will be called first time, when class B is loading, getResourceAsStream(Inter) will be called second time, could the times of getResourceAsStream(Inter) been called decreased to one time?

On the other hand, is there any solution in JDK that when getResourceAsStream(Inter) have been called one time, the second time call of getResourceAsStream(Inter) avoids an file IO operation, like a cache, get the resource from memory that has been read by the first time call of getResourceAsStream(Inter)?

furaul avatar May 09 '22 03:05 furaul

Byte Buddy supports different cache approaches and it is common that the cache is retained between class loaders. Byte Buddy's agent builder offers such caches but it needs to be activated by the creator of the agent in question.

raphw avatar May 09 '22 07:05 raphw

Byte Buddy supports different cache approaches and it is common that the cache is retained between class loaders. Byte Buddy's agent builder offers such caches but it needs to be activated by the creator of the agent in question.

TKS, this PoolStrategy really speed up the booting of my application for 60S, maybe I could find some other ways to make the booting faster.

furaul avatar May 09 '22 12:05 furaul