当系统swap空间所剩不多时,可通过在本地磁盘上创建普通文件作为swap,步骤如下:
$ dd if=/dev/zero of=./swapfile bs=1M count=1000
$ mkswap ./swapfile
$ swapon ./swapfile
即可为系统临时增加1G的swap。
使用完毕后执行:
$ swapoff ./swapfile
$ rm -f swapfile
vim变量
vim中的变量类型和大多数高级语言的基本变量类似,大概可以分为:
1. 数值
2. 浮点数
3. 字符串
4. 函数引用变量
5. 列表
6. 字典
简单说一下函数引用变量、列表变量、字典变量。
一. 函数引用变量
函数引用变量通过function()函数得到,用在表达式里来代替函数名。例如:
:let Fn = function("MyFunc")
:echo Fn()
函数引用变量必须以大写字母、"s:"、"w:"、"t:"、或"b:"开始,引用变量不能和其他任何函数重名。这些前缀的意思和申请变量时前缀一样,分别表明其作用域(:help internal-variables):
b: 局部于当前缓冲区。 :help buffer-variable
w: 局部于当前窗口。 :help window-variable
t: 局部于当前标签页。 :help tabpage-variable
g: 全局。 :help global-variable
l: 局部于函数。 :help local-variable
s: 局部于 |:source| 的 Vim 脚本。 :help script-variable
a: 函数参数 (只限于函数内使用)。 :help function-argument
v: Vim 预定义的全局变量。 :help vim-variable
二. 列表变量
列表变量和perl的变量很类似,比如:
:let mylist = [1, two, 3, "four"]
:let nestlist = [[11, 12], [21, 22], [31, 32]]
1. 访问列表项目时同样用索引的办法:
:let item = mylist[0]; " 得到第一个项目: 1
:let item = nestlist[0][1] " 得到第三个项目: 3
也可以试用负数索引,它的意思就是列表倒数,比如:
:let last = mylist[-1] " 得到最后一个项目: "four"
要避免非法索引值产生的错误,用 |get()| 函数。如果项目不存在,它返回零或者你指定的缺省值:
:echo get(mylist, idx)
:echo get(mylist, idx, "NONE")
2. 列表连接 两个列表可以用 "+" 操作符连接,比如 :let longlist = mylist + [5, 6]
3. 子列表 列表的一部分可以通过指定首末两个索引获得,方括号内以冒号分隔两者:
:let shortlist = mylist[2:-1] " 得到列表 [3, "four"]
:let endlist = mylist[2:] " 从项目 2 到结束: [3, "four"]
4. 列表同一 如果变量 "aa" 是列表,把它赋给另一个变量 "bb" 后,两个变量指向同一列表。因此,对列表 "aa" 的修改也同时修改了 "bb":
:let aa = [1, 2, 3]
:let bb = aa
:call add(aa, 4)
:echo bb
[1, 2, 3, 4]
|copy()| 函数可以复制列表。如上所述,用 [:] 也可。这种方式建立列表的浅备份: 改变列表中的列表项目仍然会修改复制列表的相应项目:
:let aa = [[1, ‘a’], 2, 3]
:let bb = copy(aa)
:call add(aa, 4)
:let aa[0][1] = ‘aaa’
:echo aa
[[1, aaa], 2, 3, 4]
:echo bb
[[1, aaa], 2, 3]
可用操作符 "is" 检查两个变量是否指向同一个列表。"isnot" 刚好相反。与此对照,"==" 比较两个列表的值是否相同。
:let alist = [1, 2, 3]
:let blist = [1, 2, 3]
:echo alist is blist
0
:echo alist == blist
1
比较列表时 注意: 如果长度相同,所有项目用 "==" 的比较的结果也相同,两个列表就认为相同。有一个例外: 数值和字符串总被认为不相同。这里不进行自动类型转换,而在变量间直接用 "==" 却不是如此。例如:
echo 4 == "4"
1
echo [4] == ["4"]
0
5. 列表解包 要给列表项目解包,即把它们分别存入单独的变量,用方括号把变量括起来,如同把它们当作列表项目:
:let [var1, var2] = mylist
6. 列表修改 要修改列表的指定项目,用:let命令:
:let list[4] = "four"
:let listlist[0][3] = item
VIM内建了大量操作列表的函数,可以查阅:help function-list,找到针对列表操作的函数群,查看其用途。利用这些函数就可以修改列表。
7. For 循环 就跟perl的for循环遍历列表数据类似:
:for item in mylist
: call Doit(item)
:endfor
就像 |:let| 命令,|:for| 也可以接受变量的列表。这需要参数是列表的列表。
:for [lnum, col] in [[1, 3], [2, 8], [3, 0]]
: call Doit(lnum, col)
:endfor
三. 字典变量
字典是关联数组: 每个项目有一个键和一个值。这和perl的关联数组(%)类似,用键可以定位项目,而项目的存储不能确定任何特定顺序。
1. 字典建立
字典通过花括号里逗号分隔的项目列表建立。每个项目包含以冒号分隔的键和值(perl中用"=>"分隔)。一个键只能出现一次。例如:
:let mydict = {1: ‘one’, 2: ‘two’, 3: ‘three’}
键必须是字符串。用数值也可以,但它总被自动转换为字符串。所以字符串 ‘4’ 和数值4 总会找到相同的项目。注意 字符串 ’04’ 和数值 04 是不一样的,因为后者被转换成字符串 ‘4’。
2. 访问项目
常见的访问项目的方式是把键放入方括号:
:let val = mydict["one"]
:let mydict["four"] = 4
用这种方式可以给已存在的字典增加新项目,这和列表不同。
如果键只包含字母、数字和下划线,可以使用如下形式 |expr-entry|:
:let val = mydict.one
:let mydict.four = 4
因为项目可以是包括列表和字典的任何类型,你可以反复使用索引和键进行访问:
:echo dict.key[idx].key
3. 字典到列表的转换
你可以循环遍历字典的所有项目。为此,你需要把字典转为列表,然后把它传递给:for
通常,你期望遍历所有的键,用 |keys()| 函数就可以了:
:for key in keys(mydict)
: echo key . ‘: ‘ . mydict[key]
:endfor
要遍历所有的值,用 |values()| 函数: >
:for v in values(mydict)
: echo "value: " . v
:endfor
如果你想同时得到键和值,用 |items()| 函数。它返回一个列表,其中每个项目是两个项目的列表: 键和值:
:for [key, value] in items(mydict)
: echo key . ‘: ‘ . value
:endfor
4. 字典同一
就像列表那样,你需要用 |copy()| 和 |deepcopy()| 来构造字典的备份。否则,赋值产生的结果会引用同一个字典:
:let onedict = {‘a’: 1, ‘b’: 2}
:let adict = onedict
:let adict[‘a’] = 11
:echo onedict[‘a’]
11
5. 字典修改
要修改字典已经存在的项目或者增加新的项目,用:let:
:let dict[4] = "four"
:let dict[‘one’] = item
从字典里删除项目可以通过 |remove()| 或 |:unlet| 完成。从 dict 里删除键 "aaa" 的项目有三种方法:
:let i = remove(dict, ‘aaa’)
:unlet dict.aaa
:unlet dict[‘aaa’]
6. 字典函数
关于Apache调优点滴
Apache 通过管道记日志对性能的影响:
- 如果访问量比较小,则,使用管道可能比只直接写文件要快那么一点点(不会太明显),因为写管道毕竟是些内存(但是操作系统层面对写文件也是有优化的)
- 如果访问量很大,多个进程并发写一个管道,而只有一个进程在读管道,写日志文件,则,管道很容易写慢导致处理进程阻塞,这时,管道产生的瓶颈是很明显的,可能会导致Apache的处理性能减少一个数量级;而且你看到的将是cpu idle很高,iowait很低,
但是loadaverage却很高。
关于gearman
这次看gearman关注了两个问题:
1. 可以异步(后台)执行任务,addTaskBackground();
2. 可以并发执行多个任务, runTasks(); 这个在一定程度上弥补了PHP不能多线程编程的弊端。
进程的一生
随着一句fork,一个新进程呱呱落地,但它这时只是老进程的一个克隆。
然后随着exec,新进程脱胎换骨,离家独立,开始了为人民服务的职业生涯。
人有生老病死,进程也一样,它可以是自然死亡,即运行到main函数的最后一个"}",从容地离我们而去;也可以是自杀,自杀有2种方 式,一种是调用exit函数,一种是在main函数内使用return,无论哪一种方式,它都可以留下遗书,放在返回值里保留下来;它还甚至能可被谋杀, 被其它进程通过另外一些方式结束他的生命。
进程死掉以后,会留下一具僵尸,wait和waitpid充当了殓尸工,把僵尸推去火化,使其最终归于无形。
这就是进程完整的一生。
给Apache做压力测试时遇到的问题
最近,在Linux上对Apache-2.1.16做了一下压力测试;只访问一个简单的hello world静态文件,做了多次,每秒处理请求次数才700左右;
一定是哪里出现了问题,因为:
1. 虽然load很高,但是cpu和io都很低,这种现象就比较奇怪
2. client端的负载很低
3. 曾经有过 2000/s的测试,而且当时的机器配置比现在的要差的多
当我使用同样的方法对nginx做测试的时候,nginx可以达到 2.2w/s 。
无奈之下,只好又把strace请出来了,发现写日志的地方很慢。
于是怀疑是磁盘问题; 使用hdparm测试了一下磁盘,没有问题; 又用 time dd … 测试了一下,写的速度也 700+MB/s ; 回头想想,确认了一下nginx也是记日志的,而且都是同一块磁盘,大概不是磁盘问题了。
修改Apache 配置文件,把记日志的配置注释掉, 重新测试,发现可以达到 7k+/s 了;仔细观察Apache的配置,是这样写的:
TransferLog "|/data1/apache2/bin/rotatelogs /path/to/logfile"
于是,我想怀疑rotatelogs 这个程序了,但是似乎也没有道理; 那么就只剩下那个管道了,恩, 大概问题就出现在管道上了。
因为管道的大小为4k, 多进程写管道,单进程读管道,也难免会出现阻塞的情况;另外,load高的时候,io是很低的,所以说磁盘不是瓶颈。 管道是瓶颈
———-
如何利用管道来模拟一个cpu、io都很低,但是load很高的实例呢?
GNU、GPL、Linux
首先是GNU计划,由理查德*斯托尔曼发起。GNU组织发布了一系列的GNU工具集。
然后到91年的时候,Linus开发了Linux,当时不过是一个内核;由于Linux采用开放源代码,所以自然和GNU的开源精神不谋而合,两者就结合在一起了。其结果就是一个完整的GNU/Linux操作系统出现了。
GPL(General Public License,通用公共许可协议)是一种版权形式,是Richard Stallman在开放源代码软件发行的实践中,逐渐总结出的一套保护自由软件的条款,称之为GPL
Copyright 与 Copyleft : http://91win.blog.163.com/blog/static/390038662008624904962/
多线程与虚拟内存
前面文章提到siege是一个多线程程序,在32位的机器上,我准备使用500个并发做测试,结果发现报内存不够的错误。
于是,使用gdb跟了一下,在创建完线程后,报错的函数出停止,看看到底使用了多少内存,结果发现使用虚拟内存3G,实际占用物理内存2.3M,很明显,不是物理内存不足,而是32位机器的虚拟内存的大小所限导致的,更大的物理内存也没有意义,关键是要支持更大的虚拟内存,如果使用64位的机器,一个够他折腾了。
问题: 创建线程真的需要很大的虚拟内存的开销吗?创建线程的开销是怎么计算的?和主线程占用内存大小的关系是怎样的?
再用gdb跟一下,这次在pthread_create处设置断点,使用top观察内存变化情况,发现:
1. 创建线程之前,程序使用虚拟内存5M,物理内存1M
2. 创建1个线程后,程序使用虚拟内存增加10M,物理内存增加4K
3. 继续观察创建更多线程的情况,发现,每创建一个线程,虚拟内存增加10M,物理内存增加4K
线程真的很消耗虚拟内存资源吗?都用来做什么了?
关于http server的几个压测工具
1. ab
Apache自带的一个工具,是一个单进程、单线程的程序,采用异步的http请求来实现并发;表现到server上的并发数可能就不是给ab设置的并发数了; 所以可以使用下面两个工具。
2. webbench
http://home.tiscali.cz/~cz210552/webbench.html
这是一个多进程实现并发的程序,结果都通过管道汇总到主进程。
- 统计信息太简单,只知道访问次数,不知道响应时间的分布
- 目前还不支持keep-alive
3. siege
http://www.joedog.org/index/siege-home
这是一个多线程实现并发的程序。
4. http_load
http://www.acme.com/software/http_load/
html Meta
meta是用来在HTML文档中模拟HTTP协议的响应头报文。meta 标签用于网页的<head>与</head>中,meta 标签的用处很多。meta 的属性有两种:name和http-equiv。name属性主要用于描述网页,对应于content(网页内容),以便于搜索引擎机器人查找、分类(目 前几乎所有的搜索引擎都使用网上机器人自动查找meta值来给网页分类)。这其中最重要的是description(站点在搜索引擎上的描述)和 keywords(分类关键词),所以应该给每页加一个meta值。比较常用的有以下几个:
name 属性
1、<meta name="Generator" contect="">用以说明生成工具(如Microsoft FrontPage 4.0)等;
2、<meta name="KEYWords" contect="">向搜索引擎说明你的网页的关键词;
3、<meta name="DEscription" contect="">告诉搜索引擎你的站点的主要内容;
4、<meta name="Author" contect="你的姓名">告诉搜索引擎你的站点的制作的作者;
5、<meta name="Robots" contect= "all|none|index|noindex|follow|nofollow">
其中的属性说明如下:
设定为all:文件将被检索,且页面上的链接可以被查询;
设定为none:文件将不被检索,且页面上的链接不可以被查询;
设定为index:文件将被检索;
设定为follow:页面上的链接可以被查询;
设定为noindex:文件将不被检索,但页面上的链接可以被查询;
设定为nofollow:文件将不被检索,页面上的链接可以被查询。
http-equiv属性
1、<meta http-equiv="Content-Type" contect="text/html";charset=gb_2312-80">
和 <meta http-equiv="Content-Language" contect="zh-CN">用以说明主页制作所使用的文字以及语言;
又如英文是ISO-8859-1字符集,还有BIG5、utf-8、shift-Jis、Euc、Koi8-2等字符集;
2、<meta http-equiv="Refresh" contect="n;url=http://yourlink">定时让网页在指定的时间n内,跳转到页面http://yourlink;
3、<meta http-equiv="Expires" contect="Mon,12 May 2001 00:20:00 GMT">可以用于设定网页的到期时间,一旦过期则必须到服务器上重新调用。需要注意的是必须使用GMT时间格式;
4、<meta http-equiv="Pragma" contect="no-cache">是用于设定禁止浏览器从本地机的缓存中调阅页面内容,设定后一旦离开网页就无法从Cache中再调出;
5、<meta http-equiv="set-cookie" contect="Mon,12 May 2001 00:20:00 GMT">cookie设定,如果网页过期,存盘的cookie将被删除。需要注意的也是必须使用GMT时间格式;
6、<meta http-equiv="Pics-label" contect="">网页等级评定,在IE的internet选项中有一项内容设置,可以防止浏览一些受限制的网站,而网站的限制级别就是通过meta属性来设置的;
7、<meta http-equiv="windows-Target" contect="_top">强制页面在当前窗口中以独立页面显示,可以防止自己的网页被别人当作一个frame页调用;
8、<meta http-equiv="Page-Enter" contect="revealTrans(duration=10,transtion= 50)">和<meta http-equiv="Page-Exit" contect="revealTrans(duration=20,transtion=6)">设定进入和离开页面时的特殊效果,这个功能即 FrontPage中的“格式/网页过渡”,不过所加的页面不能够是一个frame页面。
以上是常用的几个meta属性,有个人主页的朋友不妨在你的主页中加上它,效果可是不一样的哦:)。