• 线程池的取值(二)设计吞吐量【重点】


    (2)补充,对于任务型,比如推送,也会有一个推送延迟的要求,可用n1来压测取得其吞吐量和响应时间,对比是否在要求以内

    实测数据:

    线程数  吞吐量  响应时间

    1      0.5    2

    2      1      2

    3      1.5    2

    4      2     2

    5      2    2.5

    6      2     3

    40      2    20

    测试代码:

    import java.util.concurrent.*;
    
    /**
     * https://www.cnblogs.com/silyvin/p/11806859.html
     * https://www.cnblogs.com/silyvin/p/11875907.html
     * Created by joyce on 2019/11/6.
     */
    @BenchmarkMode(Mode.AverageTime)
    @OutputTimeUnit(TimeUnit.SECONDS)
    @Threads(40)
    @State(Scope.Thread)
    public class MyThread {
    
        private static final ThreadPoolExecutor MQ_POOL = new ThreadPoolExecutor(
                4, 4, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(),
                new DefaultThreadFactory("mq-", true));
        
        public static class action implements Callable<Integer> {
    
            @Override
            public Integer call() throws Exception {
                int a = 0;
                Thread.sleep(2000);
                System.out.println(a);
                return a;
            }
        }
    
        @Benchmark
        public static void testS() {
            try {
                Future<Integer> i = MQ_POOL.submit(new action());
                i.get();
            } catch (RejectedExecutionException e) {
                System.out.println("放弃");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        public static void main(String [] f) throws RunnerException {
            
            // jhm压力测试
            Options opt = new OptionsBuilder().include(MyThread.class.getSimpleName()).forks(1).warmupIterations(0)
                    .measurementIterations(1).build();
    
            new Runner(opt).run();
    
            // 自己的压力测试
            MyYali.start(40);
    
    
        }
    
        private static class MyYali implements Runnable {
    
            public static void start(int threadCount) {
    
                for(int i=0; i<threadCount; ++i) {
                    new Thread(new MyYali()).start();
                }
            }
    
            // 这个地方如果用1不会出错
            private int count = 2;
    
            @Override
            public void run() {
                for(int i=0; i<count; ++i) {
                    testS();
                }
            }
        }
    }
    

    这里使用LinkedBlockingQueue无界队列来接收等待队列,之后将会详解

    引用:

    https://blog.csdn.net/sinat_34976604/article/details/88125707

    单线程场景:

    假设我们的服务端只有一个线程,那么所有的请求都是串行执行,我们可以很简单的算出系统的QPS,也就是:QPS = 1000ms/RT。假设一个RT过程中CPU计算的时间为49ms,CPU Wait Time 为200ms,那么QPS就为1000/(49+200) = 4.01。

    多线程场景

    我们接下来把服务端的线程数提升到2,那么整个系统的QPS则为:2 *(1000/(49+200))=8.02。可见QPS随着线程的增加而线性增长,那QPS上不去就加线程呗,听起来很有道理,公式也说得通,但是往往现实并非如此,后面会聊这个问题。

    最佳线程数?

    从上面单线程场景来看,CPU Wait time为200ms,你可以理解为CPU这段时间什么都没做,是空闲的,显然我们没把CPU利用起来,这时候我们需要启多个线程去响应请求,把这部分利用起来,那么启动多少个线程呢?我们可以估算一下 空闲时间200ms,我们要把这部分时间转换为CPU Time,那么就是(200+49)/49 = 5.08个,不考虑上下文切换的话,约等于5个线程。

    。。。。。。。。。
    通过上面一些例子,我们发现当线程数增加的时候,线程的上下文切换会增加,GC Time会增加。这也就导致CPU time 增加,QPS减小,RT也会随着增大。这显然不是我们希望的,我们希望的是在核数一定的情况下找到某个点,使系统的QPS最大,RT相对较小。所以我们需要不断的压测,调整线程池,找到这个QPS的峰值,并且使CPU的利用率达到100%,这样才是系统的最大QPS和最佳线程数。

    https://elasticsearch.cn/question/4350

    顺着楼上大牛的思路,现有业务场景下,评估一下你的线程池模型是否合理
    举个例子:
    一个节点假设配置search线程池为16,队列长度为1000, 一个线程处理一个搜索请求处理耗时是20ms,那么一个线程一秒可以处理50个请求。 那么理论上16个线程一秒可以处理900个请求,1000+16的线程队列大小是能够容纳qps为900的业务的(当然这是理论上,没有考虑的线程上下文切换,网络原因,内存GC导致stw等等,所以实际值肯定比这个低)。

    与“n决定吞吐量,L决定响应时间”一致

    https://blog.csdn.net/qq_34417408/article/details/78895573

    先由之前遇到的一个测试题说起,假设要求一个系统的TPS(Transaction Per Second或者Task Per Second)至少为20,然后假设每个Transaction由一个线程完成,继续假设平均每个线程处理一个Transaction的时间为4s。那么问题转化为:

    如何设计线程池大小,使得可以在1s内处理完20个Transaction?

    计算过程很简单,每个线程的处理能力为0.25TPS,那么要达到20TPS,显然需要20/0.25=80个线程。(理论上)

  • 相关阅读:
    uip源码剖析【一】——【网络层】ARP解读
    MySql字符编码详解
    51单片机+uip实战
    dos中如何查找一个字符串是否包含在某个文件中,如果有则将该文件名输出
    Full TCP/IP for 8Bit Architectures 阅读
    个人PKM之路
    Overlooked Essentials For Optimizing Code
    Would it be faster to batch SetVertex/PixelShaderConstant calls?
    2D Skinned Mesh(3D的完全翻版 带旋转)
    The difference between d8&d9's constants def in asm shaders
  • 原文地址:https://www.cnblogs.com/silyvin/p/11806859.html
Copyright © 2020-2023  润新知