Python 求平均运行时间

2018-10-24 09:38:54 +08:00
 ladypxy

如题,log 类似下面这样

get_foo start 913912131
get_foo end 14141251132
get_abc start 12312415
get_def start 123156151
get_def end 123115112312
get_abc end 121515161

第一列是线程名,最后一列是线程运行时间 怎么求同名线程的平均运行时间?

3039 次点击
所在节点    Python
20 条回复
laqow
2018-10-24 09:43:47 +08:00
给个 lock 让主线程去算啊
ladypxy
2018-10-24 09:46:08 +08:00
@laqow python 练习题……就是分析日志
holajamc
2018-10-24 10:06:14 +08:00
这……怎么平均
ladypxy
2018-10-24 10:12:50 +08:00
@holajamc 我的理解是,首先筛选第一列相同的 get_foo,然后就一行 end 的第三列减去一行 start 的第三列。就是一次执行时间,然后把文件中所有 get_foo 的执行时间求和,除以执行次数
holajamc
2018-10-24 10:35:04 +08:00
@ladypxy 但是线程名都不相同…而且都只运行了一次 emmm 不懂
msg7086
2018-10-24 10:46:40 +08:00
@holajamc 人家总不能贴个几万行的日志上论坛吧……
ladypxy
2018-10-24 10:48:40 +08:00
@holajamc 这只是日志格式。。。不能贴几百行上来啊。。难点就是线程名不同,要先根据线程名筛选,然后再根据 start end 筛选。
我目前想法是,用多个 list 来实现,但是感觉太笨重了。。
holajamc
2018-10-24 10:55:27 +08:00
@msg7086
@ladypxy
2333 确实有些误解了
xcolder
2018-10-24 11:01:15 +08:00
塞到 map 里
beny2mor
2018-10-24 11:01:20 +08:00
用一个 namedtuple 和一个 dict 就可以了吧
统计值放到 tuple namedtuple('LogStatistic', ['已经统计的线程数', '统计过的线程的时间'])

用一个 dict 保存线程的开始时间 {'get_foo': {start: 913912131}, 'get_abc': {start: 12312415}} 用来保存时间,每读取到数据看看是否 start 和 end 都有了,有的话从 dict 中删除这个键,统计进入 tuple
princelai
2018-10-24 11:15:29 +08:00
用到了 python pandas 包

df = pd.read_clipboard(header=None)

df.columns = ['process','status','time']

df.groupby(by='process').apply(lambda x:(x.sort_values(by='time').loc[x.status=='end','time'].values - - x.sort_values(by='time').loc[x.status=='start','time'].values).mean())


前提是要保证线程的 start 和 end 的数量是匹配的

写完上面我又想到一个更好的办法,透视表
df_pivot = df.pivot_table( values='time', index='process',columns='status',aggfunc=list)

df_pivot.apply(lambda x:(pd.np.array(sorted(x.end)) - pd.np.array(sorted(x.start))).mean(), axis=1)
xpresslink
2018-10-24 11:45:08 +08:00
首先楼主的问题没有描述清楚,给的信息不够,如同名线程中后面的线程比前面的先结束,如何正确配对开始和结束时间?
另外,说心理话这么简单个问题都要到这里来问,劝退。楼主你不是干这行的料。
ladypxy
2018-10-24 12:10:57 +08:00
@princelai 用 pandas 实现很简单,但是最好使用自带的函数解决。。。下面的不错,不过我 pivot 一点没看。。。但是表示感谢。。。。

@xpresslink 原始的题目就是这样的,应该是同名的前面的总是比后面的先结束。
我本来就不是码农,闲的没事学 python,我这才看了 3 天,有问题还不能问了? 看了下你的回帖,总是对提问人各种嘲讽。难道你是什么都知道?呵呵
princelai
2018-10-24 14:21:03 +08:00
@ladypxy 那也简单啊,建个 defaultdict ( list ),key 是( process,status ),value 是[time],然后相减,其实就是一个 group by 操作
xpresslink
2018-10-24 14:24:37 +08:00
@ladypxy,我这么说你肯定不服气,下面用你能理解的方式写了一个算法。

#!/usr/bin/env python
# -*- coding: utf-8 -*-

data = """get_foo start 913912131
get_foo end 14141251132
get_abc start 12312415
get_def start 123156151
get_def end 123115112312
get_abc end 121515161
get_foo start 913912131
get_foo end 14141251132
get_abc start 12312415
get_def start 123156151
get_def end 123115112312
get_abc end 121515161
get_foo start 913912131
get_foo end 14141251132
get_abc start 12312415
get_def start 123156151
get_def end 123115112312
get_abc end 121515161
"""

i_data = (l.split() for l in data.splitlines())

result={}
for proc, flag, timestamp in i_data:
□□□□temp = result.setdefault(proc, {'sum':0,'cnt':0, 'start':0})
□□□□if flag == 'start':
□□□□□□□□temp['start']=int(timestamp)
□□□□else:
□□□□□□□□temp['sum'] += int(timestamp) - temp['start']
□□□□□□□□temp['cnt'] += 1

for p, v in result.items():
□□□□print('process:', p, 'avg time:',v['sum']/v['cnt'])
jmc891205
2018-10-24 14:31:09 +08:00
最暴力的做法
线程名做 key,总时间和运行次数组成一个 tuple 做 value
遍历一遍日志全塞到一个 dict 里
最后遍历一遍 dict 把每个线程的平均时间求出来
ladypxy
2018-10-24 14:57:20 +08:00
用比较笨的方法实现了一下

with open('logtest.txt','r',encoding='utf-8') as f:
list=[]
for lines in f:
list.append(lines.split())

api_name={}
count={}
for i in list:
if i[0] not in api_name:
api_name.update({i[0]:(0-int(i[2]))})
count.update({i[0]:int("1")})
else:
if i[1] =="end":
api_name.update({i[0]:(int(i[2])+int(api_name[i[0]]))})
count.update({i[0]:(count[i[0]]+1)})
if i[1] == "start":
api_name.update({i[0]:(int(api_name[i[0]]-int(i[2])))})
count.update({i[0]:(count[i[0]]+1)})

for i in count.keys():
print('api',i,"average running time =",api_name[i] / count[i])
aijam
2018-10-24 16:55:30 +08:00
import sys

d = {}
n = 0
s = 0
for line in sys.stdin:
____name, flag, t = line.split()
____t = int(t)
____if flag == "start":
________d[name] = t
____elif name in d:
________s += t - d[name]
________n += 1
________del d[name]

print(s / n)
shm7
2018-10-24 17:05:05 +08:00
导入 pandas,求出 unique names,然后 reshape(2, N/2), sum(ax=1) -> (start_sum, end_sum) -> (end_sum - start_sum) / N * 2
ladypxy
2018-10-24 18:26:58 +08:00
@aijam 感谢回复。。。第一次发现 python 居然可以这样赋值。。name, flag, t = line.split()

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/500505

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX