先谈下我们需求,一个比较大的nginx访问日志,根据访问日期切割日志,保存在/tmp目录下。

测试机器为腾讯云机子,单核1G内存。测试日志大小80M。

不使用多线程版:

#!/usr/bin/env python
# coding=utf-8 import re
import datetime if __name__ == '__main__':
date_pattern = re.compile(r'\[(\d+)\/(\w+)\/(\d+):')
with open('./access_all.log-20161227') as f:
for line in f:
day, mon, year = re.search(date_pattern, line).groups()
mon = datetime.datetime.strptime(mon, '%b').month
log_file = '/tmp/%s-%s-%s' % (year, mon, day)
with open(log_file, 'a+') as f:
f.write(line)

耗时:

[root@VM_255_164_centos data_parse]# time python3 log_cut.py 
real 0m41.152s
user 0m32.578s
sys 0m6.046s

多线程版:

#!/usr/bin/env python
# coding=utf-8 import re
import datetime
import threading date_pattern = re.compile(r'\[(\d+)\/(\w+)\/(\d+):') def log_cut(line):
day, mon, year = re.search(date_pattern, line).groups()
mon = datetime.datetime.strptime(mon, '%b').month
log_file = '/tmp/%s-%s-%s' % (year, mon, day)
with open(log_file, 'a+') as f:
f.write(line) if __name__ == '__main__':
with open('./access_all.log-20161227') as f:
for line in f:
t = threading.Thread(target=log_cut, args=(line,))
t.setDaemon(True)
t.start()

耗时:

# time python3 log_cut.py 

real    1m35.905s
user 1m10.292s
sys 0m19.666s

使用多线程版竟然比不使用多进程版要慢的多。。cpu密集型任务使用上下文切换果然很耗时。

线程池版:

线程池类

#!/usr/bin/env python
# coding=utf-8 import queue
import threading
import contextlib
import time StopEvent = object() class ThreadPool(object): def __init__(self, max_num, max_task_num = None):
if max_task_num:
self.q = queue.Queue(max_task_num)
else:
self.q = queue.Queue()
self.max_num = max_num
self.cancel = False
self.terminal = False
self.generate_list = []
self.free_list = [] def run(self, func, args, callback=None):
if self.cancel:
return
if len(self.free_list) == 0 and len(self.generate_list) < self.max_num:
self.generate_thread()
w = (func, args, callback,)
self.q.put(w) def generate_thread(self):
t = threading.Thread(target=self.call)
t.start() def call(self):
current_thread = threading.currentThread()
self.generate_list.append(current_thread) event = self.q.get()
while event != StopEvent: func, arguments, callback = event
try:
result = func(*arguments)
success = True
except Exception as e:
success = False
result = None if callback is not None:
try:
callback(success, result)
except Exception as e:
pass with self.worker_state(self.free_list, current_thread):
if self.terminal:
event = StopEvent
else:
event = self.q.get()
else:
self.generate_list.remove(current_thread) def close(self):
self.cancel = True
full_size = len(self.generate_list)
while full_size:
self.q.put(StopEvent) #
full_size -= 1 def terminate(self):
self.terminal = True while self.generate_list:
self.q.put(StopEvent) self.q.queue.clear() @contextlib.contextmanager
def worker_state(self, state_list, worker_thread):
state_list.append(worker_thread)
try:
yield
finally:
state_list.remove(worker_thread)

threadingPool.py

代码

#!/usr/bin/env python
# coding=utf-8 import re
import datetime
from threadingPool import ThreadPool date_pattern = re.compile(r'\[(\d+)\/(\w+)\/(\d+)\:') def log_cut(line):
day, mon, year = date_pattern.search(line).groups()
mon = datetime.datetime.strptime(mon, '%b').month
log_file = '/tmp/%s-%s-%s' % (year, mon, day)
with open(log_file, 'a+') as f:
f.write(line) def callback(status, result):
pass pool = ThreadPool(1) with open('./access_all.log-20161227') as f:
for line in f:
pool.run(log_cut, (line,), callback) pool.close()

耗时:

# time python3 log_cut2.py 

real    0m53.371s
user 0m44.761s
sys 0m5.600s

线程池版比多线程版要快,看来写的线程池类还是有用的。减少了上下文切换时间。

进程池版:

#!/usr/bin/env python
# coding=utf-8 import re
import datetime
from multiprocessing import Pool date_pattern = re.compile(r'\[(\d+)\/(\w+)\/(\d+):') def log_cut(line):
day, mon, year = re.search(date_pattern, line).groups()
mon = datetime.datetime.strptime(mon, '%b').month
log_file = '/tmp/%s-%s-%s' % (year, mon, day)
with open(log_file, 'a+') as f:
f.write(line) if __name__ == '__main__':
pool = Pool(1)
with open('./access_all.log-20161227') as f:
for line in f:
pool.apply_async(func=log_cut, args=(line,))
pool.close()

单个进程耗时:

# time python3 log_cut.py 

real    0m28.392s
user 0m23.451s
sys 0m1.888s

2个进程耗时:

# time python3 log_cut.py 

real    0m40.920s
user 0m33.690s
sys 0m3.206s

看来使用多进程时,如果是单核cpu只开一个进程,多核cpu的话开多个速度更快,单核cpu开多个进程速度很慢。

shell版

#!/bin/bash

