[译]Linux性能分析的前60000毫秒 #36

https://github.com/spacewander/blogWithMarkdown/issues/36

 

 

原文链接:http://techblog.netflix.com/2015/11/linux-performance-analysis-in-60s.html
作者是Brendan Gregg, Oracle/Linux系统性能分析方面的大牛。

Linux性能分析的前60000毫秒

为了解决性能问题,你登入了一台Linux服务器,在最开始的一分钟内需要查看什么?

在Netflix我们有一个庞大的EC2 Linux集群,还有非常多的性能分析工具来监控和调查它的性能。其中包括用于云监控的Atlas,用于实例按需分析的Vector。即使这些工具帮助我们解决了大多数问题,我们有时还是得登入Linux实例,运行一些标准的Linux性能工具来解决问题。

在这篇文章里,Netflix Performance Engineering团队将使用居家常备的Linux标准命令行工具,演示在性能调查最开始的60秒里要干的事,

最开始的60秒……

运行下面10个命令,你可以在60秒内就对系统资源的使用情况和进程的运行状况有大体上的了解。无非是先查看错误信息和饱和指标,再看下资源的使用量。这里“饱和”的意思是,某项资源供不应求,已经造成了请求队列的堆积,或者延长了等待时间。

uptime
dmesg | tail
vmstat 1
mpstat -P ALL 1
pidstat 1
iostat -xz 1
free -m
sar -n DEV 1
sar -n TCP,ETCP 1
top

有些命令需要你安装sysstat包。(译注:指mpstat, pidstat, iostat和sar,用包管理器直接安装sysstat即可) 这些命令所提供的指标能够帮助你实践USE方法:这是一种用于定位性能瓶颈的方法论。你可以以此检查所有资源(CPU,内存,硬盘,等等)的使用量,是否饱和,以及是否存在错误。同时请留意上一次检查正常的时刻,这将帮助你减少待分析的对象,并指明调查的方向。(译注:USE方法,就是检查每一项资源的使用量(utilization)、饱和(saturation)、错误(error))

接下来的章节里我们将结合实际例子讲解这些命令。如果你想了解更多的相关信息,请查看它们的man page。

1. uptime

$ uptime
 23:51:26 up 21:31,  1 user,  load average: 30.02, 26.43, 19.02

这个命令显示了要运行的任务(进程)数,通过它能够快速了解系统的平均负载。在Linux上,这些数值既包括正在或准备运行在CPU上的进程,也包括阻塞在uninterruptible I/O(通常是磁盘I/O)上的进程。它展示了资源负载(或需求)的大致情况,不过进一步的解读还有待其它工具的协助。对它的具体数值不用太较真。

最右的三个数值分别是1分钟、5分钟、15分钟系统负载的移动平均值。它们共同展现了负载随时间变动的情况。举个例子,假设你被要求去检查一个出了问题的服务器,而它最近1分钟的负载远远低于15分钟的负载,那么你很可能已经扑了个空。

在上面的例子中,负载均值最近呈上升态势,其中1分钟值高达30,而15分钟值仅有19。这种现象有许多种解释,很有可能是对CPU的争用;该系列的第3个和第4个命令——vmstatmpstat——可以帮助我们进一步确定问题所在。

2. dmesg | tail

$ dmesg | tail
[1880957.563150] perl invoked oom-killer: gfp_mask=0x280da, order=0, oom_score_adj=0
[...]
[1880957.563400] Out of memory: Kill process 18694 (perl) score 246 or sacrifice child
[1880957.563408] Killed process 18694 (perl) total-vm:1972392kB, anon-rss:1953348kB, file-rss:0kB
[2320864.954447] TCP: Possible SYN flooding on port 7001. Dropping request.  Check SNMP counters.

这个命令显示了最新的10个系统信息,如果有的话。注意会导致性能问题的错误信息。上面的例子里就包括对过多占用内存的某进程的死刑判决,还有丢弃TCP请求的公告。

不要漏了这一步!检查dmesg总是值得的。

3. vmstat 1

$ vmstat 1
procs ---------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
34  0    0 200889792  73708 591828    0    0     0     5    6   10 96  1  3  0  0
32  0    0 200889920  73708 591860    0    0     0   592 13284 4282 98  1  1  0  0
32  0    0 200890112  73708 591860    0    0     0     0 9501 2154 99  1  0  0  0
32  0    0 200889568  73712 591856    0    0     0    48 11900 2459 99  0  0  0  0
32  0    0 200890208  73712 591860    0    0     0     0 15898 4840 98  1  1  0  0
^C

vmstat(8),是“virtual memory stat”的简称,几十年前就已经包括在BSD套件之中,一直以来都是居家常备的工具。它会逐行输出服务器关键数据的统计结果。

通过指定1作为vmstat的输入参数,它会输出每一秒内的统计结果。(在我们当前使用的)vmstat输出的第一行数据是从启动到现在的平均数据,而不是前一秒的数据。所以我们可以跳过第一行,看看后面几行的情况。

检查下面各列:

r:等待CPU的进程数。该指标能更好地判定CPU是否饱和,因为它不包括I/O。简单地说,r值高于CPU数时就意味着饱和。

free:空闲的内存千字节数。如果你数不清有多少位,就说明系统内存是充足的。接下来要讲到的第7个命令,free -m,能够更清楚地说明空闲内存的状态。

si,so:Swap-ins和Swap-outs。如果它们不为零,意味着内存已经不足,开始动用交换空间的存粮了。

us,sy,id,wa,st:它们是所有CPU的使用百分比。它们分别表示user time,system time(处于内核态的时间),idle,wait I/O和steal time(被其它租户,或者是租户自己的Xen隔离设备驱动域(isolated driver domain),所占用的时间)。

通过相加us和sy的百分比,你可以确定CPU是否处于忙碌状态。一个持续不变的wait I/O意味着瓶颈在硬盘上,这种情况往往伴随着CPU的空闲,因为任务都卡在磁盘I/O上了。你可以把wait I/O当作CPU空闲的另一种形式,它额外给出了CPU空闲的线索。

