python性能分析和优化,GIL常考题

什么是Cpython GIL

  • Cpython解释器的内存管理并不是线程安全的
  • 保护多线程情况下对python对象访问
  • Cpython使用简单的锁机制避免多个线程同时执行字节码

GIL的影响

限制了程序的多核执行

  • 同一个时间只能有一个线程执行字节码
  • CPU密集程序难以利用多核优势
  • IO期间会释放GIL,对IO密集程序影响不大

如何规避GIL影响和IO密集程序

  • CPU密集可以使用多进程+进程池
  • IO密集使用多线程/协程
  • Cpython扩展

为什么有了GIl还要关注线程安全

python中什么操作才是原子的?一步到位执行完

  • 一个操作如果是一个字节码指令可以完成就是原子的
  • 原子的是可以保证线程安全的
  • 使用dis操作来分析字节码

原子操作

  1. import dis
  2. def update_list(l):
  3. l[0] = 1 #原子操作,不用担心线程安全问题
  4. dis.dis(update_list)
  5. """
  6. 6 0 LOAD_CONST 1 (1)
  7. 3 LOAD_FAST 0 (L)
  8. 6 LOAD_CONST 2 (0)
  9. 9 STORE_SUBSCR # 但字节码操作 线程安全
  10. 10 LOAD_CONST 0 (None)
  11. 13 RETURN_VALUE
  12. """

非原子操作不是线程安全的

  1. def incr_list(l):
  2. l[0] += 1 #危险!!! 不是原子操作
  3. dis.dis(incr_list)
  4. """
  5. 21 0 LOAD_FAST 0(l)
  6. 3 LOAD_CONST 1 (0)
  7. 6 DUP_TOPX 2
  8. 9 BINARY_SUBSCR
  9. 10 LOAD_CONST 2 (1)
  10. 13 INPLACE_ADD # 需要多个字节码操作,有可能在线程中切到其他线程
  11. """
  1. import threading
  2. lock = threading.Lock() # 加锁,保证线程安全
  3. # 加锁操作对性能有一定影响
  4. n = [0]
  5. def foo():
  6. with lock:
  7. n[0] = n[0] + 1
  8. n[0] = n[0] + 1
  9. threads = []
  10. for i in range(5000);
  11. t = threading.Thread(target=foo)
  12. threads.append(t)
  13. for t in threads:
  14. t.start()
  15. print(n)

如何剖析程序性能

使用各种profile工具(内置或第三方)

  • 二八定律,大部分时间耗时在少量代码上
  • 内置的profile/cprofile等工具
  • 使用pyflame(uber开源)的火焰图工具

服务端性能优化措施

web应用一般语言不会成为瓶颈

  • 数据结构与算法优化
  • 数据库层: 索引优化,满查询消除,批量操作减少IO,NoSql
  • 网络IO:批量操作,pipeline操作 减少IO
  • 缓存: 使用内存数据库 redis/memcached
  • 异步; asyncio , celery
  • 并发: gevent/多线程
python生成器与协程

Generator

  • 生成器就是可以生成值的函数
  • 当一个函数里有了yield关键字就成了生成器
  • 生成器可以挂起执行并且保持当前执行的状态
  1. # 生成器
  2. def simple_gen():
  3. yield 'hello'
  4. yield 'world'
  5. gen = simple_gen()
  6. print(type(gen)) # 'generator' object
  7. print(next(gen)) # 'hello'
  8. print(next(gen)) # 'world'

基于生成器的协程(python2)

python3之前没有原生协程,只有基于生成器的协程

  • pep 342增强生成器功能
  • 生成器可以通过yield暂停执行和产出数据
  • 同时支持send()向生成器发送数据和throw()向生成器抛出异常
  1. def coro():
  2. hello = yield 'hello' # yield关键字在=右边作为表达式, 可以被sengd的值
  3. yield hello
  4. c = cor0()
  5. #输出 ' hello' ,这里调用next产出一个值 'hello',之后函数暂停
  6. print(next(c))
  7. # 再次调用send发送值, 此时hello变量赋值为'world', 然后yield产出hello变量的值 'world'
  8. print(c.send('world'))
  9. # 之后协程结束,后续再send值会抛出异常StopIteration

python3原生协程

python3.5引入async/await支持原生协程(natice copoutine)

  1. import asyncio
  2. import datetime
  3. import random
  4. async def display_date(num, loop):
  5. end_time = loop.time(0) + 50.0
  6. while True:
  7. print('Loop: {} Time: {}').format(num, datetime.datetime.now())
  8. if (loop.time() + 1.0) >= end_time:
  9. break
  10. await asyncio.sleep(random.randint(0, 5))
  11. loop = asyncio.get_event_loop()
  12. asyncio.ensure_future(display_date(1, loop))
  13. asyncio.ensure_future(display_date(2, loop))
  14. loop.run_forever()

python 单元测试

什么是单元测试

  • 针对程序模式进行正确性检验
  • 一个函数, 一个类进行验证
  • 自底向上保证程序正确性

为什么要写单元测试

三无代码不可取(无文档,无注释,无单测)

  • 保证代码逻辑的正确性(甚至有些采用测试驱动开发TDD)
  • 单测影响设计,易测的代码往往是高内聚低耦合的
  • 回归测试,防止改一处整个服务不可用

