美文网首页
Linux 进度调度测试

Linux 进度调度测试

作者: 蓝笔头 | 来源:发表于2021-07-20 19:08 被阅读0次

调度器的参数

参数简介:

  • sched_min_granularity_ns:CFS 设定了进程占用 CPU 的最小时间值,sched_min_granularity_ns,正在 CPU 上运行的进程如果不足这个时间是不可以被调离 CPU 的。
  • sched_latency_ns:设定一个调度周期(sched_latency_ns),目标是让每个进程在这个周期内至少有机会运行一次,换一种说法就是每个进程等待 CPU 的时间最长不超过这个调度周期;然后根据进程的数量,大家平分这个调度周期内的 CPU 使用权,由于进程的优先级即 nice 值不同,分割调度周期的时候要加权。

如果进程数量太多的话,就会造成 CPU 时间片太小,如果小于 sched_min_granularity_ns 的话就以 sched_min_granularity_ns 为准;而调度周期也随之不再遵守 sched_latency_ns,而是以(sched_min_granularity_ns * 进程数量)的乘积为准。

实际配置:

$ uname -a
Linux dev.xxx.net 4.19.0-17-amd64 #1 SMP Debian 4.19.194-1 (2021-06-10) x86_64 GNU/Linux
$ cat /proc/sys/kernel/sched_min_granularity_ns
3000000
$ cat /proc/sys/kernel/sched_latency_ns
24000000

单位转换:

  • 1 (ms) = 1000 * 1000 (ns)
  • 3000000 (ns) = 3(ms)
  • 24000000 (ns) = 24(ms)

测试代码

import java.time.LocalDateTime;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;


public class TestThread {
    private static int threadCount = 10;
    private static int calcCount = 10000;

    public static void main(String[] args) throws InterruptedException {
        if (args.length >= 1) {
            threadCount = Integer.parseInt(args[0]);
        }
        if (args.length >= 2) {
            calcCount = Integer.parseInt(args[1]);
        }

        System.out.println(LocalDateTime.now());
        System.out.println(Runtime.getRuntime().availableProcessors());
        ScheduledExecutorService executorService = Executors.newScheduledThreadPool(threadCount);
        for (int i = 0; i < threadCount; ++i) {
            String task = "task_" + i;
            System.out.println(LocalDateTime.now() + " -- [" + task + "] 分配线程");
            executorService.scheduleAtFixedRate(() -> spin(task, calcCount), 0, 500, TimeUnit.MILLISECONDS);
        }
    }

    public static void spin(String task, int count) {
        System.out.println(LocalDateTime.now() + " -- [" + task + "] spin 开始, 当前线程:" + Thread.currentThread().getName());
        long startTime = System.currentTimeMillis();
        long tempStartTime = startTime;

        long num = 1;
        long max = 0;
        max = Math.max(System.currentTimeMillis() - tempStartTime, max);
        for (int i = 0; i < count; ++ i) {
            num = num * 3;
            max = Math.max(System.currentTimeMillis() - tempStartTime, max);

            tempStartTime = System.currentTimeMillis();
        }
        long stopTime = System.currentTimeMillis();
        System.out.println(LocalDateTime.now() + " -- [" + task + "] spend time = " + (stopTime - startTime) + "(ms) num = "
            + num + " 当前线程:" + Thread.currentThread().getName() + "max = " + max);

    }
}

jmx 参数:

-Dcom.sun.management.jmxremote.port=12345 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false

线程数量:1

