刘勇的平凡之路

不积跬步无以至千里


  • 首页

  • 关于

  • 标签

  • 分类

  • 归档

  • 站点地图

利用 XHProf 对 PHP 代码进行性能分析

发表于 2018-11-23

遇到程序执行速度慢的情况,除了看服务器系统状态、mysql slow log外,还可以对代码进行性能分析来定位问题。最简单常用的办法是代码不同的地方记录日志来分析程序各个节点的执行时间。XHProf可以高效地对php代码进行性能分析。

介绍

XHProf 是一个轻量级的分层性能测量分析器的PHP扩展。 可以跟踪调用次数、运行时间、CPU 计算时间和内存开销,展示程序动态调用的路径。XHProf 提供一个基于 HTML 的简单用户界面来展示分析数据,也支持图片的形式查看调用路径。

安装

Centos

1
pecl install xhprof

这是会报如下错误:

1
2
3
Failed to download pecl/xhprof within preferred state “stable”, 
latest release is version 0.9.4, stability “beta”,
use “channel://pecl.php.net/xhprof-0.9.4” to install

因为 xhprof 是 beta 版本,不是 stable 版,要用下面命令安装:

1
pecl install channel://pecl.php.net/xhprof-0.9.4

为了后面可以用图片的形式展示,需要安装 graphviz:

1
yum install graphviz # 支持图形化展示结果

在 php.ini 中加载扩展,配置生成 profile 数据的存放目录:

1
2
extension=xhprof.so
xhprof.output_dir=生成数据的存放目录

要通过 web 形式查看分析结果,需要下载xhprof源码(里面包括图形化展示分析结果所需的代码和相关类库)放到 web 可以访问到的目录。xhprof 目录结构如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
bin
CHANGELOG
CREDITS
examples
extension
LICENSE
package.xml
README
scripts
support
xhprof_html
xhprof_lib

使用

以一段简单的代码举例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<?php
include(realpath(dirname(__FILE__)."/vendor/autoload.php"));

// 在开始分析的地方加上 xhprof_enable() 方法
// XHPROF_FLAGS_NO_BUILTINS 表示不分析 PHP内置函数
xhprof_enable(XHPROF_FLAGS_NO_BUILTINS);


// 需要分析的代码开始
// 具体逻辑不用关心
use Simplelog\Simplelog;

$logFile = "/tmp/simple.log";
$log = new Simplelog($logFile);
$log->debug('skimlinks', array('affid'=>'223'));
// 需要分析的代码结束

// 结束分析
// 分析结果存在数组 $xhprof_data 里
$xhprof_data = xhprof_disable();

// 将分析结果存到 php.ini 中配置的 xhprof.output_dir 目录中
// 下面代码可以封装,这里只做简单演示用
// xhprof/xhprof_lib/ 是下载源码中的 xhprof_lib,即上图标2的文件夹
include_once "xhprof/xhprof_lib/utils/xhprof_lib.php";
include_once "xhprof/xhprof_lib/utils/xhprof_runs.php";

$xhprof_runs = new XHProfRuns_Default();

// "xhprof_foo" 是命名空间,可自定义.
// run_id 生成的唯一id,供下面通过 url 的形式访问查看
$run_id = $xhprof_runs->save_run($xhprof_data, "xhprof_foo");

// xhprof/xhprof_html/ 是下载源码中的 xhprof_html,即上图标1的文件夹
// xhprof_html 须放到 web 可以访问到的目录
// link 为可以查看分析结果的地址
$link = "http://yourdomain.com/xhprof_html/index.php?run=$run_id&source=xhprof_foo";

echo "<a href='{$link}' target='_blank'>{$link}</a>";

结果分析

上一步中生成的分析结果,可以通过下面地址查看:

1
http://yourdomain.com/xhprof_html/index.php?run=5be28a5486b02&source=xhprof_foo

通过上面地址,可以看到类似下面的列表展示,可以从不同的维度来看各方法的性能:执行时长,CPU占用等信息
xhprof report list

主要参数说明

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Calls        调用次数
Calls% 调用百分比
Incl. Wall Time 调用的包括子函数所有花费时间,以微秒算
IWall% 调用的包括子函数所有花费时间的百分比
Excl. Wall Time 函数执行本身花费的时间,不包括子树执行时间,以微秒算
EWall% 函数执行本身花费的时间的百分比不包括子树执行时间
Incl. CPU(microsecs) 方法执行花费的CPU时间,包括子方法的执行时间
ICPU% 方法执行花费的CPU时间百分比
Excl. CPU(microsec) 方法本身执行花费的CPU时间,不包括子方法的执行时间
ECPU% 方法本身执行花费的CPU时间百分比
Incl.MemUse(bytes) 方法执行占用的内存,包括子方法执行占用的内存。(单位:字节)
IMemUse% 方法执行占用的内存百分比。
Excl.MemUse(bytes) 方法本身执行占用的内存,不包括子方法执行占用的内存。(单位:字节)
EMemUse% 方法本身执行占用的内存百分比。

