高效,简洁的API性能测量

时间:2017-10-06 15:55:38

标签: java performance

我想集中API性能测量逻辑 - 是否有优雅,高效的解决方案?

假设我们有这个API:

public interface MyApi {
    void zero();
    Long one(String a);
    String two(Long a, Long b);
}

我想使用一个简单的测量包装器测量此API实现的性能:

public class MyApiImpl implements MyApi{
    // ...
    public Long one(String a) {
        Long start = System.nanoTime();
        try {
          return oneImpl(a);
        } finally {
           Measure.record(System.nanoTime()-start, "one", a);
        }
    }
    // ...
}

但是我没有在每个API实现中重复这个测量包装器逻辑,而是想集中它,例如,一个有效的注释将是一个优雅的解决方案:

public class MyApiImpl implements MyApi{
    // ...

    @Measure
    public Long one(String a) {
        // ...
    }

    // ...
}

具有Measure的API位于Linux开发,登台和生产环境中,并且全天候启用。有谁愿意分享好的解决方案?

注意:我特别不是在寻找“解决”这个问题的“打包软件解决方案”,无论是商业还是开源。问题是如何在呼叫站点有效和优雅地解决数据收集问题,即什么是程序化解决方案,例如,有效的注释。

1 个答案:

答案 0 :(得分:2)

我使用方面和Dropwizard指标做了类似的事情。首先为Timed注释创建一个方面,

@Aspect
@Component
public class TimedAspect {

    private MetricRegistry registry;

    @Autowired
    public TimedAspect(MetricRegistry registry) {
        this.registry = registry;
    }

    @Around("@annotation(annotation) || @within(annotation)")
    public Object generateMetric(
            final ProceedingJoinPoint pointcut,
            final Timed annotation) throws Throwable {
        Timed anno = getAnnotation(pointcut, annotation);
        String metricName = ...;
        final Timer timer = registry.timer(metricName);
        final Timer.Context context = timer.time();

        try {
            return pointcut.proceed();
        } finally {
            context.stop();
        }
    }

    ...

}

现在,您可以在班级的任何位置使用@Timed注释

public class MyApiImpl implements MyApi {
    // ...

    @Timed
    public Long one(String a) {
        // ...
    }

    // ...
}

我有一个工作示例here