最近发现lantern和shadowsocks client自生成pac都一定的性能问题,在url数目上升到一定程度的时候加载速度明显慢了很多.
于是我翻看了它们的实现
- lantern
- 把所有需要代理的domain组合成一个RegExp,然后在FindProxyForURL时对host做RegExp.exec的操作来判断是否需要代理
- shadowsocks
- 把domain做成一个{domain:1,…}的字典,然后在FindProxyForURL时对host做domains.hasOwnProperty判断是否在字典内,若不在,则去掉最前面的'.‘和之前的内容 继续做domains.hasOwnProperty判断
可以看出lantern的pac会严重影响网页的加载速度,shadowsocks的稍微好点,但在遇到不需要代理的网页时则会消耗更多无谓的判断
于是我自己实现一个pac优化FindProxyForURL匹配速度
我的思路是:
- 把所有需要代理的url以 ‘.’ 分割成节点
- 然后存入一个dict 格式如下
{
"com": {
"google": true,
"blogspot": {
"www": true
}
}
}
- 在FindProxyForURL中把host也split成list与这个dict match一下
var domains = [
"google.com",
"www.blogspot.com",
...
];
var domain_dict = {};
for(var i = 0; i < domains.length; i++){
if(domains[i].endsWith(".")){
domains[i] = domains[i].slice(0, -1)
}
var url_list = domains[i].split('.');
var domain_node = domain_dict;
for(var j = url_list.length; j > 0; j--){
var node_name = url_list[j-1];
if (!domain_node.hasOwnProperty(node_name)){
if (j === 1){
domain_node[node_name] = true;
break;
} else {
domain_node[node_name] = {};
}
} else if(domain_node[node_name] === true) {
break;
}
domain_node = domain_node[node_name];
}
}
var proxy = "SOCKS5 127.0.0.1:1080; SOCKS 127.0.0.1:1080; DIRECT";
var direct = 'DIRECT;';
function FindProxyForURL(url, host) {
if( host == "localhost" ||
host == "127.0.0.1") {
return direct;
}
var host_list = host.split('.')
var domain_node = domain_dict
for(var i = host_list.length; i > 0; i--){
var node_name = host_list[i-1]
if (domain_node.hasOwnProperty(node_name)){
if(domain_node[node_name] === true){
return proxy;
} else {
domain_node = domain_node[node_name]
}
}
else {
return direct;
}
}
return direct;
}
- 以下是我在nodejs下的性能测试结果 测试js下载地址
function renderChart(ctx, data) { var chart_obj = new Chart(ctx, { type: ‘bar’, data: { labels: [‘proxy_2_node’, ‘noproxy_2_node’, ‘proxy_3_node’, ‘noproxy_3_node’, ‘proxy_4_node’, ‘noproxy_4_node’], datasets: [ { type: ‘bar’, label: ‘shadowsocks’, data: data.shadowsocks, backgroundColor: “#1C9b47”, }, { type: ‘bar’, label: ‘lantern’, data: data.lantern, backgroundColor: “#00BCD4”, }, { type: ‘bar’, label: ‘owner’, data: data.owner, backgroundColor: “#FF4088”, } ] }, options: { title: { display: true, text: ctx.id } } }); return chart_obj; }
renderChart(document.getElementById(“bench-chart-10k”), benck10kData); renderChart(document.getElementById(“bench-chart-100k”), benck100kData); renderChart(document.getElementById(“bench-chart-1m”), benck1mData);