I/O处理同样会消耗系统时间。一个高于20%的平均系统时间,往往值得进一步发掘:也许系统花在I/O的时太长了。

在上面的例子中,CPU基本把时间花在用户态里面,意味着跑在上面的应用占用了大部分时间。此外,CPU平均使用率在90%之上。这不一定是个问题;检查下“r”列,看看是否饱和了。

4. mpstat -P ALL 1

$ mpstat -P ALL 1
Linux 3.13.0-49-generic (titanclusters-xxxxx)  07/14/2015  _x86_64_ (32 CPU)

07:38:49 PM  CPU   %usr  %nice   %sys %iowait   %irq  %soft  %steal  %guest  %gnice  %idle
07:38:50 PM  all  98.47   0.00   0.75    0.00   0.00   0.00    0.00    0.00    0.00   0.78
07:38:50 PM    0  96.04   0.00   2.97    0.00   0.00   0.00    0.00    0.00    0.00   0.99
07:38:50 PM    1  97.00   0.00   1.00    0.00   0.00   0.00    0.00    0.00    0.00   2.00
07:38:50 PM    2  98.00   0.00   1.00    0.00   0.00   0.00    0.00    0.00    0.00   1.00
07:38:50 PM    3  96.97   0.00   0.00    0.00   0.00   0.00    0.00    0.00    0.00   3.03
[...]

这个命令显示每个CPU的时间使用百分比,你可以用它来检查CPU是否存在负载不均衡。单个过于忙碌的CPU可能意味着整个应用只有单个线程在工作。

5. pidstat 1

$ pidstat 1
Linux 3.13.0-49-generic (titanclusters-xxxxx)  07/14/2015    _x86_64_    (32 CPU)

07:41:02 PM   UID       PID    %usr %system  %guest    %CPU   CPU  Command
07:41:03 PM     0         9    0.00    0.94    0.00    0.94     1  rcuos/0
07:41:03 PM     0      4214    5.66    5.66    0.00   11.32    15  mesos-slave
07:41:03 PM     0      4354    0.94    0.94    0.00    1.89     8  java
07:41:03 PM     0      6521 1596.23    1.89    0.00 1598.11    27  java
07:41:03 PM     0      6564 1571.70    7.55    0.00 1579.25    28  java
07:41:03 PM 60004     60154    0.94    4.72    0.00    5.66     9  pidstat

07:41:03 PM   UID       PID    %usr %system  %guest    %CPU   CPU  Command
07:41:04 PM     0      4214    6.00    2.00    0.00    8.00    15  mesos-slave
07:41:04 PM     0      6521 1590.00    1.00    0.00 1591.00    27  java
07:41:04 PM     0      6564 1573.00   10.00    0.00 1583.00    28  java
07:41:04 PM   108      6718    1.00    0.00    0.00    1.00     0  snmp-pass
07:41:04 PM 60004     60154    1.00    4.00    0.00    5.00     9  pidstat
^C

pidstat看上去就像top,不过top的输出会覆盖掉之前的输出,而pidstat的输出则添加在之前的输出的后面。这有利于观察数据随时间的变动情况,也便于把你看到的内容复制粘贴到调查报告中。

上面的例子表明,CPU主要消耗在两个java进程上。%CPU列是在各个CPU上的使用量的总和;1591%意味着java进程消耗了将近16个CPU。

6. iostat -xz 1

$ iostat -xz 1
Linux 3.13.0-49-generic (titanclusters-xxxxx)  07/14/2015  _x86_64_ (32 CPU)

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
          73.96    0.00    3.73    0.03    0.06   22.21

Device:   rrqm/s   wrqm/s     r/s     w/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
xvda        0.00     0.23    0.21    0.18     4.52     2.08    34.37     0.00    9.98   13.80    5.42   2.44   0.09
xvdb        0.01     0.00    1.02    8.94   127.97   598.53   145.79     0.00    0.43    1.78    0.28   0.25   0.25
xvdc        0.01     0.00    1.02    8.86   127.79   595.94   146.50     0.00    0.45    1.82    0.30   0.27   0.26
dm-0        0.00     0.00    0.69    2.32    10.47    31.69    28.01     0.01    3.23    0.71    3.98   0.13   0.04
dm-1        0.00     0.00    0.00    0.94     0.01     3.78     8.00     0.33  345.84    0.04  346.81   0.01   0.00
dm-2        0.00     0.00    0.09    0.07     1.35     0.36    22.50     0.00    2.55    0.23    5.62   1.78   0.03
[...]
^C

这个命令可以弄清块设备(磁盘)的状况,包括工作负载和处理性能。注意以下各项:

r/s,w/s,rkB/s,wkB/s:分别表示每秒设备读次数,写次数,读的KB数,写的KB数。它们描述了磁盘的工作负载。也许性能问题就是由过高的负载所造成的。

await:I/O平均时间,以毫秒作单位。它是应用中I/O处理所实际消耗的时间,因为其中既包括排队用时也包括处理用时。如果它比预期的大,就意味着设备饱和了,或者设备出了问题。

avgqu-sz:分配给设备的平均请求数。大于1表示设备已经饱和了。(不过有些设备可以并行处理请求,比如由多个磁盘组成的虚拟设备)

%util:设备使用率。这个值显示了设备每秒内工作时间的百分比,一般都处于高位。低于60%通常是低性能的表现(也可以从await中看出),不过这个得看设备的类型。接近100%通常意味着饱和。

如果某个存储设备是由多个物理磁盘组成的逻辑磁盘设备,100%的使用率可能只是意味着I/O占用

请牢记于心,disk I/O性能低不一定是个问题。应用的I/O往往是异步的(比如预读(read-ahead)和写缓冲(buffering for writes)),所以不一定会被阻塞并遭受延迟。

7. free -m

$ free -m
             total       used       free     shared    buffers     cached
Mem:        245998      24545     221453         83         59        541
-/+ buffers/cache:      23944     222053
Swap:            0          0          0

右边的两列显示:
buffers:用于块设备I/O的缓冲区缓存
cached:用于文件系统的页缓存
它们的值接近于0时,往往导致较高的磁盘I/O(可以通过iostat确认)和糟糕的性能。上面的例子里没有这个问题,每一列都有好几M呢。

