效能優化之拋棄Calendar

佔小狼發表於2018-06-20

目前在做限流相關的需求,有這麼一個限流策略,和使用者相關,當系統發生故障時,允許一個非核心介面按照使用者的百分比進行限流,如果完全按照UUID進行hash,那麼每次都是限制同一批的使用者,如果在UUID的基礎上加上當天的日期,那麼就可以有效的避免這個問題。

所以在這個需求中,每次請求都需要拿到當前的日期,不過精確到天即可。 嗖~的一下,完成了如下程式碼

Calendar calendar = Calendar.getInstance();
String time = "" + calendar.get(Calendar.YEAR) + calendar.get(Calendar.MONTH) +calendar.get(Calendar.DAY_OF_MONTH);
複製程式碼

很簡單是不是,不過寫完之後,很快就被業務同學diss了,Calendar效能太差了,在QPS很高的情況下,會使介面的999線劣化。

QPS高的業務真是惹不起... (丟)

為什麼Calendar不行,因為每次請求都要建立一個Calendar例項,這個建立過程比較的耗時(qps低的時候可以忽略這種消耗),但是做基礎元件的,應該考慮各種場景。

因為只需要獲取到與天相關資料,所以想到了另一個簡單的解決方案

private static final int DAY_MILLIS = 24 * 60 * 60 * 1000;
long day = System.currentTimeMillis() / DAY_MILLIS;
複製程式碼

通過當前的時間戳(毫秒級別),除以一天的毫秒數,得到的結果就是從1970 到今天經歷過的天數,這完全符合當前的需求。

這個解決方案,只是恰好可以滿足這種需求,對於其它更復雜一點的需求,我這裡推薦使用Joda Time元件。

下面通過Openjdk的JMH類庫,對上述三種情況進行效能基準測試,還沒有接觸過JMH的同學,可以在官網上進行學習,傳送門

@OutputTimeUnit(TimeUnit.NANOSECONDS)
@BenchmarkMode(Mode.AverageTime)
public class Main {

    static int millis = 24 * 3600 * 1000;

    public static void main(String[] args) throws Exception {
        Options options = new OptionsBuilder().include(Main.class.getName()).forks(1).build();
        new Runner(options).run();
    }

    @Benchmark
    @Threads(5)
    public void runCalendar() {
        Calendar calendar = Calendar.getInstance();
    }

    @Benchmark
    @Threads(5)
    public void runJoda() {
        DateTime dateTime = new DateTime();
    }

    //
    @Benchmark
    @Threads(5)
    public void runSystem() {
        long result = System.currentTimeMillis() / millis;
    }
}
複製程式碼

使用benchmark之前,需要引入相關依賴

<dependency>
    <groupId>org.openjdk.jmh</groupId>
    <artifactId>jmh-core</artifactId>
    <version>1.21</version>
</dependency>
<dependency>
    <groupId>org.openjdk.jmh</groupId>
    <artifactId>jmh-generator-annprocess</artifactId>
    <version>1.21</version>
    <scope>provided</scope>
</dependency>
複製程式碼

最終結果如下

效能優化之拋棄Calendar

這裡只是測試了Calendar和Joda物件的建立耗時,可以發現Joda的效能比Calendar整整高了10倍,真的不可忽略。

更多精彩問題,歡迎加入知識星球 460+小夥伴正在討論

效能優化之拋棄Calendar

相關文章