python 优化IO和并发提高性能

一、任务量与执行效率的关系

  • 任务量和效率成反比:任务量越大,程序整体耗时越长,执行效率越低。
  • 程序执行效率 = 完成单位任务所需的时间。任务多、耗时长,效率自然低。

二、如何提高程序执行效率?

  1. 减少任务量

    • 只做必要的工作,减少无用或重复的任务。
    • 例如:数据预处理、过滤无效请求、合并重复操作等。
  2. 提高并发量

    • 让多个任务“同时”进行(并发/并行),充分利用CPU和IO资源。
    • 例如:多线程/多进程/协程/异步IO等。
  3. 减少单个任务的执行时间

    • 优化算法、减少不必要的计算、提升IO速度。
    • 例如:用高效的数据结构、减少磁盘/网络访问、批量处理等。

三、程序执行时的“耗时”来源

1. 正常的耗时(CPU耗时)

  • CPU执行程序指令所消耗的时间。
  • 例如:数学运算、数据处理、逻辑判断等。
  • 这种耗时取决于CPU性能和代码效率。

2. IO的耗时

  • 等待数据时消耗的时间,通常远大于CPU耗时。
  • 例如:读写文件、网络请求、数据库操作等。
  • 程序在等待数据时,CPU可能处于空闲状态。

四、什么是IO(Input/Output)?

  • IO:输入/输出,是指程序与外部世界(磁盘、网络、外设等)之间的数据交换。
  • Input(输入):将数据从内存以外的地方(如磁盘、网络)拷贝进内存。
  • Output(输出):将数据从内存发送到内存以外的地方(如磁盘、网络)。

五、IO操作的优化思路

1. 缩短IO的时间

  • 用更快的硬件(如SSD代替HDD)。
  • 优化数据格式,减少数据量。
  • 批量读写,减少IO次数。

2. 利用等待IO的时间

  • 在等待IO时,让CPU去做其他任务,而不是空等。
  • 这就是并发/异步编程的核心思想。
  • 例如:多线程/多进程/协程/异步IO,让一个任务在等待IO时,其他任务可以继续执行。

六、举例说明

1. 串行IO(低效)

def read_and_write():
    data = read_file()   # 等待IO
    process(data)        # CPU计算
    write_file(data)     # 等待IO
  • 每一步都要等前一步完成,IO等待时CPU空闲,效率低。

2. 并发IO(高效)

from threading import Thread

def task():
    data = read_file()
    process(data)
    write_file(data)

threads = [Thread(target=task) for _ in range(10)]
for t in threads: t.start()
for t in threads: t.join()
  • 多个任务同时进行,等待IO时CPU可以切换到其他任务,整体效率大幅提升。

七、总结

  • 程序耗时主要来自CPU计算和IO等待,IO等待通常是性能瓶颈。
  • 提升效率的核心思路:
    1. 减少任务量
    2. 提高并发量
    3. 优化单个任务的执行时间,尤其是缩短IO等待或利用等待时间做更多事
  • 并发/异步编程是现代高性能程序的关键。

一、代码逐行详解

from threading import Thread
  • 导入Python标准库中的Thread类,用于创建和管理线程。

def task():
    data = read_file()
    process(data)
    write_file(data)
  • 定义一个任务函数task,每个线程都会执行这个函数。
  • read_file():假设是一个读取文件或数据的IO操作(可能会阻塞)。
  • process(data):对读取到的数据进行处理(CPU计算)。
  • write_file(data):将处理后的数据写回文件或其他地方(也是IO操作)。

threads = [Thread(target=task) for _ in range(10)]
  • 创建一个包含10个线程的列表,每个线程的目标函数都是task
  • 这意味着将有10个任务并发执行,每个任务都独立完成“读-处理-写”的流程。

for t in threads: t.start()
  • 启动所有线程,让它们几乎同时开始执行task函数。
  • 线程的启动是非阻塞的,主线程会很快把所有子线程都启动起来。

for t in threads: t.join()
  • 主线程等待所有子线程执行完毕后再继续(或退出)。
  • join()会阻塞主线程,直到对应的子线程结束,保证所有任务都完成。

二、并发的原理与优势

1. 并发执行

  • 多线程让多个任务“同时”进行(实际上是CPU快速切换,或多核CPU真正并行)。
  • 当一个线程在等待IO(如读写文件、网络请求)时,CPU可以切换去执行其他线程的任务,大大提升了资源利用率和程序整体效率

2. 适用场景

  • IO密集型任务:如文件读写、网络爬虫、数据库操作等。
  • 多线程能有效利用等待IO的时间,让CPU不空闲。

3. 为什么能提升效率?

  • 如果串行执行,每个任务都要等前一个任务的IO和处理全部完成,整体耗时是所有任务耗时之和。
  • 并发执行时,多个任务的IO等待可以重叠,CPU利用率更高,总耗时大大缩短

三、注意事项

  • 这里假设read_filewrite_file是IO操作,多线程适合IO密集型任务
  • 如果process(data)是CPU密集型任务,Python的GIL会限制多线程的并行效率,此时建议用多进程。
  • 多线程操作共享数据时要注意线程安全(本例每个线程独立处理自己的数据,不会有冲突)。

四、流程图

主线程
  ├─ 启动线程1 ──> task() ──> read_file() ──> process() ──> write_file()
  ├─ 启动线程2 ──> task() ──> ...
  ├─ ...
  └─ 启动线程10 ─> task() ──> ...
  ↓
等待所有线程结束(join)

五、总结

  • 这段代码用多线程并发执行10个独立任务,每个任务包括读、处理、写三个步骤。
  • 适合IO密集型场景,能大幅提升程序整体效率。
  • start()启动线程,join()等待线程结束,保证所有任务都完成。

你可能感兴趣的:(python)