ChuannBlog

高性能基础

基本概念

同步、异步、回调

串行、并行、并发

效率问题

进程

进程的概念起源于操作系统,是操作系统最核心的概念。

概念

特征

  1. 动态性
    • 进程的实质是程序在多道程序系统中的一次执行过程,动态产生,动态消亡
  2. 并发性
    • 伪并行,任何进程都可以同其他进程一起并发执行
  3. 独立性
    • 进程是一个能独立运行的基本单位,同时也是系统分配资源和调度的独立单位
  4. 异步性
    • 由于进程间的相互制约,使进程具有执行的间断性,即进程按各自独立的、不可预知的速度向前推进
  5. 结构特征
    • 进程由程序、数据和进程控制块三部分组成

状态

python使用多进程实现爬虫

from os import getpid
from multiprocessing import Process
import requests


def parse_page(res):
    print(getpid(), "正在解析", res.url, len(res.text))


def get_page(_url, callback=parse_page):
    print(getpid(), "GET", _url)
    response = requests.get(_url)
    if response.status_code == 200:
        callback(response)


urls = [
    "https://www.baidu.com",
    "https://www.cnblogs.com",
    "https://www.python.org",
    "https://www.github.com"
]


if __name__ == '__main__':
    for url in urls:
        p = Process(target=get_page, args=(url, ))
        p.start()

线程

概念

开线程的两种方式

线程和进程的区别

线程

  1. 线程的地址空间为进程的地址空间
  2. 线程可以直接与同进程下线程共享数据
  3. windows下线程创建开销小
  4. 同进程下线程可以互相影响
  5. 更改主线程会影响其他线程运行

进程

  1. 每个进程有自己独立的地址空间
  2. 进程必须通过进程间通信共享数据
  3. 进程创建需要拷贝父进程的信息
  4. 进程只能控制自己的子进程
  5. 父进程不影响子进程的运行

python使用多线程实现爬虫

from threading import Thread, get_ident
import requests


def parse_page(res):
    print(get_ident(), "正在解析", res.url, len(res.text))


def get_page(_url, callback=parse_page):
    print(get_ident(), "GET", _url)
    response = requests.get(_url)
    if response.status_code == 200:
        callback(response)


urls = [
    "https://www.baidu.com",
    "https://www.cnblogs.com",
    "https://www.python.org",
    "https://www.github.com"
]


for url in urls:
    t = Thread(target=get_page, args=(url,))
    t.start()

协程

协程特点

python使用协程实现爬虫

from gevent import monkey;monkey.patch_all()
from gevent.threading import get_ident
import gevent

import requests


def parse_page(res):
    print(get_ident(), "正在解析", res.url, len(res.text))


def get_page(_url, callback=parse_page):
    print(get_ident(), "GET", _url)
    response = requests.get(_url)
    if response.status_code == 200:
        callback(response)


urls = [
    "https://www.baidu.com",
    "https://www.cnblogs.com",
    "https://www.python.org",
    "https://www.github.com"
]

g_list = []
for url in urls:
    g = gevent.spawn(get_page, url)
    g_list.append(g)
gevent.joinall(g_list)

相关扩展

互斥锁

原理

当一个进程/线程拿到数据使用权后,上一把锁,其余进程/线程看到数据被加锁就进入阻塞状态,直到锁被释放。

全局解释器锁(GIL)(Global Interpreter Lock)

死锁

生产者消费者模型

I/O模型

同步/异步/阻塞/非阻塞

阻塞I/O

非阻塞I/O

I/O多路复用

异步I/O

信号驱动I/O(不常用)