如题,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
第一列是线程名,最后一列是线程运行时间 怎么求同名线程的平均运行时间?
1
laqow 2018-10-24 09:43:47 +08:00 via Android
给个 lock 让主线程去算啊
|
3
holajamc 2018-10-24 10:06:14 +08:00
这……怎么平均
|
4
ladypxy OP @holajamc 我的理解是,首先筛选第一列相同的 get_foo,然后就一行 end 的第三列减去一行 start 的第三列。就是一次执行时间,然后把文件中所有 get_foo 的执行时间求和,除以执行次数
|
7
ladypxy OP @holajamc 这只是日志格式。。。不能贴几百行上来啊。。难点就是线程名不同,要先根据线程名筛选,然后再根据 start end 筛选。
我目前想法是,用多个 list 来实现,但是感觉太笨重了。。 |
9
xcolder 2018-10-24 11:01:15 +08:00
塞到 map 里
|
10
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 |
11
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) |
12
xpresslink 2018-10-24 11:45:08 +08:00
首先楼主的问题没有描述清楚,给的信息不够,如同名线程中后面的线程比前面的先结束,如何正确配对开始和结束时间?
另外,说心理话这么简单个问题都要到这里来问,劝退。楼主你不是干这行的料。 |
13
ladypxy OP @princelai 用 pandas 实现很简单,但是最好使用自带的函数解决。。。下面的不错,不过我 pivot 一点没看。。。但是表示感谢。。。。
@xpresslink 原始的题目就是这样的,应该是同名的前面的总是比后面的先结束。 我本来就不是码农,闲的没事学 python,我这才看了 3 天,有问题还不能问了? 看了下你的回帖,总是对提问人各种嘲讽。难道你是什么都知道?呵呵 |
14
princelai 2018-10-24 14:21:03 +08:00 via Android
@ladypxy 那也简单啊,建个 defaultdict ( list ),key 是( process,status ),value 是[time],然后相减,其实就是一个 group by 操作
|
15
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']) |
16
jmc891205 2018-10-24 14:31:09 +08:00
最暴力的做法
线程名做 key,总时间和运行次数组成一个 tuple 做 value 遍历一遍日志全塞到一个 dict 里 最后遍历一遍 dict 把每个线程的平均时间求出来 |
17
ladypxy OP 用比较笨的方法实现了一下
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]) |
18
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) |
19
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
|