在PyV8中分析Javascript
Profiling Javascript in PyV8
本文关键字:Javascript PyV8 更新时间:2023-09-26
我有一个JS代码库在PyV8中运行。现在我想提高它的性能,但似乎没有任何钩子来启用V8分析器。在PyV8的旧主干版本中,有一些引用分析器的选项,但我没有找到任何关于它的文档。你有关于如何在PyV8配置文件没有我重写python到js包装的想法吗?
你知道有哪个js -only框架使用猴子补丁来生成时序配置文件吗?如果涉及到一些开销,这不是什么大问题——总比根本没有配置文件要好。
最后我找到了我在《Pro Javascript设计模式》一书中需要的提示:使用闭包和func.apply
在函数上应用instrumentation。不幸的是,JS修饰函数的方式不像Python那样干净——但是,嘿,它工作了,我得到了我需要深入研究代码性能特征的信息。
profile.js
function mod_profiler() {
var profile_by_function_name = {};
var total_time = 0;
var time_counting_for_function = null;
function get_function_name(func) {
var result = func.toString();
result = result.substr('function '.length);
result = result.substr(0, result.indexOf('('));
return result;
}
function update_profile(function_name, elapsed_time) {
var profile = profile_by_function_name[function_name];
if (profile === undefined) {
profile = {calls:0, elapsed_time:0};
profile_by_function_name[function_name] = profile;
}
profile.calls += 1;
profile.elapsed_time += elapsed_time;
if (time_counting_for_function === function_name) {
total_time += elapsed_time;
}
}
function profile(func) {
function profiled() {
var function_name = get_function_name(func);
if (time_counting_for_function === null) {
time_counting_for_function = function_name;
}
var start_time = new Date().getTime()
var result = func.apply(undefined, arguments);
var elapsed_time = new Date().getTime() - start_time;
update_profile(function_name, elapsed_time);
if (time_counting_for_function === function_name) {
time_counting_for_function = null;
}
return result;
}
return profiled;
}
function get_formatted_result() {
function get_whitespace(length) {
var result = "";
for (var i = 0; i < length; i++) {
result += " ";
}
return result;
}
var function_names = Object.keys(profile_by_function_name);
var function_names_sorted_by_elapsed_time = function_names.sort(function (a,b) {
var elapsed_a = profile_by_function_name[a].elapsed_time;
var elapsed_b = profile_by_function_name[b].elapsed_time;
if (elapsed_a < elapsed_b) {
return 1;
}
if (elapsed_a > elapsed_b) {
return -1;
}
return 0;
});
var max_name_length = 0;
for (var i = 0; i < function_names_sorted_by_elapsed_time.length; i++) {
if (function_names_sorted_by_elapsed_time[i].length > max_name_length) {
max_name_length = function_names_sorted_by_elapsed_time[i].length;
}
}
var result = "'n" + get_whitespace(max_name_length) + " " + "#calls'telapsed't% of total'n";
for (var i = 0; i < function_names_sorted_by_elapsed_time.length; i++) {
if (total_time === 0) {
break;
}
var function_name = function_names_sorted_by_elapsed_time[i];
var percentage_elapsed = profile_by_function_name[function_name].elapsed_time * 100 / total_time;
if (percentage_elapsed < 0.3) {
break;
}
result += function_name + ":" + get_whitespace(max_name_length - 1 - function_name.length) + profile_by_function_name[function_name].calls + "'t" + profile_by_function_name[function_name].elapsed_time + "'t" + percentage_elapsed.toFixed(2) + "'n";
}
result += "=========='n";
result += "total time accounted for [ms]: " + total_time;
return result;
}
return {
profile: profile,
get_formatted_result: get_formatted_result
}
}
my_module_1.js
function mod_1(profiler_param) {
var profiler = profiler_param;
function my_private_func() {
return "hello world2";
}
if (typeof(profiler) === 'object' && profiler !== null) {
render_user_menu = profiler.profile(render_user_menu);
} //private functions need the instrumentation to be added manually or else they're not included in the profiling.
function my_public_func1() {
return "hello world";
}
function my_public_func2(input1, input2) {
return my_private_func() + input1 + input2;
}
//public functions get the instrumentations automatically as long as they're called from outside the module
var public_function_by_names = {
my_public_func1: my_public_func1
my_public_func2: my_public_func2
}
var result = {};
var public_function_names = Object.keys(public_function_by_names);
for (var i = 0; i < public_function_names.length; i++) {
var func = public_function_by_names[public_function_names[i]];
if (typeof(profiler) === 'object' && profiler !== null) {
result[public_function_names[i]] = profiler.profile(func);
}
else {
result[public_function_names[i]] = func;
}
}
return result;
}
<<p> PyV8一边/strong> with X4GEJSContext(extensions=['profile', 'my_module_1']) as ctx:
if self.enable_profiling == True:
ctx.eval("var profiler = mod_profiler();")
ctx.eval("var mod1 = mod_1(profiler);")
#note: you can pass profiler to as many modules as you want and they get instrumented together.
logging.info(ctx.eval("mod1.my_public_func_1() + mod1.my_public_func_2('a', 3);"))
logging.info(ctx.eval("profiler.get_formatted_result();"))
else:
ctx.eval("var mod1 = mod_1();") #it still works without the profiler
"hello worldhelloworld2a3"
#calls elapsed % of total
my_public_func1: 1 31 50.00
my_public_func2: 1 31 50.00
my_private_func: 1 31 50.00
==========
total time accounted for [ms]: 62
相关文章:
- 为什么不't Javascript对我的输入值进行了一些重新检查
- 创建一个类似链接的按钮,并通过Javascript函数打开一个新的弹出窗口
- 将函数的上下文应用于javascript变量
- 使用php或javascript从facebook相册URL中删除多余的部分
- 正在添加'X'按钮,在文本字段旁边使用javascript
- 如何在JavaScript中将字符串转换为函数引用
- 模糊事件的Javascript测试
- Javascript更改图标
- 如何将HTML id分配给元素,以及如何将JavaScript应用于元素
- 如何使用WCF服务和javascript表单post上传.doc文件
- javascript结合了数组和字典
- 这是什么 ==- javascript 运算符
- 从javascript创建一个列表
- 无法在通过jQuery的ajax加载的页面中执行javascript
- Javascript:selenium Web驱动程序isDisplayed()不工作
- 如何通过ajax刷新JSF填充的javascript变量
- 如何在Javascript中将JSon对象转换为数组
- PyV8在JavaScript/获取当前行号时抛出错误
- 如何使用PyV8和httplib来解释javascript
- 在PyV8中分析Javascript