为什么Spring环境中for循环执行耗时比非Spring环境多?

新手上路,请多包涵

同样的for循环语句,在spring环境中执行和不在spring环境中执行,耗时不同。

@RestController
@RequestMapping("api/")
public class ApiV2Controller {

    @RequestMapping(value = "upload")
    public void upload() throws IOException {
        for (int i = 0; i < 10; i++) {
            long l = System.currentTimeMillis();
            encode();
            System.out.println("controller耗时:" + (System.currentTimeMillis() - l));
        }

    }

    public static void main(String[] args) throws IOException {
        for (int i = 0; i < 10; i++) {
            long l = System.currentTimeMillis();
            encode();
            System.out.println("main耗时:" + (System.currentTimeMillis() - l));
        }
    }

    private static void encode() throws IOException {
        File file = new File("C:\\Users\\admin\\Desktop\\demo.bin");
        byte[] fileBytes = Files.readAllBytes(file.toPath());
        int index = 0;
        byte[] key = "onekey;".getBytes(StandardCharsets.UTF_8);
        int keylen = key.length;
        int length = fileBytes.length;
        for (int i = 0; i < length; i++) {
            if (index >= keylen) {
                index = 0;
            }
            int diff = fileBytes[i] - key[index];
            if (diff < -128) {
                diff += 256;
            }
            fileBytes[i] = (byte) diff;
            index++;
        }
    }

代码的for循环是一个常用的用key加密文件的方法
在spring中执行耗时
controller耗时:399
controller耗时:368
controller耗时:367
controller耗时:366
controller耗时:368
controller耗时:367
controller耗时:367
controller耗时:367
controller耗时:367
controller耗时:367
使用普通的main方法耗时
main耗时:137
main耗时:118
main耗时:114
main耗时:114
main耗时:114
main耗时:116
main耗时:117
main耗时:118
main耗时:111
main耗时:113

spring中执行耗时会多2-3倍,文件大小为64Mb

很疑惑,不知道为什么会这样

求解答

阅读 838
avatarAI BotBETA

在Spring环境中,特别是当你通过Spring MVC的@RestController@RequestMapping处理HTTP请求时,相比直接在main方法中执行相同的逻辑,存在几个潜在的原因导致执行时间显著增加:

  1. Spring容器初始化:在Spring环境中,每次HTTP请求都会经历Spring容器的初始化、依赖注入等过程,尽管这些过程对于单个请求来说是微秒级别的,但在大量请求或复杂应用中可能会累积成显著的延迟。
  2. HTTP请求处理:处理HTTP请求涉及到多个层级的处理,包括网络IO、Spring MVC的DispatcherServlet、Controller的调用、数据绑定、模型渲染(尽管这里是void方法,但流程依然存在)、视图解析(尽管未使用)等。这些步骤在main方法中是不存在的。
  3. 线程管理和上下文切换:在Web服务器(如Tomcat)中,HTTP请求通常由服务器管理的线程池中的线程处理。线程管理(如线程的创建、销毁、上下文切换)以及可能的线程同步或锁等待都可能导致额外的开销。
  4. I/O性能差异:虽然这不太可能是导致如此大差异的主要原因,但不同环境下的文件系统I/O性能(如缓存、磁盘速度等)可能会有所不同。
  5. 日志和监控:Spring框架和底层服务器可能会进行额外的日志记录和监控,这些活动也会消耗时间。
  6. JVM热加载和JIT编译:在main方法中,JVM可能会更快地达到最佳性能状态(即JIT编译优化),因为main方法通常是一次性执行的。而在Web应用中,JVM需要持续运行并处理多个请求,这可能导致性能表现不同。

针对你的情况,虽然你的测试代码是在控制器中执行,但性能差异很可能是由于Spring MVC处理HTTP请求时的额外开销,以及可能存在的JVM性能优化差异。

为了更准确地评估性能,你可以考虑:

  • 在控制器中使用更精确的时间测量工具(如System.nanoTime())。
  • 分离测试,仅测量encode方法的执行时间,排除Spring MVC框架的干扰。
  • 评估并优化Spring MVC的配置和设置,以减少不必要的开销。
  • 检查和优化JVM参数,特别是与垃圾回收和JIT编译相关的参数。
  • 监控和分析系统资源使用情况,如CPU、内存和磁盘I/O,以查找可能的瓶颈。
1 个回答

环境差异很大。运行main函数和启动springboot时,jvm参数差别很大,这些差异都能影响到程序的执行性能。另外编译器在运行过程中会有一些优化,springboot和main中优化也会不一样。

宣传栏