以编程方式衡量分配
我從Heinz Kabutz撰寫的Java專家通訊中獲得了這個(gè)技巧。 (對(duì)于所有想要了解JDK內(nèi)容的Java開發(fā)人員來(lái)說(shuō),這是絕對(duì)必要的!)
特別是對(duì)于編寫低延遲代碼但對(duì)于普通Java代碼的開發(fā)人員來(lái)說(shuō),分配是您真正要避免的事情。 有關(guān)更多詳細(xì)信息,請(qǐng)參見我以前的文章“ 優(yōu)化的第一條規(guī)則 ”和“ 重新訪問(wèn)性能優(yōu)化的第一條規(guī)則:逃逸分析的效果 ”。
在本技巧之前,我一直使用分析器來(lái)計(jì)算分配,或者我想您可以使用對(duì)Runtime的調(diào)用來(lái)查看JVM已分配了多少堆內(nèi)存。
使用MBean,我們能夠查詢單個(gè)線程的分配情況。 這為我們提供了一種非常精確的方法來(lái)測(cè)量特定線程是否已分配以及是否分配了多少。 在為零分配進(jìn)行編碼的情況下,可以在測(cè)試中包括對(duì)該代碼的調(diào)用,斷言沒(méi)有分配。
下面是一個(gè)簡(jiǎn)單的類,您可以根據(jù)時(shí)事通訊的提示使用它。
您會(huì)注意到,構(gòu)造函數(shù)進(jìn)行了校準(zhǔn),以調(diào)整由bean本身創(chuàng)建的分配量。
還有一些防御性代碼可確保僅從單個(gè)線程調(diào)用該類。
您可以調(diào)用方法markAllocations來(lái)查找自上一個(gè)標(biāo)記以來(lái)已分配的字節(jié)數(shù)。 printAllocations是一種方便的方法,用于打印從最后一個(gè)標(biāo)記到標(biāo)準(zhǔn)輸出的分配。 構(gòu)造類后,將reset分配分配,調(diào)用reset或調(diào)用markAllocations或printAllocations 。
在測(cè)試中,您可能具有以下代碼:
Allocations measure = new AllocationsMeasure(); ... //critical code ... assertEquals(0, measure.markAllocations());以下是AllocationsMeasure完整代碼:
package util;import javax.management.*; import java.lang.management.ManagementFactory; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong;/*** Created by daniel on 06/07/2015.*/ public class AllocationMeasure {private final String GET_THREAD_ALLOCATED_BYTES = "getThreadAllocatedBytes";private final String[] SIGNATURE = new String[]{long.class.getName()};private final String threadName = Thread.currentThread().getName();private final Object[] PARAMS = new Object[]{Thread.currentThread().getId()};private MBeanServer mBeanServer;private ObjectName name = null;private AtomicLong allocated = new AtomicLong();private long BYTES_USED_TO_MEASURE = 336;private long tid;public AllocationMeasure(){tid = Thread.currentThread().getId();try {name = new ObjectName(ManagementFactory.THREAD_MXBEAN_NAME);mBeanServer = ManagementFactory.getPlatformMBeanServer();} catch (MalformedObjectNameException e) {e.printStackTrace();}//calibratefor (int i = 0; i < 100; i++) {//run a few loops to allow for startup anomaliesmarkAllocations();}long callibrate = threadAllocatedBytes();BYTES_USED_TO_MEASURE = threadAllocatedBytes()-callibrate;reset();}public void reset(){if(tid != Thread.currentThread().getId())throw new AssertionError("AllocationMeasure must not be used over more than 1 thread.");allocated.set(threadAllocatedBytes());}private long threadAllocatedBytes() {try {return (long)mBeanServer.invoke(name,GET_THREAD_ALLOCATED_BYTES,PARAMS,SIGNATURE);} catch (Exception e) {throw new IllegalArgumentException(e);}}public long markAllocations() {if(tid != Thread.currentThread().getId())throw new AssertionError("AllocationMeasure must not be used over more than 1 thread.");long mark1 = ((threadAllocatedBytes()-BYTES_USED_TO_MEASURE) - allocated.get());allocated.set(threadAllocatedBytes());return mark1;}public void printAllocations(CharSequence marker) {if(tid != Thread.currentThread().getId())throw new AssertionError("AllocationMeasure must not be used over more than 1 thread.");long mark1 = ((threadAllocatedBytes()-BYTES_USED_TO_MEASURE) - allocated.get());System.out.println(threadName + " allocated " + marker + ":" + mark1);allocated.set(threadAllocatedBytes());}public static void main(String[] args) {String TEST = "Test";AllocationMeasure allocationMeasure = new AllocationMeasure();for (int i = 0; i < 1000; i++) {allocationMeasure.reset();//allocationMeasure = new AllocationMeasure();long mark1 = allocationMeasure.markAllocations();if(mark1 >0 )System.out.println("m1:" + mark1);}allocationMeasure.printAllocations(TEST);} }翻譯自: https://www.javacodegeeks.com/2015/07/measuring-allocations-programmatically.html
總結(jié)
- 上一篇: B 站将引进多部 HBO 作品,《黑暗物
- 下一篇: 努比亚 Z50 手机获推 MyOS14