$ java TestThread 1 50000
2021-07-20T21:22:04.818
1
2021-07-20T21:22:04.825 -- [task_0] 分配线程
2021-07-20T21:22:04.847 -- [task_0] spin 开始, 当前线程:pool-1-thread-1
2021-07-20T21:22:04.866 -- [task_0] spend time = 19(ms) num = -246746203963084735 当前线程:pool-1-thread-1max = 1
2021-07-20T21:22:05.343 -- [task_0] spin 开始, 当前线程:pool-1-thread-1
2021-07-20T21:22:05.357 -- [task_0] spend time = 13(ms) num = -246746203963084735 当前线程:pool-1-thread-1max = 1
2021-07-20T21:22:05.843 -- [task_0] spin 开始, 当前线程:pool-1-thread-1
2021-07-20T21:22:05.851 -- [task_0] spend time = 8(ms) num = -246746203963084735 当前线程:pool-1-thread-1max = 1
2021-07-20T21:22:06.343 -- [task_0] spin 开始, 当前线程:pool-1-thread-1
2021-07-20T21:22:06.351 -- [task_0] spend time = 8(ms) num = -246746203963084735 当前线程:pool-1-thread-1max = 1
2021-07-20T21:22:06.843 -- [task_0] spin 开始, 当前线程:pool-1-thread-1
2021-07-20T21:22:06.851 -- [task_0] spend time = 8(ms) num = -246746203963084735 当前线程:pool-1-thread-1max = 1
2021-07-20T21:22:07.343 -- [task_0] spin 开始, 当前线程:pool-1-thread-1
2021-07-20T21:22:07.350 -- [task_0] spend time = 7(ms) num = -246746203963084735 当前线程:pool-1-thread-1max = 1
2021-07-20T21:22:07.842 -- [task_0] spin 开始, 当前线程:pool-1-thread-1
2021-07-20T21:22:07.850 -- [task_0] spend time = 7(ms) num = -246746203963084735 当前线程:pool-1-thread-1max = 1
2021-07-20T21:22:08.343 -- [task_0] spin 开始, 当前线程:pool-1-thread-1
2021-07-20T21:22:08.351 -- [task_0] spend time = 8(ms) num = -246746203963084735 当前线程:pool-1-thread-1max = 1
2021-07-20T21:22:08.843 -- [task_0] spin 开始, 当前线程:pool-1-thread-1
2021-07-20T21:22:08.850 -- [task_0] spend time = 7(ms) num = -246746203963084735 当前线程:pool-1-thread-1max = 1
2021-07-20T21:22:09.343 -- [task_0] spin 开始, 当前线程:pool-1-thread-1
2021-07-20T21:22:09.351 -- [task_0] spend time = 8(ms) num = -246746203963084735 当前线程:pool-1-thread-1max = 1

通过 1 个线程的测试,可以发现执行 50000 次循环大概要 8ms

线程数量:3