图片展示

点击上面列表展示中的“View Full Callgraph”,就可以跳转到下图的的图片展示的界面。
通过下图可以看到各方法的调用路径以及执行所花费的时间,红色块是执行时间最长的,黄色块是其次。这样就能快速找到对性能影响较大的节点,然后到相应的节点里分析到底是代码还是 mysql 的问题就很方便了。

xhprof report graph

参考:
XHProf
层次式性能分析器
https://www.kam24.ru/xhprof/docs/index.html#ui_setup

用测试账户调试Google Ads API

发表于 2018-09-14 | 更新于 2018-09-16

申请生产经理账号和开发者令牌

申请生产经理账号(production manager account)后可以申请生产经理开发者令牌(后面称 Developer Token),Developer Token 会让 AdWords API 识别你的应用。只有经过批准的令牌才能连接到生产 AdWords 帐号的 API;待处理令牌只能连接到测试帐号。一旦 Developer Token 获得批准,就可以将同一令牌用于针对所有 AdWords 帐号的请求,即使它们未关联到与此开发者令牌相关联的经理帐号,也就是说 Developer Token 不仅可以在正式环境中使用,也可以在测试环境中使用。

  1. 创建生产经理帐号
  2. [在生产经理帐号中请求开发者令牌(production manager developer token)]
    注册 AdWords API 时,系统会自动生成一个开发者令牌。提出申请后,令牌立刻进入待审批状态。在令牌获得批准后,可以指定在生产环境中使用的目标 AdWords 帐号。
    (https://developers.google.com/adwords/api/docs/guides/signup)

请求成功后在 TOOLS -> API Center 中可以看到相应的 Developer Token。
Developer Token

可以使用开发者令牌来指定任何目标 AdWords 帐号,因此,只需使用目标帐号(或其某一个经理帐号,包括测试账号)的 OAuth2 凭据来授权你的请求即可(见下文)。

在下面的流程中,对测试经理帐号发出请求时,就会使用到这里的生产经理帐号开发者令牌。

测试经理帐号(test manager account)

  • 申请测试经理帐号
    测试经理帐号申请成功,登录后可以看到一个红色的标签 Test account,说明是测试经理帐号,如果没有在 AdWords 帐号页上看到红色的“Test account”标签,那么该帐号是一个生产帐号。
    test account

申请测试客户账号(test client account)

测试经理帐号申请成功后才能进行这一步。

  1. 使用 AdWords 网页界面,在之前创建的测试经理帐号下创建测试客户帐号。当您以测试经理帐号登录 AdWords 时,您创建的所有客户帐号都将自动成为测试帐号。
    create test client account
  2. 记下新测试客户帐号的客户 ID (Client Customer ID)并保存:稍后您需要将其添加到配置文件中。客户帐号的 Client Customer ID 如下所示:
    client customer ID
  3. 使用 AdWords 网页界面,在测试客户帐号下创建几个测试广告系列(test campaigns),比如我这里创建一个名为“test1”的 campaign,生成的 id 为1557850521(后面会用到)。

设置 OAuth2 身份验证,将 OAuth2 与测试帐号配合使用

应用必须先获取授予 API 访问权限的 OAuth2 访问令牌,才可以使用 API 访问非公开数据。通过 OAuth2 进行身份验证后可让应用代表你的帐号进行各种操作。要使用 OAuth2 访问测试帐号,测试经理帐号用户必须向客户端应用授予权限。授权后,应用就可以用授权账户提供的 OAuth2 客户端 ID (Client ID)和客户端密钥(Client Secret)来访问 API。

生成 OAuth2 凭据(Credentials)

  1. 使用经理帐号凭据登录后,打开 Google API 控制台凭据页面。
  2. 从项目下拉菜单中,选择 新建项目,输入项目的名称,然后点击 创建。
  3. 选择 创建凭据,然后选择 OAuth 客户端 ID。
  4. 点击 配置同意屏幕(Configure consent screen),提供要求的信息,然后点击 保存 以返回到凭据(Credentials)屏幕。
  5. 在应用类型下,选择其他。在提供的空间中输入名称。
  6. 点击创建。系统会显示 OAuth2 客户端 ID (Client ID)和客户端密钥(Client Secret)。复制并保存这些信息。在下一步中将它们添加到配置文件中。
    oauth2 client id & client secret

获取 OAuth2 刷新令牌(Refresh token)

由于 OAuth2 访问权限会在限定时间后过期,因此使用 OAuth2 刷新令牌来自动更新 OAuth2 访问权限。当请求 OAuth2 刷新令牌时,请确保您以测试经理帐号用户身份登录,以获取测试经理帐号对应的 OAuth2 客户端 ID (client ID)和客户端密钥(client secret)。在针对测试经理帐号提出请求时需要使用生产经理帐号的开发者令牌。

  1. 调用刷新令牌脚本,这里我用Python版的。 修改 generate_refresh_token.py 文件,把其中的 DEFAULT_CLIENT_ID,DEFAULT_CLIENT_SECRET 修改为上面刚刚创建好的 Client ID 和 Client Secret:

    1
    2
    3
    4
    5
    6
    ...
    # Your OAuth2 Client ID and Secret. If you do not have an ID and Secret yet,
    # please go to https://console.developers.google.com and create a set.
    DEFAULT_CLIENT_ID = 'Your client id here'
    DEFAULT_CLIENT_SECRET = 'Your client secret here'
    ...
  2. 执行:python generate_refresh_token.py

  3. 按照提示复制生成的 url 到浏览器,在到达的页面中用测试经理帐号对应的账号登录, 下一步点击“允许”,会出现下图:
    access code
  4. 复制下图中的 code 粘贴到步骤2执行的命令行
    refresh token
  5. 记录下上步中的 Refresh Token。

生产环境中,从测试经理帐号切换到生产经理帐号,需要用生产经理帐号相关的 Client ID 和 Client Secret 来请求生产经理帐号的刷新令牌。

测试 ads API 功能

上面的步骤里我们已经准备好了调用 API 需要的必要配置:Developer Token, Client Customer ID, Client ID, Client Secret, Refresh Token。下面测试一个 API 调用:

  1. 选择自己熟悉语言的客户端库,这里用Python。
  2. 配置文件(googleads.yaml)中填写正确的配置信息:

    1
    2
    3
    4
    5
    6
    7
    # AdWordsClient configurations
    adwords:
    developer_token: Developer Token
    client_customer_id: Client Customer ID
    client_id: Client ID
    client_secret: Client Secret
    refresh_token: Refresh Token
  3. 测试 ad groups 功能:

    • 修改 add_ad_groups.py :

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      ...
      CAMPAIGN_ID = 1557850521 # 上面创建测试客户帐号后添加的 campaign
      ...
      if __name__ == '__main__':
      # Initialize client object.
      adwords_client = adwords.AdWordsClient.LoadFromStorage('你的 googleads.yaml 存放位置')

      main(adwords_client, CAMPAIGN_ID)

      ...
    • 命令行执行:python add_ad_groups.py

  4. 执行后到测试客户账号下查看对应的 campaign 下的 ad groups 如下所示:
    test-ad-groups

参考

  • 管理帐号
  • OAuth2 身份验证
  • 进行首次 API 调用
  • API 典型使用案例

抓取网页内容(爬虫)一些方法介绍

发表于 2018-07-19 | 更新于 2018-09-07

抓取网页内容的一般流程

  1. 发HTTP请求
  2. 解析请求返回的结果
  3. 得到的结果持久化

常用的抓取网页内容的方法和工具

命令行

  • cURL

PHP:

  • 原生Client URL 库(cURL)
  • 类库,比如:Requests, Guzzle
  • 爬虫开发框架:phpspider

Python

  • 类库,比如:Requests
  • 爬虫开发框架:Scrapy

NodeJS

  • curl-request
  • 爬虫开发框架:node-crawler

可能遇到的问题和困难

  • 登录:保存Cookie, 认证
  • 被屏蔽
  • 验证码
  • 执行JS
  • 其他

另外一种思路

利用界面自动化测试工具进行抓取,简单点讲就是:程序唤起浏览器后模拟用户行为进行操作

阅读全文 »

MySQL MyISAM 分区(partition)导致打开文件过多

发表于 2018-07-19 | 更新于 2018-09-11

问题表现

最近公司一个业务环境的数据库,出现无法连接的情况,重启后过几个小时问题又出现。查看报错信息,如下所示:

1
Out of resources when opening file './xxx.MYD' (Errcode: 24 - Too many open files)

问题很明显:打开文件过多,超过了配置的限制。

问题分析

查看 table_open_cache, open_files_limit 当前配置的值:

1
2
3
4
5
6
7
8
9
10
11
mysql> show variables like '%open_%';
+----------------------------+-------+
| Variable_name | Value |
+----------------------------+-------+
| have_openssl | YES |
| innodb_open_files | 2000 |
| open_files_limit | 5000 |
| table_open_cache | 2000 |
| table_open_cache_instances | 16 |
+----------------------------+-------+
5 rows in set (0.01 sec)

阅读全文 »
William Liu

William Liu

记录一些编程点滴

4 日志
10 标签
GitHub StackOverflow
© 2018 William Liu
由 Hexo 强力驱动 v3.7.1
|
主题 — NexT.Pisces v6.3.0