比起第一行,-/+ buffers/cache提供的内存使用量会更加准确些。Linux会把暂时用不上的内存用作缓存,一旦应用需要的时候立刻重新分配给它。所以部分被用作缓存的内存其实也算是空闲内存,第二行以此修订了实际的内存使用量。为了解释这一点, 甚至有人专门建了个网站: linuxatemyram

如果你在Linux上安装了ZFS,正如我们在一些服务上所做的,这一点会变得更加迷惑,因为ZFS它自己的文件系统缓存不算入free -m。有时系统看上去已经没有多少空闲内存可用了,其实内存都待在ZFS的缓存里呢。

8. sar -n DEV 1

$ sar -n DEV 1
Linux 3.13.0-49-generic (titanclusters-xxxxx)  07/14/2015     _x86_64_    (32 CPU)

12:16:48 AM     IFACE   rxpck/s   txpck/s    rxkB/s    txkB/s   rxcmp/s   txcmp/s  rxmcst/s   %ifutil
12:16:49 AM      eth0  18763.00   5032.00  20686.42    478.30      0.00      0.00      0.00      0.00
12:16:49 AM        lo     14.00     14.00      1.36      1.36      0.00      0.00      0.00      0.00
12:16:49 AM   docker0      0.00      0.00      0.00      0.00      0.00      0.00      0.00      0.00

12:16:49 AM     IFACE   rxpck/s   txpck/s    rxkB/s    txkB/s   rxcmp/s   txcmp/s  rxmcst/s   %ifutil
12:16:50 AM      eth0  19763.00   5101.00  21999.10    482.56      0.00      0.00      0.00      0.00
12:16:50 AM        lo     20.00     20.00      3.25      3.25      0.00      0.00      0.00      0.00
12:16:50 AM   docker0      0.00      0.00      0.00      0.00      0.00      0.00      0.00      0.00
^C

这个命令可以用于检查网络流量的工作负载:rxkB/s和txkB/s,以及它是否达到限额了。上面的例子中,eth0接收的流量达到22Mbytes/s,也即176Mbits/sec(限额是1Gbit/sec)

我们用的版本中还提供了%ifutil作为设备使用率(接收和发送两者中的最大值)的指标。我们也可以用Brendan的nicstat计量这个值。一如nicstatsar显示的这个值不一定是对的,在这个例子里面就没能正常工作(0.00)。

9. sar -n TCP,ETCP 1

$ sar -n TCP,ETCP 1
Linux 3.13.0-49-generic (titanclusters-xxxxx)  07/14/2015    _x86_64_    (32 CPU)

12:17:19 AM  active/s passive/s    iseg/s    oseg/s
12:17:20 AM      1.00      0.00  10233.00  18846.00

12:17:19 AM  atmptf/s  estres/s retrans/s isegerr/s   orsts/s
12:17:20 AM      0.00      0.00      0.00      0.00      0.00

12:17:20 AM  active/s passive/s    iseg/s    oseg/s
12:17:21 AM      1.00      0.00   8359.00   6039.00

12:17:20 AM  atmptf/s  estres/s retrans/s isegerr/s   orsts/s
12:17:21 AM      0.00      0.00      0.00      0.00      0.00
^C

这个命令显示一些关键TCP指标的汇总。其中包括:
active/s:本地每秒创建的TCP连接数(比如concept()创建的)
passive/s:远程每秒创建的TCP连接数(比如accept()创建的)
retrans/s:每秒TCP重传次数

主动连接数(active)和被动连接数(passive)通常可以用来粗略地描述系统负载。可以认为主动连接是对外的,而被动连接是对内的,虽然严格来说不完全是这个样子。(比如,一个从localhost到localhost的连接)

重传是网络或系统问题的一个信号;它可能是不可靠的网络(比如公网)所造成的,也有可能是服务器已经过载并开始丢包。在上面的例子中,每秒只创建一个新的TCP连接。

10. top

$ top
top - 00:15:40 up 21:56,  1 user,  load average: 31.09, 29.87, 29.92
Tasks: 871 total,   1 running, 868 sleeping,   0 stopped,   2 zombie
%Cpu(s): 96.8 us,  0.4 sy,  0.0 ni,  2.7 id,  0.1 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem:  25190241+total, 24921688 used, 22698073+free,    60448 buffers
KiB Swap:        0 total,        0 used,        0 free.   554208 cached Mem

   PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
 20248 root      20   0  0.227t 0.012t  18748 S  3090  5.2  29812:58 java
  4213 root      20   0 2722544  64640  44232 S  23.5  0.0 233:35.37 mesos-slave
 66128 titancl+  20   0   24344   2332   1172 R   1.0  0.0   0:00.07 top
  5235 root      20   0 38.227g 547004  49996 S   0.7  0.2   2:02.74 java
  4299 root      20   0 20.015g 2.682g  16836 S   0.3  1.1  33:14.42 java
     1 root      20   0   33620   2920   1496 S   0.0  0.0   0:03.82 init
     2 root      20   0       0      0      0 S   0.0  0.0   0:00.02 kthreadd
     3 root      20   0       0      0      0 S   0.0  0.0   0:05.35 ksoftirqd/0
     5 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 kworker/0:0H
     6 root      20   0       0      0      0 S   0.0  0.0   0:06.94 kworker/u256:0
     8 root      20   0       0      0      0 S   0.0  0.0   2:38.05 rcu_sched

top命令包括很多我们之前检查过的指标。它适合用来查看相比于之前的命令输出的结果,负载有了哪些变动。

不能清晰显示数据随时间变动的情况,这是top的一个缺点。相较而言,vmstatpidstat的输出不会覆盖掉之前的结果,因此更适合查看数据随时间的变动情况。另外,如果你不能及时暂停top的输出(Ctrl-s暂停,Ctrl-q继续),也许某些关键线索会湮灭在新的输出中。

在这之后…

有很多工具和方法论有助于你深入地发掘问题。Brendan在2015年Velocity大会上的Linux Performance Tools tutorial中列出超过40个命令,覆盖了观测、基准测试、调优、静态性能调优、分析(profile),和追踪(tracing)多个方面。

