Python学习:jsonpath的性能问题
2020-12-26 本文已影响0人
khaos
问题
前面刚总结了,利用jsonpath可以快速访问和设置json对象节点值的帖子。没想到这么快就打脸了。python的jsonpath居然性能如此之差,简直无法接受。
今天其实就是抛一个问题,作为记录,希望后续能够找到解决之道。
方案
利用python装饰器,可以轻松写一个记录函数执行时间的功能。代码如下:
import time
from functools import wraps
def exec_time():
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
beg = time.time() * 1000
ret = func(*args, **kwargs)
end = time.time() * 1000
print('func:{%s} exec time is:{%.5f} ms' % (func.__name__, end - beg))
return ret
return wrapper
return decorator
回到jsonpath问题上来,简单写了一个设置节点值的代码,如下:
js = {'a': 10, 'b': 20, 'c': {'e': 10, 'f': 'string'}, 'c1': {'e': 10, 'f': 'string'}, 'c2': {'e': 10, 'f': 'string'}}
JsonHelper(js).set('e', 20)
JsonHelper(js).get('e')
JsonHelper(js).set('e', 30)
JsonHelper(js).get('e')
JsonHelper(js).set('e', 40)
JsonHelper(js).get('e')
JsonHelper(js).set('e', 50)
JsonHelper(js).get('e')
输出为:
func:{set} exec time is:{9.77808} ms
func:{get} exec time is:{7.33887} ms
func:{set} exec time is:{6.12109} ms
func:{get} exec time is:{6.15625} ms
func:{set} exec time is:{5.82568} ms
func:{get} exec time is:{5.17139} ms
func:{set} exec time is:{4.96606} ms
func:{get} exec time is:{4.96899} ms
这么简单的json节点set和get,居然要接近10ms级别。再对比python对象的直接访问:
@exec_time()
def op_dict(data, field):
data[field] = 20
return data
输出:
func:{op_dict} exec time is:{0.00122} ms
python直接访问,性能居然相差千遍以上。jsonpath-ng的性能确实很差,库的实现有问题。不死心,又找到另外两个jsonpath库,一个就是jsonpath,一个是jsonpath-rw,再次验证性能:
import jsonpath
@exec_time()
def test_jsonpath(data, field):
return jsonpath.jsonpath(data, field)
from jsonpath_rw import parse as parserw
@exec_time()
def test_jsonpathrw(data, field):
jsonpath_expr = parserw(field)
return jsonpath_expr.find(data)
js = {'a': 10, 'b': 20, 'c': {'e': 10, 'f': 'string'}, 'c1': {'e': 10, 'f': 'string'}, 'c2': {'e': 10, 'f': 'string'}}
print(test_jsonpath(js, '$..e'))
print(test_jsonpathrw(js, '$..e'))
输出为:
func:{test_jsonpath} exec time is:{0.57471} ms
func:{test_jsonpathrw} exec time is:{5.48584} ms
结果很明显,jsonpath比jsonpath-ng性能相差10倍,但也并不算很好,与原始的json对象直接访问近100倍性能之差。jsonpath-rw的性能和jsonpath-ng差不多,实际上jsonpath-ng就是基于jsonpath-rw改造的。可惜jsonpath还不支持节点设置功能,jsonpath也不是好的选择。
讨论
本文中的exec_time装饰器,可以作为日常开发调测的工具箱中,尤其是引用第三方库的时候,需要及时验证下性能问题。
对于jsonpath,目前第三方库中确实难以找到合适的库可以使用。期待库的作者能够意识到性能问题并修复。后面的方向,找一下c语言的jsonpath库,试一试集成到python中,规避性能问题。