$ java TestThread 3 50000
2021-07-20T21:27:14.824
1
2021-07-20T21:27:14.831 -- [task_0] 分配线程
2021-07-20T21:27:14.849 -- [task_1] 分配线程
2021-07-20T21:27:14.850 -- [task_2] 分配线程
2021-07-20T21:27:14.850 -- [task_0] spin 开始, 当前线程:pool-1-thread-1
2021-07-20T21:27:14.851 -- [task_1] spin 开始, 当前线程:pool-1-thread-2
2021-07-20T21:27:14.854 -- [task_2] spin 开始, 当前线程:pool-1-thread-3
2021-07-20T21:27:14.883 -- [task_0] spend time = 32(ms) num = -246746203963084735 当前线程:pool-1-thread-1max = 1
2021-07-20T21:27:14.883 -- [task_1] spend time = 32(ms) num = -246746203963084735 当前线程:pool-1-thread-2max = 1
2021-07-20T21:27:14.886 -- [task_2] spend time = 32(ms) num = -246746203963084735 当前线程:pool-1-thread-3max = 1
2021-07-20T21:27:15.350 -- [task_0] spin 开始, 当前线程:pool-1-thread-1
2021-07-20T21:27:15.350 -- [task_1] spin 开始, 当前线程:pool-1-thread-2
2021-07-20T21:27:15.350 -- [task_2] spin 开始, 当前线程:pool-1-thread-3
2021-07-20T21:27:15.403 -- [task_2] spend time = 53(ms) num = -246746203963084735 当前线程:pool-1-thread-3max = 1
2021-07-20T21:27:15.404 -- [task_0] spend time = 54(ms) num = -246746203963084735 当前线程:pool-1-thread-1max = 1
2021-07-20T21:27:15.405 -- [task_1] spend time = 55(ms) num = -246746203963084735 当前线程:pool-1-thread-2max = 1
2021-07-20T21:27:15.849 -- [task_0] spin 开始, 当前线程:pool-1-thread-1
2021-07-20T21:27:15.850 -- [task_1] spin 开始, 当前线程:pool-1-thread-3
2021-07-20T21:27:15.850 -- [task_2] spin 开始, 当前线程:pool-1-thread-2
2021-07-20T21:27:15.857 -- [task_0] spend time = 8(ms) num = -246746203963084735 当前线程:pool-1-thread-1max = 1
2021-07-20T21:27:15.860 -- [task_2] spend time = 10(ms) num = -246746203963084735 当前线程:pool-1-thread-2max = 1
2021-07-20T21:27:15.860 -- [task_1] spend time = 10(ms) num = -246746203963084735 当前线程:pool-1-thread-3max = 1
2021-07-20T21:27:16.349 -- [task_0] spin 开始, 当前线程:pool-1-thread-1
2021-07-20T21:27:16.350 -- [task_1] spin 开始, 当前线程:pool-1-thread-2
2021-07-20T21:27:16.350 -- [task_2] spin 开始, 当前线程:pool-1-thread-3
2021-07-20T21:27:16.357 -- [task_0] spend time = 8(ms) num = -246746203963084735 当前线程:pool-1-thread-1max = 1
2021-07-20T21:27:16.358 -- [task_1] spend time = 7(ms) num = -246746203963084735 当前线程:pool-1-thread-2max = 1
2021-07-20T21:27:16.358 -- [task_2] spend time = 8(ms) num = -246746203963084735 当前线程:pool-1-thread-3max = 1
2021-07-20T21:27:16.849 -- [task_0] spin 开始, 当前线程:pool-1-thread-1
2021-07-20T21:27:16.850 -- [task_1] spin 开始, 当前线程:pool-1-thread-2
2021-07-20T21:27:16.850 -- [task_2] spin 开始, 当前线程:pool-1-thread-3
2021-07-20T21:27:16.856 -- [task_0] spend time = 7(ms) num = -246746203963084735 当前线程:pool-1-thread-1max = 1
2021-07-20T21:27:16.858 -- [task_1] spend time = 8(ms) num = -246746203963084735 当前线程:pool-1-thread-2max = 1
2021-07-20T21:27:16.858 -- [task_2] spend time = 8(ms) num = -246746203963084735 当前线程:pool-1-thread-3max = 1
2021-07-20T21:27:17.349 -- [task_0] spin 开始, 当前线程:pool-1-thread-1
2021-07-20T21:27:17.350 -- [task_1] spin 开始, 当前线程:pool-1-thread-2
2021-07-20T21:27:17.350 -- [task_2] spin 开始, 当前线程:pool-1-thread-3
2021-07-20T21:27:17.356 -- [task_0] spend time = 7(ms) num = -246746203963084735 当前线程:pool-1-thread-1max = 1
2021-07-20T21:27:17.357 -- [task_1] spend time = 7(ms) num = -246746203963084735 当前线程:pool-1-thread-2max = 1
2021-07-20T21:27:17.358 -- [task_2] spend time = 8(ms) num = -246746203963084735 当前线程:pool-1-thread-3max = 1

3 个线程,一个线程执行 8ms,符合 sched_latency_ns = 24ms 的值,说明在 sched_latency_ns 范围内每个线程都会执行一次,即不会被切换上下文。

后面输出的日志也说明了这一点。