use passpahrse in ssh with ForwordAgent

重启机器后,发现本来等于远程可以git checkout的Repo报告说

fatal: Could not read from remote repository.

Please make sure you have the correct access rights

 

因为是用本地的forward useragent 的.估计是本地的key没有被加入user agent.所以查看本地的 agent.

首先查看key是不是给agent管理了?

ssh-add -L

果然返回

The agent has no identities.

果然没有被管理. 然后用ssh-add mykey

ssh-add yourkey

就把自己的key加入的钥匙串(苹果里叫这个)了.然后在登陆远程,就能顺利checkout了.

 

if the private key is protected with passpharse, before use ssh with forwordAgent, you need to use

ssh-add YourPassparse

to add/store the passparse.

这篇文章对于SSH Key管理讲解的比较清新 。建议阅读。 链接

 

 

 

Magento2 下导入产品CSV文件

每次导入都说有错,这里有个字段说明。原文地址

https://firebearstudio.com/blog/the-complete-guide-to-magento-2-product-import-export.html

字段说明

The CSV File Structure

Let’s have a look at CSV file structure for Magento 2 product import. Below, you can find a detailed description of its columns.

sku – a unique product identifier used as a key product attribute in the Magento 2 core. It is required for all products and should be unique for each of them. sku can include both digits and letters without spaces separated with underscores (_) and dashes (-). 唯一的标示。字母和数字。不带空格。允许下划线和横线。

store_view_code – an associated store view code. The column can be empty if an associated store / website have a single sub item.

attribute_set_code – a product attribute set code. Create and configure an attribute set before importing products into Magento 2. It should look exactly the same as an attribute set name including capital letters (e.g. “Default”, “Man shoes” etc.)
product_type – the type of an imported product. Use only lowercase letters (small, configurable etc.) 必须小写
categories – product categories in Magento 2 differs from ones utilized in Magento 1, where comma separated category ids are used. In Magento 2, full names of assigned categories, including full path, are required. Besides, assigned categories should be separated by |. For instance, “Default Category/Gear|Default Category/Gear/Bags” means that product should be assigned to both Gear and Bags categories. The latest one is a subcategory of Gear.  和v1的逗号分割id不同。v2里是分类的完整路径名称,用|分割。
product_websites – an associated product website code. Use lowercase letters only (e.g. “base”). 只能小写
name – a product name.
description – a product description. 可以包含HTML
short_description – a short description of a product. Both, description and short description, could include valid HTML tags.可以包含HTML
weight – a weight of a product. Requires using the following format 1.00000.
product_online – enables or disables products. Use 1 or 0 respectively. 是否在线产品。用1标示是,0表示否
tax_class_name – a product tax class. Allows using capital later and spaces, like in Magento 2 backend (e.g. “Taxable Goods”). 税务等级
visibility – a visibility of a product (e.g. “Catalog, Search”, “Not Visible Individually” etc.). 可见

