|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
欢迎大家来到仓酷云论坛!近期要在公司外部做个LinuxIO方面的培训,收拾动手头的材料给人人分享下
各类IO监督工具在LinuxIO系统布局中的地位
源自LinuxPerformanceandTuningGuidelines.pdf
1体系级IO监控
iostat
iostat-xdm1#团体习气
%util代表磁盘忙碌水平。100%暗示磁盘忙碌,0%暗示磁盘余暇。可是注重,磁盘忙碌不代表磁盘(带宽)使用率高
argrq-sz提交给驱动层的IO哀求巨细,一样平常不小于4K,不年夜于max(readahead_kb,max_sectors_kb)
可用于判别以后的IO形式,一样平常情形下,特别是磁盘忙碌时,越年夜代表按次,越小代表随机
svctm一次IO哀求的办事工夫,关于单块盘,完整随机读时,基础在7ms摆布,既寻道+扭转提早工夫
注:各统计量之间干系
=======================================
%util=(r/s+w/s)*svctm/1000#行列长度=抵达率*均匀办事工夫
avgrq-sz=(rMB/s+wMB/s)*2048/(r/s+w/s)#2048为1M/512
=======================================
总结:
iostat统计的是通用块层经由兼并(rrqm/s,wrqm/s)后,间接向设备提交的IO数据,能够反应体系全体的IO情况,可是有以下2个弱点:
1间隔营业层对照悠远,跟代码中的write,read不合错误应(因为体系预读+pagecache+IO调剂算法等要素,也很难对应)
2是体系级,没举措准确到历程,好比只能告知你如今磁盘很忙,可是没举措告知你是谁在忙,在忙甚么?
2历程级IO监控
iotop和pidstat(仅rhel6u系列)
iotop望文生义,io版的top
pidstat望文生义,统计历程(pid)的stat,历程的stat天然包含历程的IO情况
这两个下令,都能够按历程统计IO情况,因而能够回覆你以下二个成绩
- 以后体系哪些历程在占用IO,百分比是几?
- 占用IO的历程是在读?仍是在写?读写量是几?
pidstat参数良多,仅给出几个团体习气
pidstat-d1#只显现IO
pidstat-u-r-d-t1#-dIO信息,
#-r缺页及内存信息
#-uCPU利用率
#-t以线程为统计单元
#11秒统计一次
iotop,很复杂,间接敲下令
block_dump,iodump
iotop和pidstat用着很爽,但二者都依附于/proc/pid/io文件导出的统计信息,这个关于老一些的内核是没有的,好比rhel5u2
因而只好用以上2个穷汉版下令来替换:
echo1>/proc/sys/vm/block_dump#开启block_dump,此时会把io信息输出到dmesg中
#源码:submit_bio@ll_rw_blk.c:3213
watch-n1"dmesg-c|grep-oP"w+(d+):(WRITE|READ)"|sort|uniq-c"
#一直的dmesg-c
echo0>/proc/sys/vm/block_dump#不必时封闭
也能够利用现成的剧本iodump,详细拜见http://code.google.com/p/maatkit/source/browse/trunk/util/iodump?r=5389
iotop.stp
systemtap剧本,一看就晓得是iotop下令的穷汉复制版,必要安装Systemtap,默许每隔5秒输入一次信息
stapiotop.stp#examples/io/iotop.stp
总结
历程级IO监控,
- 能够回覆体系级IO监控不克不及回覆的2个成绩
- 间隔营业层绝对较近(比方,能够统计历程的读写量)
可是也没有举措跟营业层的read,write接洽在一同,同时颗粒度较粗,没有举措告知你,以后历程读写了哪些文件?耗时?巨细?
3营业级IO监控
ioprofile
ioprofile下令实质上是lsof+strace,详细下载可见http://code.google.com/p/maatkit/
ioprofile能够回覆你以下三个成绩:
1以后历程某工夫内,在营业层面读写了哪些文件(read,write)?
2读写次数是几?(read,write的挪用次数)
3读写数据量几?(read,write的byte数)
假定某个举动会触发步伐一次IO举措,比方:"一个页面点击,招致背景读取A,B,C文件"
============================================
./io_event#假定摹拟一次IO举动,读取A文件一次,B文件500次,C文件500次
ioprofile-p`pidofio_event`-ccount#读写次数
ioprofile-p`pidofio_event`-ctimes#读写耗时
ioprofile-p`pidofio_event`-csizes#读写巨细
注:ioprofile仅撑持多线程步伐,对单线程步伐不撑持.关于单线程步伐的IO营业级剖析,strace足以。
总结:
ioprofile实质上是strace,因而能够看到read,write的挪用轨迹,能够做营业层的io剖析(mmap体例力所不及)
4文件级IO监控
文件级IO监控能够共同/增补"营业级和历程级"IO剖析
文件级IO剖析,次要针对单个文件,回覆以后哪些历程正在对某个文件举行读写操纵.
1lsof大概ls/proc/pid/fd
2inodewatch.stp
lsof告知你以后文件由哪些历程翻开
lsof../io#io目次以后由bash和lsof两个历程翻开
lsof下令只能回覆静态的信息,而且"翻开"其实不必定"读取",关于cat,echo如许的下令,翻开和读取都是刹时的,lsof很难捕获
能够用inodewatch.stp来填补
stapinodewatch.stpmajorminorinode#主设备号,辅设备号,文件inode节点号
stapinodewatch.stp0xfd0x00523170#主设备号,辅设备号,inode号,能够经由过程stat下令取得
5IO摹拟器
iotest.py#见附录
开辟职员能够使用ioprofile(大概strace)做具体剖析体系的IO路径,然后在步伐层面做响应的优化。
可是一样平常情形下调剂步伐,价值对照年夜,特别是当不断定修正计划究竟能不克不及无效时,最好有某种摹拟路子以疾速考证。
觉得我们的营业为例,发明某次查询时,体系的IO会见形式以下:
会见了A文件一次
会见了B文件500次,每次16字节,均匀距离502K
会见了C文件500次,每次200字节,均匀距离4M
这里B,C文件是交织会见的,既
1先会见B,读16字节,
2再会见C,读200字节,
3回到B,跳502K后再读16字节,
4回到C,跳4M后,再读200字节
5反复500次
strace文件以下:
一个复杂朴实的设法,将B,C交织读,改成先批量读B,再批量读C,因而调剂strace文件以下:
将调剂后的strace文件,作为输出交给iotest.py,iotest.py依照strace文件中的会见形式,摹拟响应的IO
iotest.py-sio.strace-ffmap
fmap为映照文件,将strace中的222,333等fd,映照到实践的文件中
===========================
111=/opt/work/io/A.data
222=/opt/work/io/B.data
333=/opt/work/io/C.data
===========================
6磁盘碎片收拾
一句话:只需磁盘容量不终年坚持80%以上,基础上不必忧虑碎片成绩。
假如其实忧虑,能够用defrag剧本
7其他IO相干下令
blockdev系列
=======================================
blockdev--getbsz/dev/sdc1#检察sdc1盘的块巨细
blockblockdev--getra/dev/sdc1#检察sdc1盘的预读(readahead_kb)巨细
blockdev--setra256/dev/sdc1#设置sdc1盘的预读(readahead_kb)巨细,低版的内核经由过程/sys设置,偶然会失利,不如blockdev靠谱
=======================================
附录iotest.py
- #!/usr/bin/envpython#-*-coding:gbk-*-importosimportreimporttimeitfromctypesimportCDLL,create_string_buffer,c_ulong,c_longlongfromoptparseimportOptionParserusage=%prog-sstrace.log-ffileno.map_glibc=None_glibc_pread=None_c_char_buf=None_open_file=[]defgetlines(filename):_lines=[]withopen(filename,r)as_f:forlinein_f:ifline.strip()!="":_lines.append(line.strip())return_linesdefparsecmdline():parser=OptionParser(usage)parser.add_option("-s","--strace",dest="strace_filename",help="stracefile",metavar="FILE")parser.add_option("-f","--fileno",dest="fileno_filename",help="filenofile",metavar="FILE")(options,args)=parser.parse_args()ifoptions.strace_filenameisNone:parser.error("straceisnotspecified.")ifnotos.path.exists(options.strace_filename):parser.error("stracefiledoesnotexist.")ifoptions.fileno_filenameisNone:parser.error("filenoisnotspecified.")ifnotos.path.exists(options.strace_filename):parser.error("filenofiledoesnotexist.")returnoptions.strace_filename,options.fileno_filename#[type,...]#[pread,fno,count,offset]#pread(15,"",4348,140156928)defparse_strace(filename):lines=getlines(filename)action=[]_regex_str=r(pread|pread64)[^d]*(d+),s*[^,]*,s*([dkKmM*+-.]*),s*([dkKmM*+-.]*)foriinlines:_match=re.match(_regex_str,i)if_matchisNone:continue#跳过有效行_type,_fn,_count,_off=_match.group(1),_match.group(2),_match.group(3),_match.group(4)_off=_off.replace(k,"*1024").replace(K,"*1024").replace(m,"*1048576").replace(M,"*1048576")_count=_count.replace(k,"*1024").replace(K,"*1024").replace(m,"*1048576").replace(M,"*1048576")#print_offaction.append([_type,_fn,str(int(eval(_count))),str(int(eval(_off)))])returnactiondefparse_fileno(filename):lines=getlines(filename)fmap={}foriinlines:ifi.strip().startswith("#"):continue#正文行_split=[j.strip()forjini.split("=")]iflen(_split)!=2:continue#有效行fno,fname=_split[0],_split[1]fmap[fno]=fnamereturnfmapdefsimulate_before(strace,fmap):global_open_file,_c_char_bufrfmap={}foriinfmap.values():_f=open(i,"r+b")#print"open{0}:{1}".format(_f.fileno(),i)_open_file.append(_f)rfmap[i]=str(_f.fileno())#反向映照to_read=4*1024#默许4Kbufforiinstrace:i[1]=rfmap[fmap[i[1]]]#fid->fname->fid映照转换to_read=max(to_read,int(i[2]))#print"readbufferlen:%dByte"%to_read_c_char_buf=create_string_buffer(to_read)defsimulate_after():global_open_filefor_fin_open_file:_f.close()defsimulate(actions):#timeit.time.sleep(10)#歇息2秒钟,以便IO距离start=timeit.time.time()foractinactions:__simulate__(act)finish=timeit.time.time()returnfinish-startdef__simulate__(act):global_glibc,_glibc_pread,_c_char_bufif"pread"inact[0]:_fno=int(act[1])_buf=_c_char_buf_count=c_ulong(int(act[2]))_off=c_longlong(int(act[3]))_glibc_pread(_fno,_buf,_count,_off)#print_glibc.time(None)else:passpassdefloadlibc():global_glibc,_glibc_pread_glibc=CDLL("libc.so.6")_glibc_pread=_glibc.pread64if__name__=="__main__":_strace,_fileno=parsecmdline()#剖析下令行参数loadlibc()#加载静态库_action=parse_strace(_strace)#剖析action文件_fmap=parse_fileno(_fileno)#剖析文件名映照文件simulate_before(_action,_fmap)#预处置#print"totaliooperate:%d"%(len(_action))#foractin_action:print"".join(act)print"%f"%simulate(_action)
复制代码
欢迎大家来到仓酷云论坛! |
|