即使一个人,也要活得像军队一样!

Odoo13-- 代码性能分析

最近有些小伙伴总是问我代码这么写行不行,性能怎么样,balabala……

其实Odoo本身已经给我们提供了分析工具Profile
下面就介绍一下profile

profile的使用

profile的定义位于 odoo.tools目录下的 profile.py 和 misc.py文件。小伙伴请自行阅读源码。

姿势一: Graph a method

以Graph形式的代码分析,就是为执行的方法生成图形。

标准姿势:

1
2
3
4
from odoo.tools.misc import profile
[...]
@profile('/temp/prof.profile')
def mymethod(...)

这个性能工具在misc包中,因此需要从那里进行导入。
它会生成一个进一步生成图形文件的包含统计数据的文件。
要使用这个性能工具,你需要传递文件路径来作为参数。
在调用该函数时,它会在给定位置生成一个文件。
参见下例,它会在桌面生成一个make_available.prof文件

1
2
3
4
5
6
7
8
from odoo.tools.misc import profile
...
@profile('/Users/parth/Desktop/make_available.profile')
def make_available(self):
if self.state != 'lost':
self.write({'state': 'available'})
self.env['res.partner'].create({'name': 'test', 'email': 'test@ada.asd'})
return True

在调用make_available方法时,它会在桌面生成一个文件。要将这个数据转化为图形数据,需要安装gprof2dot工具,然后执行给定的命令来生成图形:

1
gprof2dot -f pstats -o /Users/parth/Desktop/prof.xdot /Users/parth/Desktop/make_available.prof

这条命令会在桌面上生成prof.xdot 文件。然后,你可以使用下面的命令来通过xdot显示图形

1
xdot /Users/parth/Desktop/prof.xdot

姿势二: Log a method

以Log形式的代码分析,就是为执行的方法生成通过日志方式输出。

标准姿势:

1
2
3
4
5
from odoo.tools.profiler import profile
[...]
@profile
@api.model
def mymethod(...):

实战姿势:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@profile
def action_confirm(self):
if self._get_forbidden_state_confirm() & set(self.mapped('state')):
raise UserError(_(
'It is not allowed to confirm an order in the following states: %s'
) % (', '.join(self._get_forbidden_state_confirm())))

for order in self.filtered(lambda order: order.partner_id not in order.message_partner_ids):
order.message_subscribe([order.partner_id.id])
self.write({
'state': 'sale',
'date_order': fields.Datetime.now()
})
self._action_confirm()
if self.env.user.has_group('sale.group_auto_done_setting'):
self.action_done()
return True

结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

2019-11-23 05:58:47,018 187644 INFO 13 odoo.tools.profiler:
calls queries ms
sale.order -------------------------- F:\WORK\Odoo13\odoo\addons\sale\models\sale.py, 727

1 0 1.0 @profile
def action_confirm(self):
1 10 49.42 if self._get_forbidden_state_confirm() & set(self.mapped('state')):
raise UserError(_(
'It is not allowed to confirm an order in the following states: %s'
) % (', '.join(self._get_forbidden_state_confirm())))
3 13 54.82 for order in self.filtered(lambda order: order.partner_id not in order.message_partner_ids):
1 13 46.88 order.message_subscribe([order.partner_id.id])
1 0 0.0 self.write({
1 0 0.0 'state': 'sale',
1 37 330.79 'date_order': fields.Datetime.now()
})
1 20 70.31 self._action_confirm()
1 1 0.96 if self.env.user.has_group('sale.group_auto_done_setting'):
self.action_done()
1 0 0.0 return True

Total:
1 94 554.17
-------------本文结束感谢您的阅读-------------