locust之简介(1)

 

 

目录

 

简介

什么是协程

为什么要说线程的切换    

线程的引入

操作系统如何组织多个进程

PCB的作用

PCB的内容

PCB的组织方式

操作系统如何完成进程的切换

操作系统如何对进程间相互影响进行分离


  • 简介

locust是一个基于python的开源框架。是一个易于使用的分布式用户负载工具。

它旨在对网站(或其他系统)进行负载测试,并弄清一个系统可以处理多少个并发用户。

locust是基于事件的,这里就需要介绍下它的根基协程了。

  • 什么是协程

协程是比线程更小的一种执行单元,你可以认为是轻量级的线程,之所以说轻,其中一方面的原因是协程所持有的栈比线程要小很多,java当中会为每个线程分配1M左右的栈空间,而协程可能只有几十或者几百K,栈主要用来保存函数参数、局部变量和返回地址等信息。

这里就对比loadrunner和jmeter可以看出,它本身使用的内存是很小的。
       线程的调度是在操作系统中进行的,而协程调度则是在用户空间进行的,是开发人员通过调用系统底层的执行上下文相关api来完成的,有些语言,比如nodejs、go在语言层面支持了协程,而有些语言,比如C,需要使用第三方库才可以拥有协程的能力。

 由于线程是操作系统的最小执行单元,因此也可以得出,协成是基于线程实现的,协程的创建、切换、销毁都是在某个线程中来进行的。

使用协程是因为线程的切换成本比较高,而协程在这方面很有优势。(它拥有自己的私有的寄存器,这个后面慢慢讲来)。

我们先来了解一下线程是如何进行切换的。

  • 为什么要说线程的切换    

操作系统是多进程的,我们关注的应该是进程之间的切换,那为什么关注线程的切换呢?因为理解了线程的切换之后可以更好的理解进程的切换,换句话说线程的切换是进程切换的基础。

每一个进程都包含一个映射表,如果进程切换了,那么程序选择的映射表肯定也不一样;进程的切换其实是包含两个部分的,第一个指令的切换,第二个映射表的切换。指令的切换就是从这段程序跳到另外一段程序执行,映射表切换就是执行不同的进程,所选择的映射表不一样。线程的切换只有指令的切换,同处于一个进程里面,不存在映射表的切换。进程的切换就是在线程切换的基础上加上映射表的切换。

  • 线程的引入

 多个进程可以同时执行,说白了,在不利用多核的基础上,我们其实是在快速的进行进程的切换的。在用户层面是无法感知的。而在同一个进程中,我们也是会产生很多的线程的。

  • 操作系统如何组织多个进程

  即根据PCB、根据状态形成不同的队列放在不同的位置。多个进程如何组织呢?用PCB放在不同的队列中(就绪、阻塞),用状态转化来推进多个进程的执行。下面我们来讲一讲PCB。

  • PCB的作用

 进程控制块是进程实体的一部分,是操作系统中最重要的记录型数据结构。PCB中记录了操作系统所需要的、用于描述进程情况及控制进程运行所需要的全部信息。主要表示进程状态。

 进程控制块的作用,是使一个在多道程序环境下不能独立进行的程序(含数据),成为一个能独立运行的基本单位,一个能与其他进程并发执行的进程。或者说,操作系统是根据PCB来对并发执行的进程进行控制和管理。

  • PCB的内容

     在进程控制块中,主要包括4个方面内容。  

    (1)进程标识符信息。进程标识符用于惟一地标识一个进程。一个进程,通常有以下两个标识符:外部标识符,内部标识符。
  (2)处理机状态信息。处理机状态信息主要是由处理机各种寄存器中的内容所组成。
  (3)进程一调度信息。在PCB中还存放了一些与进程调度和进程对换有关的信息,包括:进程状态、进程优先级、进程调度所需要的其他信息、事件。
  (4)进程控制信息。进程控制信息包括:程序和数据的地址、进程同步和通信机制、资源清单、链接指针。 

  • PCB的组织方式

在一个系统中,通常可拥有数十个、数百个乃至数千个PCB,为能对它们进行有效管理,应该用适当的方式将它们组织起来,目前,常见的组织方式有两种,链接方式和索引方式。

  • 操作系统如何完成进程的切换

调度选择下一个进程,得到下一个进程的PCB(进程控制块),把上一个进程的执行现场保存起来,把下一个进程的现场覆盖到CPU对应的寄存器中去。多进程如何交替?如何切换?把上一个进程的执行现场保存起来,把当前CPU中的寄存器信息等保存到上一个进程的PCB中,把选好的要执行的进程(由进程调度确定)的PCB中的各寄存器信息恢复到当前CPU的寄存器中

  • 操作系统如何对进程间相互影响进行分离

通过内存管理,地址映射方式,将不同进程中相同的虚拟地址映射到不同物理地址,实现分离。这里还会产生同步以及互斥2种可能,就不具体介绍了。只需要记住是为了争夺临界资源而相互排斥的过程,我们称为进程的互斥。在之后的例子中我们将使用队列的形式来保证资源的独享,也就是所谓的参数化方式。当然我们也可以使用一把互斥锁来保证共享数据的完整性。这些我们都会在之后一一演示给大家看。

现在我们知道进程切换要指令切换,映射表切换,线程切换只需要指令切换,记住,线程是不可控的,这是系统级别的,而不是程序级别的。而协程,我们就可以理解为用户形态的线程,意思就是我们自主交出控制权,我自己现在遇到了IO阻塞,我就先把cpu让给别的兄弟去计算,这里就有一个关键词了:yield。这可不是python独有的。

  • 为什么协程的切换很廉价

1 线程在进行切换的时候,需要将CPU中的寄存器的信息存储起来,然后读入另外一个线程的数据,这个会花费一些时间

2 CPU的高速缓存中的数据,也可能失效,需要重新加载

3 线程的切换会涉及到用户模式到内核模式的切换,据说每次模式切换都需要执行上千条指令,很耗时

协程的切换之所以快,可能的原因是:

1 在切换的时候,寄存器需要保存和加载的数据量比较小。

2 高速缓存可以有效利用

3 没有用户模式到内核模式的切换操作。

4 更有效率的调度,因为协程是非抢占式的,前一个协程执行完毕或者堵塞,才会让出CPU,而线程则一般使用了时间片的算法,会进行很多没有必要的切换(为了尽量让用户感知不到某个线程卡)。

Python通过yield提供了对协程的基本支持,但是不完全。而第三方的gevent为Python提供了比较完善的协程支持。我们下一章接着来介绍yield以及相关的知识。

 

 

你可能感兴趣的:(locust,python,性能测试)