线程数量:4

$ java TestThread 4 50000
2021-07-20T21:30:23.714
1
2021-07-20T21:30:23.721 -- [task_0] 分配线程
2021-07-20T21:30:23.740 -- [task_1] 分配线程
2021-07-20T21:30:23.741 -- [task_2] 分配线程
2021-07-20T21:30:23.742 -- [task_0] spin 开始, 当前线程:pool-1-thread-1
2021-07-20T21:30:23.743 -- [task_1] spin 开始, 当前线程:pool-1-thread-2
2021-07-20T21:30:23.744 -- [task_3] 分配线程
2021-07-20T21:30:23.747 -- [task_2] spin 开始, 当前线程:pool-1-thread-3
2021-07-20T21:30:23.750 -- [task_3] spin 开始, 当前线程:pool-1-thread-4
2021-07-20T21:30:23.778 -- [task_0] spend time = 36(ms) num = -246746203963084735 当前线程:pool-1-thread-1max = 1
2021-07-20T21:30:23.779 -- [task_3] spend time = 29(ms) num = -246746203963084735 当前线程:pool-1-thread-4max = 1
2021-07-20T21:30:23.781 -- [task_1] spend time = 38(ms) num = -246746203963084735 当前线程:pool-1-thread-2max = 1
2021-07-20T21:30:23.781 -- [task_2] spend time = 34(ms) num = -246746203963084735 当前线程:pool-1-thread-3max = 1
2021-07-20T21:30:24.241 -- [task_0] spin 开始, 当前线程:pool-1-thread-1
2021-07-20T21:30:24.241 -- [task_1] spin 开始, 当前线程:pool-1-thread-4
2021-07-20T21:30:24.242 -- [task_2] spin 开始, 当前线程:pool-1-thread-2
2021-07-20T21:30:24.245 -- [task_3] spin 开始, 当前线程:pool-1-thread-3
2021-07-20T21:30:24.288 -- [task_1] spend time = 47(ms) num = -246746203963084735 当前线程:pool-1-thread-4max = 1
2021-07-20T21:30:24.299 -- [task_0] spend time = 58(ms) num = -246746203963084735 当前线程:pool-1-thread-1max = 1
2021-07-20T21:30:24.299 -- [task_2] spend time = 57(ms) num = -246746203963084735 当前线程:pool-1-thread-2max = 1
2021-07-20T21:30:24.300 -- [task_3] spend time = 55(ms) num = -246746203963084735 当前线程:pool-1-thread-3max = 1
2021-07-20T21:30:24.740 -- [task_0] spin 开始, 当前线程:pool-1-thread-1
2021-07-20T21:30:24.741 -- [task_1] spin 开始, 当前线程:pool-1-thread-4
2021-07-20T21:30:24.742 -- [task_2] spin 开始, 当前线程:pool-1-thread-2
2021-07-20T21:30:24.745 -- [task_3] spin 开始, 当前线程:pool-1-thread-3
2021-07-20T21:30:24.749 -- [task_0] spend time = 9(ms) num = -246746203963084735 当前线程:pool-1-thread-1max = 1
2021-07-20T21:30:24.752 -- [task_1] spend time = 11(ms) num = -246746203963084735 当前线程:pool-1-thread-4max = 1
2021-07-20T21:30:24.754 -- [task_2] spend time = 12(ms) num = -246746203963084735 当前线程:pool-1-thread-2max = 1
2021-07-20T21:30:24.755 -- [task_3] spend time = 10(ms) num = -246746203963084735 当前线程:pool-1-thread-3max = 1
2021-07-20T21:30:25.240 -- [task_0] spin 开始, 当前线程:pool-1-thread-1
2021-07-20T21:30:25.241 -- [task_1] spin 开始, 当前线程:pool-1-thread-4
2021-07-20T21:30:25.241 -- [task_2] spin 开始, 当前线程:pool-1-thread-2
2021-07-20T21:30:25.245 -- [task_3] spin 开始, 当前线程:pool-1-thread-3
2021-07-20T21:30:25.248 -- [task_0] spend time = 8(ms) num = -246746203963084735 当前线程:pool-1-thread-1max = 1
2021-07-20T21:30:25.249 -- [task_1] spend time = 8(ms) num = -246746203963084735 当前线程:pool-1-thread-4max = 1
2021-07-20T21:30:25.254 -- [task_2] spend time = 12(ms) num = -246746203963084735 当前线程:pool-1-thread-2max = 1
2021-07-20T21:30:25.257 -- [task_3] spend time = 12(ms) num = -246746203963084735 当前线程:pool-1-thread-3max = 5
2021-07-20T21:30:25.740 -- [task_0] spin 开始, 当前线程:pool-1-thread-1
2021-07-20T21:30:25.741 -- [task_1] spin 开始, 当前线程:pool-1-thread-4
2021-07-20T21:30:25.742 -- [task_2] spin 开始, 当前线程:pool-1-thread-2
2021-07-20T21:30:25.745 -- [task_3] spin 开始, 当前线程:pool-1-thread-3
2021-07-20T21:30:25.748 -- [task_0] spend time = 8(ms) num = -246746203963084735 当前线程:pool-1-thread-1max = 1
2021-07-20T21:30:25.750 -- [task_2] spend time = 8(ms) num = -246746203963084735 当前线程:pool-1-thread-2max = 1
2021-07-20T21:30:25.750 -- [task_1] spend time = 9(ms) num = -246746203963084735 当前线程:pool-1-thread-4max = 1
2021-07-20T21:30:25.753 -- [task_3] spend time = 8(ms) num = -246746203963084735 当前线程:pool-1-thread-3max = 1
2021-07-20T21:30:26.240 -- [task_0] spin 开始, 当前线程:pool-1-thread-1
2021-07-20T21:30:26.241 -- [task_1] spin 开始, 当前线程:pool-1-thread-2
2021-07-20T21:30:26.242 -- [task_2] spin 开始, 当前线程:pool-1-thread-4
2021-07-20T21:30:26.245 -- [task_3] spin 开始, 当前线程:pool-1-thread-3
2021-07-20T21:30:26.248 -- [task_0] spend time = 7(ms) num = -246746203963084735 当前线程:pool-1-thread-1max = 1
2021-07-20T21:30:26.249 -- [task_1] spend time = 8(ms) num = -246746203963084735 当前线程:pool-1-thread-2max = 1
2021-07-20T21:30:26.255 -- [task_2] spend time = 13(ms) num = -246746203963084735 当前线程:pool-1-thread-4max = 5
2021-07-20T21:30:26.258 -- [task_3] spend time = 12(ms) num = -246746203963084735 当前线程:pool-1-thread-3max = 1
2021-07-20T21:30:26.740 -- [task_0] spin 开始, 当前线程:pool-1-thread-1
2021-07-20T21:30:26.741 -- [task_1] spin 开始, 当前线程:pool-1-thread-2
2021-07-20T21:30:26.742 -- [task_2] spin 开始, 当前线程:pool-1-thread-4
2021-07-20T21:30:26.745 -- [task_3] spin 开始, 当前线程:pool-1-thread-3
2021-07-20T21:30:26.749 -- [task_1] spend time = 8(ms) num = -246746203963084735 当前线程:pool-1-thread-2max = 1
2021-07-20T21:30:26.749 -- [task_2] spend time = 7(ms) num = -246746203963084735 当前线程:pool-1-thread-4max = 1
2021-07-20T21:30:26.752 -- [task_3] spend time = 7(ms) num = -246746203963084735 当前线程:pool-1-thread-3max = 1
2021-07-20T21:30:26.754 -- [task_0] spend time = 13(ms) num = -246746203963084735 当前线程:pool-1-thread-1max = 1
2021-07-20T21:30:27.240 -- [task_0] spin 开始, 当前线程:pool-1-thread-1
2021-07-20T21:30:27.241 -- [task_1] spin 开始, 当前线程:pool-1-thread-4
2021-07-20T21:30:27.242 -- [task_2] spin 开始, 当前线程:pool-1-thread-3
2021-07-20T21:30:27.245 -- [task_3] spin 开始, 当前线程:pool-1-thread-2
2021-07-20T21:30:27.248 -- [task_0] spend time = 8(ms) num = -246746203963084735 当前线程:pool-1-thread-1max = 1
2021-07-20T21:30:27.249 -- [task_2] spend time = 7(ms) num = -246746203963084735 当前线程:pool-1-thread-3max = 1
2021-07-20T21:30:27.253 -- [task_3] spend time = 8(ms) num = -246746203963084735 当前线程:pool-1-thread-2max = 1
2021-07-20T21:30:27.257 -- [task_1] spend time = 16(ms) num = -246746203963084735 当前线程:pool-1-thread-4max = 8