price – a price of a product (e.g. 34.000). 价格
special_price – a special price of a product (e.g. 34.000). 特价
special_price_from_date – time when Magento starts using a special price instead of a default one (e.g. ’2015-09-01 15:26:29’). 特价开始日期
special_price_to_date – time when MAgento stops using a special price (e.g. ’2015-09-01 15:26:29’). 特价截止日期
url_key – an URL key of product. In case of an empty field, a value is generated automatically based on a product name.
meta_title – a meta title of a product. 产品页meta标签标题
meta_keywords – product meta keywords meta关键字
meta_description – a product meta description meta描述
base_image – the main product’s image and its path. Should be uploaded to /pub/media/import. The path of /sample_data/m/b/mb01-blue-0.jpg has the following structure: /pub/media/import/sample_data/m/b/mb01-blue-0.jpg. In addition, you can use a direct URL of an image, such as http://site.com/images/some_image.jpg.
base_image_label – a label of a base product image. 主要图片路径。相对路径或URL路径。
small_image – a name and a path related to a small product image. Should be also uploaded to /pub/media/import. The path of /sample_data/m/b/mb01-blue-0.jpg has the following structure: /pub/media/import/sample_data/m/b/mb01-blue-0.jpg. In addition, you can use a direct URL of an image, such as http://site.com/images/some_image.jpg.
small_image_label – a label of a small product image. 小图地址
thumbnail_image – a name and a path related to a thumbnail product image. Should be uploaded to /pub/media/import as well. The path of /sample_data/m/b/mb01-blue-0.jpg has the following structure: /pub/media/import/sample_data/m/b/mb01-blue-0.jpg. In addition, you can use a direct URL of an image, such as http://site.com/images/some_image.jpg. 缩图地址
thumbnail_image_label – a product thumbnail label 缩图标签
created_at – time when a product was created. Use the following format: yyyy-mm-dd hh-mm-ss (e.g. 2015-09-01 22:26:27). If the field is empty, date and time of data base record are used. 创建日期。注意格式。
updated_at – time when a product was updated in. Use the following format: yyyy-mm-dd hh-mm-ss (e.g. 2015-09-01 22:26:27). If the field is empty, date and time of data base record are used. 更新日期
new_from_date – sets a product as “new” from the specified date. Use the following format: yyyy-mm-dd hh-mm-ss (e.g. 2015-09-01 22:26:27). 开始设为new的日期
new_to_date – stops displaying a product as “new” from the specified date. Use the following format: yyyy-mm-dd hh-mm-ss (e.g. 2015-09-01 22:26:27). 定制设为new的日期
display_product_options_in – it is a new feature introduced in Magento 2 which specifies a place on a product page where a block with options should be displayed (e.g. “Block after Info Column”). V2的新技能
map_price – a minimum price of a product.
msrp_price – a product’s MSRP price.
map_enabled – use it to enable / disable a product’s minimum price.
gift_message_available – shows that a gift message is available and will be displayed for a particular product.
custom_design – a custom design of a product page.
custom_design_from – a starting date for a custom design of a product page.
custom_design_to – an end date for a custom design of a product page.
custom_layout_update – a custom XML layout for a product page
page_layout – a product page layout (e.g. 1 Column). If empty the field is empty, a default product layout is used.
product_options_container – a product options container.
msrp_display_actual_price_type – a type of a product’s MSRP price.
country_of_manufacture – a country of origin.
additional_attributes – import of product custom options and data related to a simple product associated to a configurable product. A sample value for a simple product associated to configurable product: “color=Red,has_options=0,required_options=0,size_pants=32” (Color attribute is “Red,” simple product has options in Magento 2: has_options = 0 – no required options, size pants attribute value is 32). A sample value for a configurable product in Magento 2 – “has_options=1,required_options=1” (Product has required options, simple product SKU is associated in the _associated_sku column ). 附加属性
qty – a quantity of a particular product in stock. 库存数
out_of_stock_qty – an out of stock quantity of a particular product.
use_config_min_qty – use minimum quantity value from config.
is_qty_decimal – set 1 if a quantity can be decimal.
allow_backorders – set 1 if backorders are enabled.
use_config_backorders – use a default system value for backorder options (enable / disable).
min_cart_qty – a minimum required quantity of a product in shopping cart.
use_config_min_sale_qty – use a default config value for determining a minimum quantity of a sale product.
max_cart_qty – a maximum quantity of a product in a shopping cart.
use_config_max_sale_qty – use a default config value to determine a maximum quantity of a product in a shopping cart.
is_in_stock – 1 – a product is in stock, 0 – a product is out of stock.
notify_on_stock_below – set a minimum product quantity to start a notification about a low stock level.
use_config_notify_stock_qty – use a default system value for a product’s low stock notification.
manage_stock – to control a stock quantity of a product set 1. By setting 0 you allow Magento 2 to consider a product has an unlimited stock level.
use_config_manage_stock – use a default system configuration value for stock management.
use_config_qty_increments – use a product quantity increment from current store configuration. Set 1 to enable; set 0 to disable.
qty_increments – a product quantity increment.
use_config_enable_qty_inc – use a default store configuration value to enable a product quantity increment.
enable_qty_increments – set 1 or 0 to enable or disable product quantity increment.
is_decimal_divided – set 1 if a product quantity increment can be decimal.
website_id – an associated product website ID
related_skus – related products SKUs separated with commas (e.g. 24-WG085_Group,24-WG086,24-WG083-blue,24-UG01)
crosssell_skus – cross-sale product SKUs separated with commas (e.g. 24-WG085_Group,24-WG086,24-WG083-blue,24-UG01)
upsell_skus – upsallers product SKUs separated with comma (e.g. 24-WG085_Group,24-WG086,24-WG083-blue,24-UG01)
additional_images – additional product images (product media gallery) separated with commas. Images should be uploaded to /pub/media/import. The path of /sample_data/m/b/mb01-blue-0.jpg has the following structure: /pub/media/import/sample_data/m/b/mb01-blue-0.jpg. In addition, you can use a direct URL of an image, such as http://site.com/images/some_image.jpg. 附件图片
additional_image_labels – Сomma separated labels for additional product images from the previous column. 附加图片标签
_associated_sku – an associated simple product SKU for a configurable product (several values should be separated with commas).
_associated_default_qty – a default quantity for associated products
_associated_position – associated products position, based on the _associated_sku column

CSS 多class选择器

原文来自

Multiple Class / ID and Class Selectors

Multiple Class / ID and Class Selectors

Chris Coyier // February 22, 2010

Can you spot the difference between these two selectors?

#header.callout { }

#header .callout { }

They look nearly identical, but the top one has no space between “#header” and “.callout” while the bottom one does. This small difference makes a huge difference in what it does. To some of you, that top selector may seem like a mistake, but it’s actually a quite useful selector. Let’s see the difference, what that top selector means, and exploring more of that style selector.

Here is the “plain English” of “#header .callout”:

Select all elements with the class name callout that are decendents of the element with an ID of header.

Here is the “plain English” of “#header.callout”:

Select the element which has an ID of header and also a class name of callout.

Maybe this graphic will make that more clear:

Combinations of Classes and IDs

The big point here is that you can target elements that have combinations of classes and IDs by stringing those selectors together without spaces.
ID and Class Selector

As we covered above, you can target elements by a combination of ID and class.

This Should Be Red

#one.two { color: red; }

Double Class Selector

Target an element that has all of multiple classes. Shown below with two classes, but not limited to two.

Double Class

.three.four { color: red; }

Multiples

We aren’t limited to only two here, we can combine as many classes and IDs into a single selector as we want.

.snippet#header.code.red { color: red; }

Although bear in mind that’s getting a little ridiculous =)
Example

So how useful is all this really? Especially with ID’s, they are supposed to be unique anyway, so why would you need to combine it with a class? I admit the use cases for the ID versions are slimmer, but there are certainly uses. One of those is overriding styles easily.

#header { color: red; }
#header.override { color: black; }

The second targets the same element, but overrides the color, instead of having to use:

.override { color: black !important }

or perhaps prefacing the selector with something even more specific.

More useful is multiple classes and using them in the “object oriented” css style that is all the rage lately. Let’s say you had a bunch of divs on a page, and you used multiple various descriptive class names on them:

They all share the class “box”, which perhaps sets a width or a background texture, something that all of them have in common. Then some of them have color names as classes, this would be for controlling the colors used inside the box. Perhaps green means the box has a greenish background and light green text. A few of them have a class name of “border”, presumably these would have a border on them while the rest would not.

So let’s set something up:

.box { width: 100px; float: left; margin: 0 10px 10px 0; }
.red { color: red; background: pink; }
.blue { color: blue; background: light-blue; }
.green { color: green; background: light-green; }
.border { border: 5px solid black; }

Cool, we have a good toolbox going here, where we can create new boxes and we have a variety of options, we can pick a color and if it has a border or not just by applying some fairly semantic classes. Having this class name toolbox also allows us to target unique combinations of these classes. For example, maybe that black border isn’t working on the red boxes, let’s fix that:

.red.border { border-color: #900; }

Border color on red box changed because it had both the red class and border class

Based on this demo page.
Specificity

Also important to note here is that the specificity values of selectors like this will carry the same weight as if they were separate. This is what gives these the overriding power like the example above.
Browser Compatibility

All good current browsers support this as well as IE back to version 7. IE 6 is rather weird. It selects based on the last selector in the list. So “.red.border” will select based on just “.border”, which kinda ruins things. But if you are supporting IE 6, you are used to this kind of tomfoolery anyway and can just fix it with conditional styles.
Share On
Twitter Facebook Google+

转 决策树

From: http://blog.csdn.net/heiyeshuwu/article/details/46991273

[原]【原创】机器学习算法之:决策树
Posted: July 21st, 2015, 8:12pm CEST

机器学习算法之:决策树

作者:jmz (360电商技术)

1 概览
决策树学习是一种逼近离散值目标函数的方法,在这种方法中学习到的函数被表示为一棵决策树:

1) 学习析取表达式,能再被表示为多个if-then的规则,以提高可读性。

2) 对噪声数据有很好的适应性。–统计特性

3) 决策树学习方法搜索完整表示的假设空间(一个有效的观点是机器学习问题经常归结于搜索问题,即对非常大的假设空间进行搜索、已确定最佳拟合到观察到的数据),从而避免了受限假设空间的不足。决策树学习的归纳偏置(有兴趣参考“归纳偏置”,“奥坎姆剃刀问题”相关问题更详细的描述)是优先选择较小的树。

2 决策树表示
决策树通过把实例从根结点排列(如何选择排列次序是决策树算法的核心)到某个叶子结点来分类实例,叶子结点即为实例所属的分类。树上的每一个结点指定了对实例的某个属性的测试,并且该结点的每一个后继分支对应于该属性的一个可能值。

如,一颗根据天气情况判断是否参加打网球的决策树如下:

0

例如,下面的实例:将被沿着这棵决策树的最左分支向下排列,因而被评定为反例(也就是这棵树预测PlayTennis=No) 。

通常决策树代表实例属性值约束的合取(conjunction)的析取式(disjunction)。从树根到树叶的每一条路径对应一组属性测试的合取,树本身对应这些合取的析取,该决策树对应于以下表达式:

(Outlook=Sunny ٨Humidity=Normal)

٧(Outlook=Overcast)

٧(Outlook=Rain٨ Wind=Weak)

3 适用场景
不同的决策树学习算法可能有这样或那样的不太一致的能力和要求,但根据以上分析描述不难看出、决策树学习最适合具有以下特征的问题:

1) 实例是由“属性-值”对(pair)表示的。最简单的决策树学习中,每一个属性取少数的分离的值(例如,Hot、Mild、Cold)。

2) 目标函数具有离散的输出值。

3) 可能需要析取的描述,如上面指出的,决策树很自然地代表了析取表达式。

4) 训练数据可以包含错误。决策树学习对错误有很好的适应性,无论是训练样例所属的分类错误还是描述这些样例的属性值错误。

5) 训练数据可以包含缺少属性值的实例。

已经发现很多实际的问题符合这些特征,所以决策树学习已经被应用到很多问题中。例如根据疾病分类患者;根据起因分类设备故障;根据拖欠支付的可能性分类贷款申请。对于这些问题,核心任务都是要把样例分类到各可能的离散值对应的类别中,因此经常被称为分类问题

4 基本的决策树学习算法
大多数决策树学习算法是一种核心算法的变体、该算法采用自顶向下的贪婪搜索遍历可能的决策树空间。决策树构造过程是从“哪一个属性将在树的根结点被测试?”这个问题开始的。

1) 使用统计测试来确定每分类能力最好的属性被选作树的根结点的测试。

2) 为根结点属性的每个可能值产生一个分支,并把训练样例排列到适当的分支(也就是,样例的该属性值对应的分支)之下。

3) 重复整个过程,用每个分支结点关联的训练样例来选取在该点被测试的最佳属性。

这形成了对决策树的贪婪搜索,也就是算法从不回溯重新考虑以前的选择。下图描述了该算法的一个简化版本:

1

1. 哪个属性是最佳的分类属性?
ID3 算法的核心问题是选取在树的每个结点要测试的属性,我们希望选择的是最有助于分类实例的属性。

1) 用熵度量样例的纯度

为了精确地定义信息增益,我们先定义信息论中广泛使用的一个度量标准,称为熵(entropy),它刻画了任意样例集的纯度(purity)。给定包含关于某个目标概念的正反样例的样例集S,那么S 相对这个布尔型分类的熵为:

Entropy(S) = -p⊕log2p⊕ -pΘlog2pΘ

其中p⊕是在S 中正例的比例,pΘ是在S 中负例的比例。在有关熵的所有计算中我们定义0log0 为0。

举例说明,假设S 是一个关于某布尔概念的有14 个样例的集合,它包括9 个正例和5 个反例(我们采用记号[9+,5-]来概括这样的数据样例)。那么S 相对于这个布尔分类的熵(Entropy)为:

Entropy ([9+, 5−]) = −(9 / 14) log 2 (9 /14) − (5 / 14) log 2(5 / 14) =0.940

注意,如果S 的所有成员属于同一类,那么S 的熵为0。例如,如果所有的成员是正的 ( p⊕=1 ) , 那么 pΘ 就是 0 , 于是 Entropy(S) =− 1 ⋅ log ( 1 ) − (0) ⋅log (0) = −1 ⋅ 0 − 0 ⋅ log 0 = 0 。

另外,当集合中正反样例的数量相等时熵为1。如果集合中正反例的数量不等时,熵介于0 和1 之间。下图显示了关于某布尔分类的熵函数随着p⊕从0 到1 变化的曲线。
2

信息论中熵的一种解释是,熵确定了要编码集合S 中任意成员(即以均匀的概率随机抽出的一个成员)的分类所需要的最少二进制位数。举例来说,如果p ⊕ 是1,接收者知道抽出的样例必为正,所以不必发任何消息,此时的熵为0。另一方面,如果是p⊕0.5,必须用一个二进制位来说明抽出的样例是正还是负。如果p⊕ 是0.8,那么对所需的消息编码方法是赋给正例集合较短的编码,可能性较小的反例集合较长的编码,平均每条消息的编码少于1 个二进制位。

