性能优化之抛弃Calendar

目前在做限流相关的需求,有这么一个限流策略,和用户相关,当系统发生故障时,允许一个非核心接口按照用户的百分比进行限流,如果完全按照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和Joda对象的创建耗时,可以发现Joda的性能比Calendar整整高了10倍,真的不可忽略。

更多精彩问题,欢迎加入知识星球 460+小伙伴正在讨论

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
引用\[1\]中提到,通过min-date和max-date定义日历的范围时,需要注意范围不宜过大,否则会造成严重的性能问题。引用\[2\]和引用\[3\]中的代码示例展示了获取当前时间和获取零点时间的性能比较。根据这些引用内容,我们可以得出以下结论: 1. 在使用Calendar组件时,需要根据具体业务需求适当修改页面展现方式,以避免性能问题。\[1\] 2. 获取当前时间的性能较好,可以使用Calendar.getInstance()方法获取当前时间,并通过get方法获取年、月、日、时、分、秒等信息。\[2\] 3. 获取零点时间的性能较差,需要通过设置Calendar的时间域来实现,这会涉及到更多的操作,因此耗时较长。\[3\] 综上所述,Calendar性能取决于具体的操作和使用方式。在使用Calendar时,应根据实际需求选择合适的方法以提高性能。 #### 引用[.reference_title] - *1* [vant weapp日历组件性能优化 Calendar 日历添加min-date最小日期页面加载缓慢](https://blog.csdn.net/Taurus_0811/article/details/118249432)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [Calendar获取当前时间的性能比较](https://blog.csdn.net/riemann_/article/details/90649392)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值