4 个线程,一个线程执行 8ms,大于 sched_latency_ns = 24ms 的值,说明在 sched_latency_ns 范围内每个线程无法执行都一次,因此会被切换上下文。

日志中的 max=5max=8 说明发生了线程切换。

...
2021-07-20T21:30:25.257 -- [task_3] spend time = 12(ms) num = -246746203963084735 当前线程:pool-1-thread-3max = 5
...
2021-07-20T21:30:26.255 -- [task_2] spend time = 13(ms) num = -246746203963084735 当前线程:pool-1-thread-4max = 5
...
2021-07-20T21:30:27.257 -- [task_1] spend time = 16(ms) num = -246746203963084735 当前线程:pool-1-thread-4max = 8
...

系统负载

$ uptime
 10:31:23 up 262 days, 13:01,  2 users,  load average: 0.02, 0.05, 0.21

$ java TestThread 500

$ uptime
 10:34:04 up 262 days, 13:04,  2 users,  load average: 0.84, 0.31, 0.27

参考

相关文章

  • Linux 进度调度测试

    调度器的参数 参数简介: sched_min_granularity_ns:CFS 设定了进程占用 CPU 的最小...

  • Linux内核学习013——进程调度(二)

    Linux内核学习013——进程调度(二) Linux的进程调度 早期版本(1~2.4)的Linux内核中,调度程...

  • Linux内核学习014——进程调度(三)

    Linux内核学习014——进程调度(三) Linux调度算法 在Linux中,调度器是以模块方式提供的,这样可以...

  • linux中的调度

    linux系统的线程是内核线程,所以linux系统的调度是基于线程而不是基于进程的 为了进行调度,linux系统将...

  • 13. Oozie介绍

    1. Hadoop常见调度框架: (1)Linux Crontab:Linux自带的任务调度计划,在任务比较少的情...

  • Linux下优化Mysql的运行环境

    修改Linux默认的IO调度算法 linux默认的IO调度算法为cfq,需要修改为dealine,如果是SSD或者...

  • 打通Framework与Kernel-谈谈我对进程管理的理解

    Kernel:Linux学习-进程管理与调度(一)-进程描述及其生命周期Linux学习-进程管理与调度(二)-进程...

  • 各种类型的bug

    1.调度类bug,如何测试调度类问题? 2.

  • Linux 调度

    调度策略与调度类 进程包括两类: 实时进程(优先级高); 普通进程 两种进程调度策略不同: task_struct...

  • Zookeeper | 进度调度系统

    进度调度系统 背景 有一个Hadoop集群,用户不断向集群中提交任务在集群运行过程中提交的任务可能处于等待、执行、...

网友评论

      本文标题:Linux 进度调度测试

      本文链接:https://www.haomeiwen.com/subject/qyyrmltx.html