更一般的,如果目标属性具有c个不同的值,那么S 相对于c 个状态(c-wise)的分类的熵定义为:

3

2) 用信息增益度量期望的熵降低
4

已经有了熵作为衡量训练样例集合纯度的标准,现在可以定义属性分类训练数据的效力的度量标准。这个标准被称为“信息增益”。简单的说,一个属性的信息增益就是由于使用这个属性分割样例而导致的期望熵降低。

其中Values(A)是属性A 所有可能值的集合。

Sv是S 中属性A 的值为v 的子集(也就是,S v ={s∈S|A(s)=v})。

请注意,等式的第一项就是原来集合S 的熵,第二项是用A 分类S 后熵的期望值。这个第二项描述的期望熵就是每个子集的熵的加权和。|Sv |权值为属于Sv 的样例占原始样例S 的比例。所以Gain(S,A)是由于知道属性A的|S |值而导致的期望熵减少。

换句话来讲,Gain(S,A)是由于给定属性A 的值而得到的关于目标函数值的信息。当对S 的一个任意成员的目标值编码时,Gain(S,A)的值是在知道属性A 的值后可以节省的二进制位数。

信息增益正是ID3 算法增长树的每一步中选取最佳属性的度量标准。下图概述了如何使用信息增益来评估属性的分类能力。在这个图中,计算了两个不同属性:湿度(Humidity)和风力(Wind)的信息增益:

5

2. 算法示例
为了演示ID3 算法的具体操作,训练样例入下图。这里,目标属性PlayTennis 对于不同的星期六上午具有yes 和no两个值,我们将根据其他属性来预测这个目标属性值。

先考虑这个算法的第一步,创建决策树的最顶端结点。哪一个属性该在树上第一个被测试呢?ID3算法计算每一个候选属性(也就是Outlook,Temperature,Humidity,和Wind)的信息增益,然后选择信息增益最高的一个。所有四个属性的信息增益为:

Gain(S,Outlook)=0.246

Gain(S,Humidity)=0.151

Gain(S,Wind)=0.048

Gain(S,Temperature)=0.029

其中S 表示来自下图的训练样例的集合。

6

根据信息增益标准,属性Outlook 在训练样例上提供了对目标属性PlayTennis 的最好预测。所以,Outlook 被选作根结点的决策属性,并为它的每一个可能值(也就是Sunny,Overcast 和Rain)在根结点下创建分支。

同时画出的还有被排列到每个新的后继结点的训练样例。注意到每一个Outlook=Overcast 的样例也都是PlayTennis 的正例。所以,树的这个结点成为一个叶子结点,它对目标属性的分类是PlayTennis=Yes。相反,对应Outlook=Sunny 和Outlook=Rain 的后继结点还有非0的熵,所以决策树会在这些结点下进一步展开。

对于非终端的后继结点,再重复前面的过程选择一个新的属性来分割训练样例,这一次仅使用与这个结点关联的训练样例。已经被收编入树的较高结点的属性被排除在外,以便任何给定的属性在树的任意路径上最多仅出现一次。对于每一个新的叶子结点继续这个过程,直到满足以下两个条件中的任一个:

1) 所有的属性已经被这条路径包括

2) 与这个结点关联的所有训练样例都具有同样的目标属性值(也就是它们的熵为0)

下图演示了算法的求解过程:

7

5 用搜索的观点看决策树学习
与其他的归纳学习算法一样,ID3算法可以被描述为从一个假设空间中搜索一个拟合训练样例的假设。被ID3 算法搜索的假设空间就是可能的决策树的集合。ID3算法以一种从简单到复杂的爬山算法遍历这个假设空间。从空的树开始,然后逐步考虑更加复杂的假设,目的是搜索到一个正确分类训练数据的决策树。引导这种爬山搜索的评估函数是信息增益度量。下图描述了这种搜索:

9

可以通过ID3算法的搜索空间和搜索策略深入认识这个算法的优势和不足。

1) ID3算法中的假设空间包含所有的决策树, 避免了搜索不完整假设空间(说明一下:有些算法是搜索不完整假设空间的、具体参考<<机器学习>>这本书)的一个主要风险:假设空间可能不包含目标函数。

2) 当遍历决策树空间时,ID3仅维护单一的当前假设。因为仅考虑单一的假设,ID3算法失去了表示所有一致假设所带来的优势。(说明一下:意思就是说它不能判断有没有其他的决策树也是与现有的训练数据一致的,或者使用新的实例查询来最优地区分这些竞争假设)

3) 在搜索中不进行回溯。每当在树的某一层次选择了一个属性进行测试,它不会再回溯重新考虑这个选择。所以,它易受无回溯的爬山搜索中常见风险影响:收敛到局部最优的答案,但不是全局最优的。

4) 搜索的每一步都使用当前的所有训练样例,以统计为基础决定怎样精化当前的假设。这与那些基于单独的训练样例递增作出决定的方法不同。使用所有样例的统计属性(例如,信息增益)的一个优点是大大减小了对个别训练样例错误的敏感性。

6 决策树学习的归纳偏置(参见归纳偏置相关论述)
1从观测到的训练数据泛化以分类未见实例的策略是什么呢?
换句话说,它的归纳偏置是什么?

如果给定一个训练样例的集合,那么通常有很多决策树与这些样例一致。所以,要描述ID3 算法的归纳偏置,应找到它从所有一致的假设中选择一个的根据。ID3从这些决策树中选择哪一个呢?它选择在使用简单到复杂的爬山算法遍历可能的树空间时遇到的第一个可接受的树。

概略地讲,ID3的搜索策略为

a) 优先选择较短的树而不是较长的

b) 选择那些信息增益高的属性离根结点较近的树。

在ID3 中使用的选择属性的启发式规则和它遇到的特定训练样例之间存在着微妙的相互作用,由于这一点。很难准确地刻划出ID3 的归纳偏置。然而我们可以近似地把它的归纳偏置描述为一种对短的决策树的偏好。