单元测试相关的库

  • nose/pytest 较为常用
  • mock 模块用来模拟替换网络请求等
  • coverage 统计测试覆盖率
  1. def test():
  2. """
  3. 如何设计测试用例:(等价类划分)
  4. - 正常功能测试
  5. - 边界值 (比如最大最小,最左最右值)
  6. - 异常值 (比如None, 空值,非法值)
  7. """
  8. assert binary_search([0,1,2,3,4,5],1) == 1
  9. assert binary_search([0,1,2,3,4,5],6) == -1

python深拷贝与浅拷贝

  • 什么是深拷贝?什么是浅拷贝?
  • python中如何实现深拷贝?
  • 思考: python中如何正确初始化一个二维数组?

python面试总结3(性能分析优化,GIl常考题)的更多相关文章

  1. python 数据较大 性能分析

    前提:若有一个几百M的文件需要解析,某个函数需要运行很多次(几千次),需要考虑性能问题 性能分析模块:cProfile 使用方法:cProfile.run("func()"),其中 ...

  2. python pstats ,profile 性能分析

    #! /usr/bin/env python # encoding=utf8 import pstats import profile def func1(): for i in range(1000 ...

  3. 如何进行python性能分析?

    在分析python代码性能瓶颈,但又不想修改源代码的时候,ipython shell以及第三方库提供了很多扩展工具,可以不用在代码里面加上统计性能的装饰器,也能很方便直观的分析代码性能.下面以我自己实 ...

  4. Python面试知识点小结

    一.Python基础 1.Python语言特性: 动态型(运行期确定类型,静态型是编译型确定类型),强类型(不发生隐式转换,弱类型,如PHP,JavaScript就会发生隐患式转换) 2.Python ...

  5. 面试中常用排序算法的python实现和性能分析

    这篇是关于排序的,把常见的排序算法和面试中经常提到的一些问题整理了一下.这里面大概有3个需要提到的问题: 虽然专业是数学,但是自己还是比较讨厌繁琐的公式,所以基本上文章所有的逻辑,我都尽可能的用大白话 ...

  6. Python 优化第一步: 性能分析实践 使用cporfile+gprof2dot可视化

    拿来主义: python -m cProfile -o profile.pstats to_profile.py gprof2dot -f pstats profile.pstats |dot -Tp ...

  7. Python性能分析与优化PDF高清完整版免费下载|百度云盘

    百度云盘|Python性能分析与优化PDF高清完整版免费下载 提取码:ubjt 内容简介 全面掌握Python代码性能分析和优化方法,消除性能瓶颈,迅速改善程序性能! 对于Python程序员来说,仅仅 ...

  8. 常用排序算法的python实现和性能分析

    常用排序算法的python实现和性能分析 一年一度的换工作高峰又到了,HR大概每天都塞几份简历过来,基本上一天安排两个面试的话,当天就只能加班干活了.趁着面试别人的机会,自己也把一些基础算法和一些面试 ...

  9. 【Python】常用排序算法的python实现和性能分析

    作者:waterxi 原文链接 背景 一年一度的换工作高峰又到了,HR大概每天都塞几份简历过来,基本上一天安排两个面试的话,当天就只能加班干活了.趁着面试别人的机会,自己也把一些基础算法和一些面试题整 ...

随机推荐

  1. Python之schedule用法,类似linux下的crontab

    # -*- coding: utf-8 -*- # author:baoshan import schedule import time def job(): print("I'm work ...

  2. Qt 图片缩放参数计算

    缩放图片 void VCImgWidget::wheelEvent(QWheelEvent *event) { ) { // 当滚轮远离使用者时 //ui->textEdit->zoomI ...

  3. Spring整合Redis,并配置Jedis连接池

    目录 只言片语 创建redis连接池的配置文件 单机版 spring整合redis(使用JedisPool) 项目中使用示例 集群版 spring整合redis(使用JedisCluster) 项目中 ...

  4. PP篇10 修改工单组件行

    CO_XT_COMPONENT_CHANGE 修改工单组件行 DATA : is_order_key TYPE coxt_ord_key, is_order_component_key TYPE co ...

  5. vue 框架安装系列问题

    npm install --global vue-cli 错误提示:vue-cli-service' 不是内部或外部命令,也不是可运行的程序或批处理文件解决:如果是npm安装的 执行 npm -g b ...

  6. 两种Redis持久化原理的详解

    Redis为持久化提供了两种方式: RDB:在指定的时间间隔能对你的数据进行快照存储. AOF:记录每次对服务器写的操作,当服务器重启的时候会重新执行这些命令来恢复原始的数据. 本文将通过下面内容的介 ...

  7. LODOP中的RightMargin右边距和BottomMargin下边距

    LODOP中的打印项,例如ADD_PRINT_HTM,参数分别为顶边距,左边距,宽,高,打印项内容.第三四参数宽高,除了可以用值和百分比,还可以用RightMargin和BottomMargin变相控 ...

  8. SQL server触发器学习记录

    作为C#程序员,我工作内容基本就是winform,wpf,asp.net.sql接触的比较少,今天突然来了一个ticket要我修改触发器脚本....只会select*的我顿感迷茫... 需求描述:as ...

  9. c# Aspose.Cells 通过Excel模板生产excel数据再打印

    多的不说,我们先来利用Northwind做两个小demo.先说说Aspose.Cells的模板语法: &=DataSource.Field,&=[DataSource].[Field] ...

  10. grok语法定义

    grok默认表达式 Logstash 内置了120种默认表达式,可以查看patterns,里面对表达式做了分组,每个文件为一组,文件内部有对应的表达式模式.下面只是部分常用的. 常用表达式 表达式标识 ...