Below you can see the profiling results, created using cProfile as suggested by MuMind, setting up a Django view to start the stand-alone method profileJSON(), which in turn calls the different solutions to create the JSON output.def startProfileJSON(request): print "startProfileJSON" import cProfile cProfile.runctx('profileJSON()', globals=globals(), locals=locals()) print "endProfileJSON"结果:解决方案 1: 3350347 次函数调用(3130372 次原始调用)在 4.969 秒内(详细信息)Solution 1: 3350347 function calls (3130372 primitive calls) in 4.969 seconds (details)解决方案 2: 3.630 秒内 2533705 次函数调用(2354516 次原始调用)(详细信息)Solution 2: 2533705 function calls (2354516 primitive calls) in 3.630 seconds (details)解决方案 3: 2533621 次函数调用(2354441 次原始调用)在 3.684 秒内(详细信息)Solution 3: 2533621 function calls (2354441 primitive calls) in 3.684 seconds (details)解决方案 4: 2812725 次函数调用(2466028 次原始调用)在 3.840 秒内(详细信息)Solution 4: 2812725 function calls (2466028 primitive calls) in 3.840 seconds (details)解决方案 5: 3.779 秒内 2536504 次函数调用(2357256 次原始调用)(详情一>)Solution 5: 2536504 function calls (2357256 primitive calls) in 3.779 seconds (details)解决方案 6(改进的解决方案 4): 3.663 秒内 2593122 次函数调用(2299165 次原始调用)(详情)Solution 6 (Improved solution 4): 2593122 function calls (2299165 primitive calls) in 3.663 seconds (details)讨论:解决方案1:自己的编码实现.坏主意Solution 1: own encoding implementation. bad idea解决方案 2 + 3:目前最快,但仍然很慢Solution 2 + 3: currently the fastest, but still painfully slow解决方案 4:缓存孩子看起来很有希望,但确实表现相似并且当前产生无效的 json,因为孩子被放入双 []:Solution 4: looks promising with caching childs, but does perform similar and currently produces not valid json as childrens are put into double []:"children": [[]] instead of "children": []解决方案 5:使用 select_related 没有什么区别,但可能以错误的方式使用,因为节点总是对其父节点有一个外键,而我们正在从根解析到子节点.Solution 5: use of select_related does not make a difference, whereas probably used in the wrong way, as a node always have a ForeignKey to its parent, and we are parsing from root to child.更新:解决方案 6:对我来说,它看起来是最干净的解决方案,使用子节点的缓存.但只执行类似于解决方案 2 + 3.这对我来说很奇怪.Update: Solution 6: It looks like the cleanest solution to me, using caching of child nodes. But does only perform similar to solution 2 + 3. Which for me is strange.有没有更多关于性能改进的想法?Anybody more ideas for performance improvements?推荐答案我怀疑到目前为止最大的减速是每个节点执行 1 个数据库查询.与数据库的数百次往返相比,json 呈现是微不足道的.I suspect by far the biggest slowdown is that this will do 1 database query per node. The json rendering is trivial in comparison to the hundreds of round-trips to your database.您应该在每个节点上缓存子节点,以便可以一次性完成这些查询.django-mptt 有一个 cache_tree_children() 功能,你可以做到这一点.You should cache the children on each node so that those queries can be done all at once.django-mptt has a cache_tree_children() function you can do this with.import jsonfrom mptt.templatetags.mptt_tags import cache_tree_childrendef recursive_node_to_dict(node): result = { 'id': node.pk, 'name': node.name, } children = [recursive_node_to_dict(c) for c in node.get_children()] if children: result['children'] = children return resultroot_nodes = cache_tree_children(Node.objects.all())dicts = []for n in root_nodes: dicts.append(recursive_node_to_dict(n))print json.dumps(dicts, indent=4)自定义 json 编码,虽然它在某些情况下可能会提供轻微的加速,但我非常不鼓励这样做,因为它会有很多代码,而且很容易获得 非常错误.Custom json encoding, while it might provide a slight speedup in some scenarios, is something I'd highly discourage, as it will be a lot of code, and it's something that's easy to get very wrong. 这篇关于使用 mptt 创建 JSON 以反映 Python/Django 中的树结构的最快方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持! 上岸,阿里云!
08-27 08:58