Usage(){
echo "Usage: $0 Logfile"
} if [ $# -eq ] ;then
Usage
exit
else
Log=$
fi date_log=$(mktemp) cat $Log |awk -F'[ :]' '{print $5}'|awk -F'[' '{print $2}'|uniq > date_log for i in `cat date_log`
do
grep $i $Log > /tmp/log/${i::}-${i::}-${i::}.access done

耗时:

# time sh log_cut.sh access_all.log- 

real    0m2.435s
user 0m2.042s
sys 0m0.304s

shell的效果非常棒啊,只用2s多久完成了。

按日期切割nginx访问日志--及性能优化的更多相关文章

  1. 性能调优之访问日志IO性能优化

    性能调优之访问日志IO性能优化   poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.如果对课程感兴趣,请大家咨询qq:908821 ...

  2. 访问日志IO性能优化

    在高并发量的场景下磁盘IO往往是性能的瓶颈所在,访问日志涉及到频繁的写操作,所以这部分要尽可能地优化,不然将拖累系统的整体性能.针对文件记录及数据库记录两种方式可以有以下措施提高写性能, l 避免频繁 ...

  3. 采集并分析Nginx访问日志

    日志服务支持通过数据接入向导配置采集Nginx日志,并自动创建索引和Nginx日志仪表盘,帮助您快速采集并分析Nginx日志. 许多个人站长选取了Nginx作为服务器搭建网站,在对网站访问情况进行分析 ...

  4. Nginx访问日志.Nginx日志切割

    11月27日任务 12.10 Nginx访问日志12.11 Nginx日志切割12.12 静态文件不记录日志和过期时间 1.Nginx访问日志 示例一: 日志格式 vim /usr/local/ngi ...

  5. Nginx 访问日志轮询切割

    Nginx 访问日志轮询切割脚本 #!/bin/sh Dateformat=`date +%Y%m%d` Basedir="/application/nginx" Nginxlog ...

  6. Nginx访问日志、 Nginx日志切割、静态文件不记录日志和过期时间

    1.Nginx访问日志 配制访问日志:默认定义格式: log_format combined_realip '$remote_addr $http_x_forwarded_for [$time_loc ...

  7. Nginx访问日志、日志切割、静态文件不记录日志和过期时间

    6月8日任务 12.10 Nginx访问日志12.11 Nginx日志切割12.12 静态文件不记录日志和过期时间 12.10 Nginx访问日志 除了在主配置文件nginx.conf里定义日志格式外 ...

  8. Linux centosVMware Nginx访问日志、Nginx日志切割、静态文件不记录日志和过期时间

    一.Nginx访问日志 vim /usr/local/nginx/conf/nginx.conf //搜索log_format  日至格式 改为davery格式 $remote_addr  客户端IP ...

  9. nginx访问日志(access_log)

    一.nginx访问日志介绍 nginx软件会把每个用户访问网站的日志信息记录到指定的日志文件里,供网站提供者分析用户的浏览行为等,此功能由ngx_http_log_module模块负责,对应的官方地址 ...

随机推荐

  1. iOS获取网络图片大小

    在iOS开发过程中经常需要通过网络请求加载图片,有时,需要在创建UIImageView或UIButton来显示图片之前需要提前知道图片的尺寸,根据图片尺寸创建对应大小的控件.但是对于网络图片来说,要想 ...

  2. 在项目中使用ExtJS

    主要目录文件介绍 builds:压缩后的ExtJS代码,体积更小,更快:docs:开发文档:examples:官方演示示例:locale:多国语言资源文件:pkgs:ExtJS各部分功能的打包文件:r ...

  3. SCVMM中Clone虚拟机失败显示Unsupported Cluster Configuration状态

    在SCVMM进行虚拟机的Clone,虽然失败了,但是Clone出虚拟机却显示在SCVMM控制台的虚拟机的列表中,并且状态是Unsupported Cluster Configuration.无法修复, ...

  4. APUE学习之三个特殊位 设置用户ID(set-user-ID),设置组ID(set-group-ID),sticky

    设置用户ID(set-user-ID),设置组ID(set-group-ID),sticky   set-user-ID: SUID      当文件的该位有设置时,表示当该文件被执行时,程序具有文件 ...

  5. SQL Server 2008 阻止保存要求重新创建表的更改问题的设置方法

    不是很理解为什么在2008中会加入阻止保存要求重新创建表的更改这个选项.症状表现为修改表结构的时候会"阻止"你.而且我遇到的情况是居然有的时候阻止你,有的时候不阻止你,摸不到头脑. ...

  6. jquery $.each终止本次循环

    1.for循环中我们使用continue:终止本次循环计入下一个循环,使用break终止整个循环. 2.而在jquery中 $.each则对应的使用return true 进入下一个循环,return ...

  7. Java 类的实例变量初始化的过程 静态块、非静态块、构造函数的加载顺序

    先看一道Java面试题: public class Baset { private String baseName = "base"; // 构造方法 public Baset() ...

  8. ANSI Common Lisp Practice - My Answers - Chatper - 3

    Ok, Go ahead. 1 (a) (b) (c) (d) 2 注:union 在 Common Lisp 中的作用就是求两个集合的并集.但是这有一个前提,即给的两个列表已经满足集合的属性了.具体 ...

  9. mysql workbench如何把已有的数据库导出ER模型

    mysql workbench的特长是创建表结构的,然后在结构图中,圈圈点点,很容易就利用可视化方式把数据库建好,然后再导入到数据库服务器中,这种办法很效率.但是有时我们有一个需求,事先没有建表结构模 ...

  10. C#通过属性名称获取(读取)属性值的方法

    之前在开发一个程序,希望能够通过属性名称读取出属性值,但是由于那时候不熟悉反射,所以并没有找到合适的方法,做了不少的重复性工作啊! 然后今天我再上网找了找,被我找到了,跟大家分享一下. 其实原理并不复 ...