近似的ID3 算法归纳偏置:较短的树比较长的优先

事实上,我们可以想象一个类似于ID3的算法,它精确地具有这种归纳偏置。考虑一种算法,它从一个空的树开始广度优先搜索逐渐复杂的树,先考虑所有深度为1 的树,然后所有深度为2的,……。一旦它找到了一个与训练数据一致的决策树,它返回搜索深度的最小的一致树(例如,具有最少结点的树)。让我们称这种广度优先搜索算法为BFS-ID3。BFS-ID3寻找最短的决策树,因此精确地具有“较短的树比较长的得到优先”的偏置。ID3可被看作BFS-ID3的一个有效近似,它使用一种贪婪的启发式搜索企图发现最短的树,而不用进行完整的广度优先搜索来遍历假设空间。

因为ID3 使用信息增益启发式规则和“爬山”策略,它包含比BFS-ID3更复杂的偏置。尤其是,它并非总是找最短的一致树,而是倾向于那些信息增益高的属性更靠近根结点的树。ID3 归纳偏置的更贴切近似:

较短的树比较长的得到优先。那些信息增益高的属性更靠近根结点的树得到优先。

2. 为什么优先短的假设?
奥坎姆剃刀:优先选择拟合数据的最简单假设。

为什么应该优先选择较简单的假设呢?科学家们有时似乎也遵循这个归纳偏置。例如物理学家优先选择行星运动简单的解释,而不用复杂的解释。对这个问题并没有一个确定性的定论和证明、有兴趣的可以参考相关资料。

7 决策树常见问题
1. 避免过度拟合数据

对于一个假设,当存在其他的假设对训练样例的拟合比它差,但事实上在实例的整个分布(也就是包含训练集合以外的实例)上表现的却更好时,我们说这个假设过度拟合训练样例。

这种情况发生的一种可能原因是训练样例含有随机错误或噪声。事实上,当训练数据没有噪声时,过度拟合也有可能发生,这种情况下,很可能出现巧合的规律性。

有几种途径用来避免决策树学习中的过度拟合。它们可被分为两类:

a) 及早停止增长树法,在ID3 算法完美分类训练数据之前停止增长树;

b) 后修剪法,即允许树过度拟合数据,然后对这个树后修剪。

一个常见的做法是错误率降低修剪:考虑将树上的每一个结点作为修剪的候选对象。修剪一个结点由以下步骤组成:删除以此结点为根的子树;使它成为叶子结点;把和该结点关联的训练样例的最常见分类赋给它。仅当修剪后的树对于验证集合的性能不差于原来的树时才删除该结点。这样便使因为训练集合的巧合规律性而加入的结点很可能被删除,因为同样的巧合不大会发生在验证集合中。反复地修剪结点,每次总是选取它的删除可以最大提高决策树在验证集合上的精度的结点。继续修剪结点直到进一步的修剪是有害的。

2. 合并连续值属性

把连续值属性的值域分割为离散的区间集合。其实本质还是处理离散值、只是将连续值划分为离散值。

3. 属性选择的其他度量标准

信息增益度量存在一个内在偏置,它偏袒具有较多值的属性。举一个极端的例子,考虑属性Date,它有大量的可能值(例如March 4,1979)。要是我们把这个属性加到数据中,它会在所有属性中有最大的信息增益。

这是因为单独Date就可以完全预测训练数据的目标属性。于是这个属性会被选作树的根结点的决策属性并形成一棵深度为一级但却非常宽的树,这棵树可以理想地分类训练数据。当然,这个决策树对于后来数据的性能会相当差,因为尽管它完美地分割了训练数据,但它不是一个好的预测器(predicator)。

属性Date出了什么问题了呢?简单地讲,是因为它太多的可能值必然把训练样例分割成非常小的空间。因此,相对训练样例,它会有非常高的信息增益,尽管对于未见实例它是一个非常差的目标函数预测器。避免这个不足的一种方法是用其他度量,而不是信息增益,来选择决策属性。关于选取其他度量属性度量标准、参见参考资料。

4. 处理缺少属性值的训练样例

在某些情况下,可供使用的数据可能缺少某些属性的值。例如,在医学领域我们希望根据多项化验指标预测患者的结果,然而可能仅有部分患者具有验血结果。在这种情况下,经常需要根据此属性值已知的其他实例,来估计这个缺少的属性值。

处理缺少属性值的一种策略是赋给它结点n 的训练样例中该属性的最常见值。另一种策略是可以赋给它结点n 的被分类为c(x)的训练样例中该属性的最常见值。

5. 处理代价不同的属性

在某些学习任务中,实例的属性可能与代价相关。例如,在学习分类疾病时我们可能以这些属性来描述患者:体温、活组织切片检查、脉搏、血液化验结果等。这些属性在代价方面差别非常大,不论是所需的费用还是患者要承受的不适。对于这样的任务,我们将优先选择尽可能使用低代价属性的决策树,仅当需要产生可靠的分类时才依赖高代价属性。考虑代价的相关算法参见参考资料。

参考资料:

1<<机器学习>> Tom M. Mitchell

2<> Andrew Ng

课程翻译:

http://v.163.com/special/opencourse/machinelearning.html

讲义下载:

http://openclassroom.stanford.edu/MainFolder/CoursePage.php?course=MachineLearning

<完>

————————————————————————————-

黑夜路人,一个关注开源技术、乐于学习、喜欢分享的程序员

博客�� [blog.csdn.net]

微博�� [weibo.com]

微信:heiyeluren2012

想获取更多IT开源技术相关信息,欢迎关注微信!

微信二维码扫描快速关注本号码:

作者:heiyeshuwu 发表于2015/7/21 20:12:43 原文链接 阅读:35 评论:0 查看评论

firefox 中 hash会被预先urldecode

fiefox中如果直接使用 window.location.hash 返回的是已经 urldecode的字符串。chrome则不是。这种情况下,如果接着使用 decodeURIComponent  就很容易遇到错误。

解决办法是使用

location.href.split("#")[1].substring(1)

比如
var hash = window.location.hash.substring(1);
改为

var hash= (location.href.splice("#")[1] || "").substring(1);