V2ray-core: 请改进利用多核CPU的计算能力

Created on 7 Jun 2020  ·  81Comments  ·  Source: v2ray/v2ray-core

现在很多路由器的CPU已经是多核的了,例如MediaTek MT7621A是双核4线程的CPU。
针对MT7621编译出的v2ray mipsel版本的执行文件,观看单条流的4K油管视频时,在路由器后台用top命令,可以看到CPU占用在28%-30%左右。
实际是将CPU的单核跑到100%左右了,而且造成计算力瓶颈,高码率4K视频观看卡顿。
改用PC虚拟机运行v2ray则因单核性能强大,全无卡顿。
如果单条流的加解密能使用多线程来进行,将MT7621A的空闲CPU算力也利用起来,而不是单线程加解密计算,应该能解决这个问题,让4K视频能顺畅观看。
能否考虑进行这部分的优化呢?

Stale

Most helpful comment

@nobk

简单思考了一下,优化方案不应该是将单条流的加解密分配给多核(这可能是一个连续的过程,强行拆分只会让速度更慢),而应该是用协程(多核)同时处理多条流,包括加解密,改起来也更简单。

性能会有很大的提升,但我现在并不熟悉 v2ray-core 的整体代码,请项目组大佬们优化一下。
@xiaokangwang @vcptr @kslr @nicholascw

All 81 comments

为什么要在路由器端跑呢?设备端不香吗?

Golang 的协程是默认支持多核的,或者说不应该始终只有一个核心在处理任务。

为什么要在路由器端跑呢?设备端不香吗?

在路由器上跑,路由器下面的所有设备自动具备访问油管的能力,无需对每个设备进行任何额外设置,哪怕一个不支持跑v2ray的8块钱的IOT设备也能自动翻墙了。

Golang 的协程是默认支持多核的,或者说不应该始终只有一个核心在处理任务。

实际情况是路由器的CPU占用是28%-30%,而不是全部利用起来的CPU占用80%-90%,很明显只用到了单核。

实际情况是路由器的CPU占用是28%-30%,而不是全部利用起来的CPU占用80%-90%,很明显只用到了单核。

那可能相关代码里并没有用协程,这的确是可以被优化的地方。

@nobk

简单思考了一下,优化方案不应该是将单条流的加解密分配给多核(这可能是一个连续的过程,强行拆分只会让速度更慢),而应该是用协程(多核)同时处理多条流,包括加解密,改起来也更简单。

性能会有很大的提升,但我现在并不熟悉 v2ray-core 的整体代码,请项目组大佬们优化一下。
@xiaokangwang @vcptr @kslr @nicholascw

Who was that guy again saying V2 can never max out your CPU just a few days ago? @Kylejustknows

其实不止这里可以优化

比如我知道一个不错的 ws 库:https://github.com/nhooyr/websocket

以及一个更高性能的 json 库:https://github.com/json-iterator/go

go.mod 里面的几乎所有库都有更新不止一个版本(当然,我指的是小版本)

然后在 ARM64 平台上的 AES 指令集有点迷,按理来说应该因为 golang 两年前的一次升级而自动支持了,但总有人说没有开、耗电

Who was that guy again saying V2 can never max out your CPU just a few days ago? @Kylejustknows

lmao yea that was me 👍 saying that. On one of my cheapest VPS the v2ray maxed out @ ~7% CPU when its at hundreds mbp speed.
But you know there is NO lower limit to how slow a device can be, right? Minesweeper can consume 100% cpu on some chips.

V2 maxing out CPU on server is difficult, yes, but on client not so much. The point is, what you consider purely theoretical (or at least insignificant) improvement in performance is very real and important (in a everyday use case) to others. I'm by no mean a performance fanatic (like @rprx), but we should never be cavalier about performance.

补充:我在树莓派2上也发现同样问题。v2ray跑满单核,4K高码率60fps单流依然卡顿,而树莓派2是4核CPU,用top看CPU使用率35%。

Can we first make sure if this issue is because of compilation settings, or if changes in the code is needed?

@JimHan75d8c5

我之前也下载代码看了,很多地方用了协程,所以这就是奇怪的地方,不应该只用到一个核心

@rprx
会不会是浏览器只建立了一个连接🤔

@JimHan75d8c5

WebSocket 的确只有一个连接,但 VMess 和这是解耦的。或许问题出在里面的多条流没有用协程(比如 VMess)。

@JimHan75d8c5

我觉得很可能是这样,毕竟其它底层协议是一次性连接,所以现在的代码可能只在底层协议那个层面用了协程。但 WS 是特殊情况:长连接和连接复用,那么仅在 WS 的层面用协程是不够的,里面包裹的协议也要用协程才行。

@rprx
话说您是不是没有理解我的意思啊😂,我的意思 浏览器(Google Chrome) 只建立了一个连接:

单条流的4K油管视频

可以试试用几个不同的浏览器同时打开4k视频,如果还是只用到单核那就是 v2ray的问题。

但 WS 是特殊情况

我印象中 WebSocket 没有什么特殊的啊。

或许问题出在里面的多条流没有用协程

如果这里出问题,将 mux关闭应该可以缓解这个问题。

@JimHan75d8c5

抱歉,没往那方面想。

我刚刚测试了一个 youtube 视频,加载网页组件是 HTTP/2 的多路复用(并发,用同一个 TCP 连接),加载视频是 HTTP/1.1 的 keep-alive(序列,不过也是同一个 TCP 连接)。加载视频是 HTTP/1.1,有点意外,因为 keep-alive 是阻塞的,同一时间只能有一个请求,看来问题就在这里了。

@JimHan75d8c5

WebSocket 的情况是,一个连接建立之后,v2ray 只会用这个连接,直到它关闭为止,所以如果一个 WebSocket 内所有的 VMess 加解密始终只用一个核心处理就很尴尬了(我猜应该不会是这样吧)。

话说您是不是没有理解我的意思啊,我的意思 浏览器(Google Chrome) 只建立了一个连接:

说到“只建立了一个链接”,我想提一下我之前开的一个 issue ,大意是把一个连接在v2ray的发送端使用多条连接发送,在接收端接收这些连接并重新组装成一条连接(类似多线程下载),以此来提升传输速度。如果把“多线程下载”的连接数设为和cpu的核心数一样,让每一个核负责一条连接的解密,这样是不是可以提升性能的同时提升传输速度(或者说绕开单条连接传输速度的上限)

如果加密是调用的C/C++库的话,是不是编译库的时候使用OpenMP做循环展开就能支持多核加解密了?

你们把多核想的过于简单了。线程之间同步什么的也是要消耗资源的。然后很多解密操作根本没办法分散到多核因为数据之间是有依赖的。最后V2不是从0开始写的,如果库自己不带多核处理那V2也没办法带上多核处理。如果开了多条连接进行下载,应该每个连接是可以独立处理的,这个之上的一个连接的数据分多个核就会比较困难了。

你们把多核想的过于简单了。线程之间同步什么的也是要消耗资源的。然后很多解密操作根本没办法分散到多核因为数据之间是有依赖的。最后V2不是从0开始写的,如果库自己不带多核处理那V2也没办法带上多核处理。如果开了多条连接进行下载,应该每个连接是可以独立处理的,这个之上的一个连接的数据分多个核就会比较困难了。

在现代加密算法设计上,算法的可并发计算绝对是重要考量项目,无论是美国的加密标准AES还是中国的国密标准,都是支持多CPU并发计算的的加密算法。

在现代加密算法设计上,算法的可并发计算绝对是重要考量项目,无论是美国的加密标准AES还是中国的国密标准,都是支持多CPU并发计算的的加密算法。

This may be true for decryption in the narrow, algorithm sense - but often not in the real world due to interdependence of different parts of the data within a given protocol. For an example, if part of the data being decrypted is some sort of authentication, you might want to wait for that part to finish (and successfully authenticate) before you proceed with decrypting anything else.

为什么要在路由器端跑呢?设备端不香吗?

说反了吧,路由器跑才香吧

这是BUG,不是单核心问题,你跑到25%那么大是不正常的
参考这个
https://github.com/v2ray/discussion/issues/558

你们把多核想的过于简单了。线程之间同步什么的也是要消耗资源的。然后很多解密操作根本没办法分散到多核因为数据之间是有依赖的。最后V2不是从0开始写的,如果库自己不带多核处理那V2也没办法带上多核处理。如果开了多条连接进行下载,应该每个连接是可以独立处理的,这个之上的一个连接的数据分多个核就会比较困难了。

在现代加密算法设计上,算法的可并发计算绝对是重要考量项目,无论是美国的加密标准AES还是中国的国密标准,都是支持多CPU并发计算的的加密算法。

加密算法可并行计算是没有问题的。问题是:v2ray服务器不停地收到客户端数据包流串,每个包尺寸都很小,解密周期很简单,“不值得”把一个小包强行分拆到几个CPU来并行计算;但,如果强行把单个小包随机送到各个CPU线程来解密,因为客户发的所有包都“无状态”,解密完后必须加等待周期来汇总给包排序,增加的标记、分配、排序的运算量和增加的延迟,最终结果可能还不如分配一个TCP连接单独给一个CPU线程负责(更别说强行分配每个包增加的代码复杂度)

多数其他的高性能服务器(比如说网页服务器),也都是这么设计的;当几百、几千用户连接的时候,各个TCP连接会随机分配到CPU各个线程,很少听说有把一个TCP握手也强行分配给几个CPU线程来计算的。

现在的代码看起来,如果v2ray服务器连入几十用户,它是会把各个CPU线程都利用起来。但如果是单用户+单独一条TCP接入,那可能只会用到一个CPU线程。

我在使用小米路由器3G上也碰到了这个问题,MT7621处理器运行v2ray(ShadowSocksR Plus+)只有单线程调用,表现为使用Chrome浏览单个youtube视频最大码率是15mps,CPU占用25%;但如果浏览两个youtube视频最大码率分别分12mbps和11mpbs,CPU占用50%,总码率为23mps。证明v2ray对单个浏览只调用一个线程,无法完全发挥MT7261的处理性能。对比斐讯N1盒子,浏览单个youtube视频最大码率能到360-400mps,CPU占用能跑满。所以这应该是v2ray在MT7621上线程调度的bug。

据说是因为MT7621没有硬件FPU,所以v2ray用的是FPU模拟器,但这个FPU模拟器不支持多线程调用,导致了MT7621无法支持多线程

多核开发没那么容易,你觉得路由器不给力就搞个软路由吧。

多核开发没那么容易,你觉得路由器不给力就搞个软路由吧。

我提这个需求又不是仅仅为自己,如果可以实现,上万的路由器用户都能从中受益。

大部分时间都可以用台式机里的OpenWrt虚拟机做旁路由来解决这个问题,我台式机从不关机的所以没必要单独购置一个软路由,不过偶尔的停电之后切换到直流UPS就只剩下光猫和MT7621路由还在工作了,PC上网也只能用笔记本,对4K需求不是很迫切。

你们试试看,路由器升级到4.25版本能不能解决你们的问题,应该是一个相同的BUG导致CPU异常过高,就算路由器arm芯片性能再差,也没道理会吃满一个核心。
升级后注意同时升级客户端,客户端也需要4.25版本
如果还存在CPU过高的问题,那只能做多核心支持优化了

@1265578519 版本已经是4.25.1了,MT7621的指令集是mipsle不是arm,路由器型号是斐讯的k2p,OpenWrt 19.07-SNAPSHOT, r11113-153392e209
/usr/bin/v2ray --version
V2Ray 4.25.1 (OpenWrt) R1 (go1.14.4 linux/mipsle)
A unified platform for anti-censorship.

https://www.mediatek.com/products/homeNetworking/mt7621 看了下果然是MIPS,那你这个4.25.1版本,还有CPU过高的情况吗,注意你的服务端和客户端,都要是4.25.1版本。
也就是你的VPS服务器上,和路由器上版本一定要一致为4.25.1版本

@1265578519 CPU是单核跑满,然后构成瓶颈,不是CPU异常过高。
附上虚拟机和MT7621的AES benchmark参考对照,
x64 单线程

openssl speed aes-256-cbc
Doing aes-256 cbc for 3s on 16 size blocks: 32031981 aes-256 cbc's in 3.00s
Doing aes-256 cbc for 3s on 64 size blocks: 8282604 aes-256 cbc's in 3.00s
Doing aes-256 cbc for 3s on 256 size blocks: 2132532 aes-256 cbc's in 3.00s
Doing aes-256 cbc for 3s on 1024 size blocks: 521421 aes-256 cbc's in 3.00s
Doing aes-256 cbc for 3s on 8192 size blocks: 62339 aes-256 cbc's in 3.00s
Doing aes-256 cbc for 3s on 16384 size blocks: 31107 aes-256 cbc's in 3.00s
OpenSSL 1.1.1g  21 Apr 2020
built on: Tue Jun  9 15:53:51 2020 UTC
options:bn(64,64) rc4(16x,int) des(int) aes(partial) blowfish(ptr)
compiler: x86_64-openwrt-linux-musl-gcc -fPIC -pthread -m64 -Wa,--noexecstack -Wall -O3 -pipe -fno-caller-saves -fno-plt -fhonour-copts -Wno-error=unused-but-set-variable -Wno-error=unused-result -Wformat -Werror=format-security -fstack-protector -D_FORTIFY_SOURCE=1 -Wl,-z,now -Wl,-z,relro -O3 -fpic -ffunction-sections -fdata-sections -znow -zrelro -DOPENSSL_USE_NODELETE -DL_ENDIAN -DOPENSSL_PIC -DOPENSSL_CPUID_OBJ -DOPENSSL_IA32_SSE2 -DOPENSSL_BN_ASM_MONT -DOPENSSL_BN_ASM_MONT5 -DOPENSSL_BN_ASM_GF2m -DSHA1_ASM -DSHA256_ASM -DSHA512_ASM -DKECCAK1600_ASM -DRC4_ASM -DMD5_ASM -DAESNI_ASM -DVPAES_ASM -DGHASH_ASM -DECP_NISTZ256_ASM -DX25519_ASM -DPOLY1305_ASM -DNDEBUG
The 'numbers' are in 1000s of bytes per second processed.
type             16 bytes     64 bytes    256 bytes   1024 bytes   8192 bytes  16384 bytes
aes-256 cbc     170837.23k   176695.55k   181976.06k   177978.37k   170227.03k   169885.70k

MT7621单线程

openssl speed aes-256-cbc                                                                      0:13:48
Doing aes-256 cbc for 3s on 16 size blocks: 1550964 aes-256 cbc's in 3.00s
Doing aes-256 cbc for 3s on 64 size blocks: 421554 aes-256 cbc's in 3.00s
Doing aes-256 cbc for 3s on 256 size blocks: 107814 aes-256 cbc's in 3.01s
Doing aes-256 cbc for 3s on 1024 size blocks: 27113 aes-256 cbc's in 3.01s
Doing aes-256 cbc for 3s on 8192 size blocks: 3385 aes-256 cbc's in 3.01s
Doing aes-256 cbc for 3s on 16384 size blocks: 1697 aes-256 cbc's in 3.01s
OpenSSL 1.1.1g  21 Apr 2020
built on: Sun Jun 21 19:34:09 2020 UTC
options:bn(64,32) rc4(char) des(long) aes(partial) blowfish(ptr)
compiler: mipsel-openwrt-linux-musl-gcc -fPIC -pthread -mabi=32 -Wa,--noexecstack -Wall -O3 -Os -pipe -mno-branch-likely -mips32r2 -mtune=24kc -fno-caller-saves -fno-plt -fhonour-copts -Wno-error=unused-but-set-variable -Wno-error=unused-result -msoft-float -Wformat -Werror=format-security -fstack-protector -D_FORTIFY_SOURCE=1 -Wl,-z,now -Wl,-z,relro -fpic -ffunction-sections -fdata-sections -znow -zrelro -DOPENSSL_USE_NODELETE -DOPENSSL_PIC -DOPENSSL_BN_ASM_MONT -DSHA1_ASM -DSHA256_ASM -DAES_ASM -DNDEBUG -DOPENSSL_PREFER_CHACHA_OVER_GCM -DOPENSSL_SMALL_FOOTPRINT
The 'numbers' are in 1000s of bytes per second processed.
type             16 bytes     64 bytes    256 bytes   1024 bytes   8192 bytes  16384 bytes
aes-256 cbc       8271.81k     8993.15k     9169.56k     9223.82k     9212.60k     9237.09k

x64 3线程(4核8线程处理器,Hyper-V 配置4内核)

openssl speed -multi 3 aes-256-cbc
Forked child 0
Forked child 1
Forked child 2
+DT:aes-256 cbc:3:16
+DT:aes-256 cbc:3:16
+DT:aes-256 cbc:3:16
+R:25090732:aes-256 cbc:3.000000
+R:25000861:aes-256 cbc:3.000000
+DT:aes-256 cbc:3:64
+DT:aes-256 cbc:3:64
+R:24517595:aes-256 cbc:3.000000
+DT:aes-256 cbc:3:64
+R:6964578:aes-256 cbc:3.000000
+R:6825332:aes-256 cbc:3.000000
+DT:aes-256 cbc:3:256
+DT:aes-256 cbc:3:256
+R:7122655:aes-256 cbc:3.000000
+DT:aes-256 cbc:3:256
+R:1671616:aes-256 cbc:3.000000
+R:1655596:aes-256 cbc:3.000000
+DT:aes-256 cbc:3:1024
+DT:aes-256 cbc:3:1024
+R:1756415:aes-256 cbc:3.000000
+DT:aes-256 cbc:3:1024
+R:431590:aes-256 cbc:3.000000
+R:443291:aes-256 cbc:3.000000
+R:464140:aes-256 cbc:3.000000
+DT:aes-256 cbc:3:8192
+DT:aes-256 cbc:3:8192
+DT:aes-256 cbc:3:8192
+R:54203:aes-256 cbc:3.000000
+R:52012:aes-256 cbc:3.000000
+R:54646:aes-256 cbc:3.000000
+DT:aes-256 cbc:3:16384
+DT:aes-256 cbc:3:16384
+DT:aes-256 cbc:3:16384
+R:27130:aes-256 cbc:3.000000
+R:27365:aes-256 cbc:3.000000
+R:27270:aes-256 cbc:3.000000
Got: +H:16:64:256:1024:8192:16384 from 0
Got: +F:18:aes-256 cbc:133817237.33:148577664.00:141277525.33:158426453.33:142027434.67:149449386.67 from 0
Got: +H:16:64:256:1024:8192:16384 from 1
Got: +F:18:aes-256 cbc:133337925.33:145607082.67:142644565.33:151309994.67:149220010.67:148930560.00 from 1
Got: +H:16:64:256:1024:8192:16384 from 2
Got: +F:18:aes-256 cbc:130760506.67:151949973.33:149880746.67:147316053.33:148010325.33:148165973.33 from 2
OpenSSL 1.1.1g  21 Apr 2020
built on: Tue Jun  9 15:53:51 2020 UTC
options:bn(64,64) rc4(16x,int) des(int) aes(partial) blowfish(ptr)
compiler: x86_64-openwrt-linux-musl-gcc -fPIC -pthread -m64 -Wa,--noexecstack -Wall -O3 -pipe -fno-caller-saves -fno-plt -fhonour-copts -Wno-error=unused-but-set-variable -Wno-error=unused-result -Wformat -Werror=format-security -fstack-protector -D_FORTIFY_SOURCE=1 -Wl,-z,now -Wl,-z,relro -O3 -fpic -ffunction-sections -fdata-sections -znow -zrelro -DOPENSSL_USE_NODELETE -DL_ENDIAN -DOPENSSL_PIC -DOPENSSL_CPUID_OBJ -DOPENSSL_IA32_SSE2 -DOPENSSL_BN_ASM_MONT -DOPENSSL_BN_ASM_MONT5 -DOPENSSL_BN_ASM_GF2m -DSHA1_ASM -DSHA256_ASM -DSHA512_ASM -DKECCAK1600_ASM -DRC4_ASM -DMD5_ASM -DAESNI_ASM -DVPAES_ASM -DGHASH_ASM -DECP_NISTZ256_ASM -DX25519_ASM -DPOLY1305_ASM -DNDEBUG
aes-256 cbc     397915.67k   446134.72k   433802.84k   457052.50k   439257.77k   446545.92k

MT7621 3线程 (双核4线程CPU)

openssl speed -multi 3 aes-256-cbc                                                             0:17:13
Forked child 0
Forked child 1
Forked child 2
+DT:aes-256 cbc:3:16
+DT:aes-256 cbc:3:16
+DT:aes-256 cbc:3:16
+R:1547953:aes-256 cbc:3.010000
+DT:aes-256 cbc:3:64
+R:786173:aes-256 cbc:3.010000
+R:786131:aes-256 cbc:3.010000
+DT:aes-256 cbc:3:64
+DT:aes-256 cbc:3:64
+R:421590:aes-256 cbc:3.010000
+R:213093:aes-256 cbc:3.010000
+R:213296:aes-256 cbc:3.010000
+DT:aes-256 cbc:3:256
+DT:aes-256 cbc:3:256
+DT:aes-256 cbc:3:256
+R:107653:aes-256 cbc:3.010000
+R:54368:aes-256 cbc:3.010000
+R:54344:aes-256 cbc:3.010000
+DT:aes-256 cbc:3:1024
+DT:aes-256 cbc:3:1024
+DT:aes-256 cbc:3:1024
+R:13654:aes-256 cbc:3.010000
+R:27102:aes-256 cbc:3.010000
+R:13657:aes-256 cbc:3.010000
+DT:aes-256 cbc:3:8192
+DT:aes-256 cbc:3:8192
+DT:aes-256 cbc:3:8192
+R:3393:aes-256 cbc:3.010000
+DT:aes-256 cbc:3:16384
+R:1708:aes-256 cbc:3.010000
+DT:aes-256 cbc:3:16384
+R:1711:aes-256 cbc:3.010000
+DT:aes-256 cbc:3:16384
+R:852:aes-256 cbc:3.010000
+R:1697:aes-256 cbc:3.010000
+R:855:aes-256 cbc:3.010000
Got: +H:16:64:256:1024:8192:16384 from 0
Got: +F:18:aes-256 cbc:4178992.69:4530881.06:4623989.37:4646102.33:4648483.72:4653926.91 from 0
Got: +H:16:64:256:1024:8192:16384 from 1
Got: +F:18:aes-256 cbc:8228321.59:8964039.87:9155869.77:9220082.39:9234370.76:9237092.36 from 1
Got: +H:16:64:256:1024:8192:16384 from 2
Got: +F:18:aes-256 cbc:4178769.44:4535197.34:4621948.17:4645081.73:4656648.50:4637597.34 from 2
OpenSSL 1.1.1g  21 Apr 2020
built on: Sun Jun 21 19:34:09 2020 UTC
options:bn(64,32) rc4(char) des(long) aes(partial) blowfish(ptr)
compiler: mipsel-openwrt-linux-musl-gcc -fPIC -pthread -mabi=32 -Wa,--noexecstack -Wall -O3 -Os -pipe -mno-branch-likely -mips32r2 -mtune=24kc -fno-caller-saves -fno-plt -fhonour-copts -Wno-error=unused-but-set-variable -Wno-error=unused-result -msoft-float -Wformat -Werror=format-security -fstack-protector -D_FORTIFY_SOURCE=1 -Wl,-z,now -Wl,-z,relro -fpic -ffunction-sections -fdata-sections -znow -zrelro -DOPENSSL_USE_NODELETE -DOPENSSL_PIC -DOPENSSL_BN_ASM_MONT -DSHA1_ASM -DSHA256_ASM -DAES_ASM -DNDEBUG -DOPENSSL_PREFER_CHACHA_OVER_GCM -DOPENSSL_SMALL_FOOTPRINT
aes-256 cbc      16586.08k    18030.12k    18401.81k    18511.27k    18539.50k    18528.62k

虚拟机其实还是很给力的,有台式机一直开机的不要买软路由,用Hyper-V在后台跑个OpenWrt做旁路由就行了,多个设备多花时间维护。
再补充一下AES-NI指令加速的benchmark
x64 AES-NI 单核

openssl speed -evp aes-256-cbc
Doing aes-256-cbc for 3s on 16 size blocks: 103794706 aes-256-cbc's in 3.00s
Doing aes-256-cbc for 3s on 64 size blocks: 26880769 aes-256-cbc's in 3.00s
Doing aes-256-cbc for 3s on 256 size blocks: 6809214 aes-256-cbc's in 2.99s
Doing aes-256-cbc for 3s on 1024 size blocks: 1732968 aes-256-cbc's in 3.00s
Doing aes-256-cbc for 3s on 8192 size blocks: 218311 aes-256-cbc's in 3.00s
Doing aes-256-cbc for 3s on 16384 size blocks: 107853 aes-256-cbc's in 3.00s
OpenSSL 1.1.1g  21 Apr 2020
built on: Tue Jun  9 15:53:51 2020 UTC
options:bn(64,64) rc4(16x,int) des(int) aes(partial) blowfish(ptr)
compiler: x86_64-openwrt-linux-musl-gcc -fPIC -pthread -m64 -Wa,--noexecstack -Wall -O3 -pipe -fno-caller-saves -fno-plt -fhonour-copts -Wno-error=unused-but-set-variable -Wno-error=unused-result -Wformat -Werror=format-security -fstack-protector -D_FORTIFY_SOURCE=1 -Wl,-z,now -Wl,-z,relro -O3 -fpic -ffunction-sections -fdata-sections -znow -zrelro -DOPENSSL_USE_NODELETE -DL_ENDIAN -DOPENSSL_PIC -DOPENSSL_CPUID_OBJ -DOPENSSL_IA32_SSE2 -DOPENSSL_BN_ASM_MONT -DOPENSSL_BN_ASM_MONT5 -DOPENSSL_BN_ASM_GF2m -DSHA1_ASM -DSHA256_ASM -DSHA512_ASM -DKECCAK1600_ASM -DRC4_ASM -DMD5_ASM -DAESNI_ASM -DVPAES_ASM -DGHASH_ASM -DECP_NISTZ256_ASM -DX25519_ASM -DPOLY1305_ASM -DNDEBUG
The 'numbers' are in 1000s of bytes per second processed.
type             16 bytes     64 bytes    256 bytes   1024 bytes   8192 bytes  16384 bytes
aes-256-cbc     553571.77k   573456.41k   582996.25k   591519.74k   596134.57k   589021.18k

x64 AES-NI 3线程 多核 (Hyper-V 4虚拟CPU)

openssl speed -evp aes-256-cbc -multi 3
Forked child 0
Forked child 1
Forked child 2
+DT:aes-256-cbc:3:16
+DT:aes-256-cbc:3:16
+DT:aes-256-cbc:3:16
+R:89974009:aes-256-cbc:3.000000
+R:90130430:aes-256-cbc:3.000000
+DT:aes-256-cbc:3:64
+DT:aes-256-cbc:3:64
+R:93114175:aes-256-cbc:3.000000
+DT:aes-256-cbc:3:64
+R:24795967:aes-256-cbc:3.000000
+R:24933460:aes-256-cbc:3.000000
+DT:aes-256-cbc:3:256
+DT:aes-256-cbc:3:256
+R:25084013:aes-256-cbc:3.000000
+DT:aes-256-cbc:3:256
+R:6630139:aes-256-cbc:3.000000
+R:6640814:aes-256-cbc:3.000000
+DT:aes-256-cbc:3:1024
+DT:aes-256-cbc:3:1024
+R:6646092:aes-256-cbc:3.000000
+DT:aes-256-cbc:3:1024
+R:1713185:aes-256-cbc:3.000000
+R:1715242:aes-256-cbc:3.000000
+DT:aes-256-cbc:3:8192
+DT:aes-256-cbc:3:8192
+R:1709998:aes-256-cbc:3.000000
+DT:aes-256-cbc:3:8192
+R:214797:aes-256-cbc:3.000000
+R:214871:aes-256-cbc:3.000000
+DT:aes-256-cbc:3:16384
+DT:aes-256-cbc:3:16384
+R:214959:aes-256-cbc:3.000000
+DT:aes-256-cbc:3:16384
+R:107080:aes-256-cbc:3.000000
+R:107183:aes-256-cbc:3.000000
Got: +H:16:64:256:1024:8192:16384 from 0
+R:107118:aes-256-cbc:3.000000
Got: +F:22:aes-256-cbc:479861381.33:528980629.33:565771861.33:584767146.67:586539008.00:584799573.33 from 0
Got: +H:16:64:256:1024:8192:16384 from 1
Got: +F:22:aes-256-cbc:480695626.67:531913813.33:566682794.67:585469269.33:586741077.33:585362090.67 from 1
Got: +H:16:64:256:1024:8192:16384 from 2
Got: +F:22:aes-256-cbc:496608933.33:535125610.67:567133184.00:583679317.33:586981376.00:585007104.00 from 2
OpenSSL 1.1.1g  21 Apr 2020
built on: Tue Jun  9 15:53:51 2020 UTC
options:bn(64,64) rc4(16x,int) des(int) aes(partial) blowfish(ptr)
compiler: x86_64-openwrt-linux-musl-gcc -fPIC -pthread -m64 -Wa,--noexecstack -Wall -O3 -pipe -fno-caller-saves -fno-plt -fhonour-copts -Wno-error=unused-but-set-variable -Wno-error=unused-result -Wformat -Werror=format-security -fstack-protector -D_FORTIFY_SOURCE=1 -Wl,-z,now -Wl,-z,relro -O3 -fpic -ffunction-sections -fdata-sections -znow -zrelro -DOPENSSL_USE_NODELETE -DL_ENDIAN -DOPENSSL_PIC -DOPENSSL_CPUID_OBJ -DOPENSSL_IA32_SSE2 -DOPENSSL_BN_ASM_MONT -DOPENSSL_BN_ASM_MONT5 -DOPENSSL_BN_ASM_GF2m -DSHA1_ASM -DSHA256_ASM -DSHA512_ASM -DKECCAK1600_ASM -DRC4_ASM -DMD5_ASM -DAESNI_ASM -DVPAES_ASM -DGHASH_ASM -DECP_NISTZ256_ASM -DX25519_ASM -DPOLY1305_ASM -DNDEBUG
evp            1457165.94k  1596020.05k  1699587.84k  1753915.73k  1760261.46k  1755168.77k

那来看你和估计我这个不是同一个毛病,https://github.com/v2ray/v2ray-core/issues/2301 我这个是UDP传输的BUG引起的,然后导致单核心爆掉CPU变高,4.25.0已经修复了那个BUG。单纯是你的CPU性能太烂了吧、、

那来看你和估计我这个不是同一个毛病,#2301 我这个是UDP传输的BUG引起的,然后导致单核心爆掉CPU变高,单纯是你的CPU性能太烂了吧、、

前面贴了benchmark。
MT7621的AES 64字节单线程成绩是8993.15k,三线程的成绩是18030.12k,可见硬件性能还是有挖掘空间的,单核到瓶颈了。

没有精力对旧路由设备优化,谁有兴趣可以做这件事

没有精力对旧路由设备优化,谁有兴趣可以做这件事

其实C/C++的程序没这个性能问题,比如ssr。
go还是优化不够,适合服务器不适合各种各样架构的客户端。

@nobk 要不然你换个加密方式试试,v2ray还支持chacha指令集,这个谷歌出的加密方式专门针对这些垃圾性能的硬件有优化作用,不要用默认的aes-128-gcm这个
你试试看速度会不会快很多,不过根据文档,如果选择auto的话,在不支持aes的设备上会自动转成chacha,不过还是建议你手动指定试试,万一自动转有BUG没成功呢!
openssl speed chacha20-poly1305

多核开发没那么容易,你觉得路由器不给力就搞个软路由吧。

我提这个需求又不是仅仅为自己,如果可以实现,上万的路由器用户都能从中受益。

大部分时间都可以用台式机里的OpenWrt虚拟机做旁路由来解决这个问题,我台式机从不关机的所以没必要单独购置一个软路由,不过偶尔的停电之后切换到直流UPS就只剩下光猫和MT7621路由还在工作了,PC上网也只能用笔记本,对4K需求不是很迫切。


1,现在全世界,在旧的mipsl设备上跑v2ray的人,估计不会过百。设备也在慢慢淘汰中。
2,如果家用,单连接十几M,多线几十M的速度,已经够干所有网上的事情了。如果商用,给财务提交预算5000元更新路由器不算贵。
3,做语言编译底层优化的大神们,他们每小时的工资(人力价值)都够买好多台高端路由器了,干这事不划算,纯粹是感兴趣弄弄。

@1265578519 两种加密算法刚才我都试了一下,iperf3的成绩基本上是一样的,也许v2ray内部选择了同一种吧。

- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bitrate
[  5]   0.00-10.01  sec  3.12 MBytes  2.62 Mbits/sec                  sender
[  5]   0.00-10.01  sec  2.45 MBytes  2.05 Mbits/sec                  receiver

对同一个vps进行iperf3用虚拟机旁路由的对照参考数据,这个应该是跑满v2ray代理带宽的成绩

[ ID] Interval           Transfer     Bitrate
[  5]   0.00-10.00  sec  49.6 MBytes  41.6 Mbits/sec                  sender
[  5]   0.00-10.00  sec  36.4 MBytes  30.5 Mbits/sec                  receiver

我发现我299元刚买的路由器也是7621da+mt7615d
image

@Kylejustknows MT7621在OpenWrt源码树下官方支持的设备数就有49个,仅仅k2p在中国就起码卖了几百万台,小米还有联想以及网件都有这个产品线。
所以我说有上万用户是相当保守的说法。

$ grep '#include "mt7621' target/linux/ramips/dts/*|wc -l
49
$ grep '#include "mt7621' target/linux/ramips/dts/*
target/linux/ramips/dts/AP-MT7621A-V60.dts:#include "mt7621.dtsi"
target/linux/ramips/dts/CreativeBox-v1.dts:#include "mt7621.dtsi"
target/linux/ramips/dts/DIR-860L-B1.dts:#include "mt7621.dtsi"
target/linux/ramips/dts/EW1200.dts:#include "mt7621.dtsi"
target/linux/ramips/dts/EX6150.dts:#include "mt7621.dtsi"
target/linux/ramips/dts/FIREWRT.dts:#include "mt7621.dtsi"
target/linux/ramips/dts/GB-PC1.dts:#include "mt7621.dtsi"
target/linux/ramips/dts/GB-PC2.dts:#include "mt7621.dtsi"
target/linux/ramips/dts/GHL-R-001.dts:#include "mt7621.dtsi"
target/linux/ramips/dts/HC5962.dts:#include "mt7621.dtsi"
target/linux/ramips/dts/K2P.dts:#include "mt7621.dtsi"
target/linux/ramips/dts/MIR3G.dts:#include "mt7621.dtsi"
target/linux/ramips/dts/MIR3P.dts:#include "mt7621.dtsi"
target/linux/ramips/dts/MT7621.dts:#include "mt7621.dtsi"
target/linux/ramips/dts/Newifi-D1.dts:#include "mt7621.dtsi"
target/linux/ramips/dts/Newifi-D2.dts:#include "mt7621.dtsi"
target/linux/ramips/dts/PBR-M1.dts:#include "mt7621.dtsi"
target/linux/ramips/dts/QUAD-E4G.dts:#include "mt7621.dtsi"
target/linux/ramips/dts/R6220.dtsi:#include "mt7621.dtsi"
target/linux/ramips/dts/R6350.dts:#include "mt7621.dtsi"
target/linux/ramips/dts/RB750Gr3.dts:#include "mt7621.dtsi"
target/linux/ramips/dts/RBM11G.dts:#include "mt7621.dtsi"
target/linux/ramips/dts/RBM33G.dts:#include "mt7621.dtsi"
target/linux/ramips/dts/RE350.dts:#include "mt7621.dtsi"
target/linux/ramips/dts/RE6500.dts:#include "mt7621.dtsi"
target/linux/ramips/dts/RT-AC57U.dts:#include "mt7621.dtsi"
target/linux/ramips/dts/SAP-G3200U3.dts:#include "mt7621.dtsi"
target/linux/ramips/dts/SK-WB8.dts:#include "mt7621.dtsi"
target/linux/ramips/dts/Telco-Electronics-X1.dts:#include "mt7621.dtsi"
target/linux/ramips/dts/Timecloud.dts:#include "mt7621.dtsi"
target/linux/ramips/dts/U7621-06.dtsi:#include "mt7621.dtsi"
target/linux/ramips/dts/UBNT-ER-e50.dtsi:#include "mt7621.dtsi"
target/linux/ramips/dts/VR500.dts:#include "mt7621.dtsi"
target/linux/ramips/dts/W2914NSV2.dtsi:#include "mt7621.dtsi"
target/linux/ramips/dts/WF-2881.dts:#include "mt7621.dtsi"
target/linux/ramips/dts/WITI.dtsi:#include "mt7621.dtsi"
target/linux/ramips/dts/WN-AX1167GR.dts:#include "mt7621.dtsi"
target/linux/ramips/dts/WN-GX300GR.dts:#include "mt7621.dtsi"
target/linux/ramips/dts/WR1200JS.dts:#include "mt7621.dtsi"
target/linux/ramips/dts/WR1201.dts:#include "mt7621.dtsi"
target/linux/ramips/dts/WRC-1167GHBK2-S.dts:#include "mt7621.dtsi"
target/linux/ramips/dts/WSR-1166.dts:#include "mt7621.dtsi"
target/linux/ramips/dts/WSR-600.dts:#include "mt7621.dtsi"
target/linux/ramips/dts/YOUKU-YK2.dts:#include "mt7621.dtsi"
target/linux/ramips/dts/ZBT-WE1326.dts:#include "mt7621.dtsi"
target/linux/ramips/dts/ZBT-WE3526.dts:#include "mt7621.dtsi"
target/linux/ramips/dts/ZBT-WG2626.dts:#include "mt7621.dtsi"
target/linux/ramips/dts/ZBT-WG3526.dtsi:#include "mt7621.dtsi"
target/linux/ramips/dts/elecom_wrc-gst.dtsi:#include "mt7621.dtsi"

OpenSSL bindings for Go 替代 Go crypt原装加密库也许能提高性能到openssl benchmark的水平,近9MB/s的单核解密速度看4K视频足够,多线程加解密功能也许也能借助OpenSSL开启。
https://github.com/Jarijaas/openssl
按原作者的2017年说法是性能翻倍
package openssl
import "github.com/spacemonkeygo/openssl"

Package openssl is a light wrapper around OpenSSL for Go.

It strives to provide a near-drop-in replacement for the Go standard library tls package, while allowing for:

Performance
OpenSSL is battle-tested and optimized C. While Go's built-in library shows great promise, it is still young and in some places, inefficient. This simple OpenSSL wrapper can often do at least 2x with the same cipher and protocol.

你贴一下chacha的性能看看?我想知道和aes差了有多远,我这路由没root权限测不了

你贴一下chacha的性能看看?我想知道和aes差了有多远,我这路由没root权限测不了

我的OpenWrt 19.07-SNAPSHOT的OpenSSL版本是1.1.1g,加密算法没有包含chacha没法测,以前2017年的openssl旧版本才有那个加密算法。

openssl help
Standard commands
asn1parse     ca            ciphers       cms           crl
crl2pkcs7     dgst          dhparam       dsa           dsaparam
ec            ecparam       enc           errstr        gendsa
genpkey       genrsa        help          list          nseq
ocsp          passwd        pkcs12        pkcs7         pkcs8
pkey          pkeyparam     pkeyutl       prime         rand
rehash        req           rsa           rsautl        s_client
s_server      s_time        sess_id       smime         speed
spkac         srp           storeutl      ts            verify
version       x509

Message Digest commands (see the `dgst' command for more details)
md4           md5           rmd160        sha1          sha224
sha256        sha3-224      sha3-256      sha3-384      sha3-512
sha384        sha512        sha512-224    sha512-256    shake128
shake256

Cipher commands (see the `enc' command for more details)
aes-128-cbc   aes-128-ecb   aes-192-cbc   aes-192-ecb   aes-256-cbc
aes-256-ecb   base64        bf            bf-cbc        bf-cfb
bf-ecb        bf-ofb        cast          cast-cbc      cast5-cbc
cast5-cfb     cast5-ecb     cast5-ofb     des           des-cbc
des-cfb       des-ecb       des-ede       des-ede-cbc   des-ede-cfb
des-ede-ofb   des-ede3      des-ede3-cbc  des-ede3-cfb  des-ede3-ofb
des-ofb       des3          desx          rc2           rc2-40-cbc
rc2-64-cbc    rc2-cbc       rc2-cfb       rc2-ecb       rc2-ofb
rc4           rc4-40

openssl version
OpenSSL 1.1.1g  21 Apr 2020

OpenSSL从 1.1.0(2016年8月)开始支持 ChaCha20-Poly1305 算法。我查了下资料1.1.0版本开始支持的
https://www.jianshu.com/p/fe8fc5157f96
openssl speed chacha20-poly1305
我用的版本。。也没这个功能测试
OpenSSL 1.0.1e-fips 11 Feb 2013

@Kylejustknows MT7621在OpenWrt源码树下官方支持的设备数就有49个,仅仅k2p在中国就起码卖了几百万台,小米还有联想以及网件都有这个产品线。
所以我说有上万用户是相当保守的说法。

$ grep '#include "mt7621' target/linux/ramips/dts/*|wc -l
49
$ grep '#include "mt7621' target/linux/ramips/dts/*
target/linux/ramips/dts/AP-MT7621A-V60.dts:#include "mt7621.dtsi"
target/linux/ramips/dts/CreativeBox-v1.dts:#include "mt7621.dtsi"
target/linux/ramips/dts/DIR-860L-B1.dts:#include "mt7621.dtsi"
target/linux/ramips/dts/EW1200.dts:#include "mt7621.dtsi"
target/linux/ramips/dts/EX6150.dts:#include "mt7621.dtsi"
target/linux/ramips/dts/FIREWRT.dts:#include "mt7621.dtsi"
target/linux/ramips/dts/GB-PC1.dts:#include "mt7621.dtsi"
target/linux/ramips/dts/GB-PC2.dts:#include "mt7621.dtsi"
target/linux/ramips/dts/GHL-R-001.dts:#include "mt7621.dtsi"
target/linux/ramips/dts/HC5962.dts:#include "mt7621.dtsi"
target/linux/ramips/dts/K2P.dts:#include "mt7621.dtsi"
target/linux/ramips/dts/MIR3G.dts:#include "mt7621.dtsi"
target/linux/ramips/dts/MIR3P.dts:#include "mt7621.dtsi"
target/linux/ramips/dts/MT7621.dts:#include "mt7621.dtsi"
target/linux/ramips/dts/Newifi-D1.dts:#include "mt7621.dtsi"
target/linux/ramips/dts/Newifi-D2.dts:#include "mt7621.dtsi"
target/linux/ramips/dts/PBR-M1.dts:#include "mt7621.dtsi"
target/linux/ramips/dts/QUAD-E4G.dts:#include "mt7621.dtsi"
target/linux/ramips/dts/R6220.dtsi:#include "mt7621.dtsi"
target/linux/ramips/dts/R6350.dts:#include "mt7621.dtsi"
target/linux/ramips/dts/RB750Gr3.dts:#include "mt7621.dtsi"
target/linux/ramips/dts/RBM11G.dts:#include "mt7621.dtsi"
target/linux/ramips/dts/RBM33G.dts:#include "mt7621.dtsi"
target/linux/ramips/dts/RE350.dts:#include "mt7621.dtsi"
target/linux/ramips/dts/RE6500.dts:#include "mt7621.dtsi"
target/linux/ramips/dts/RT-AC57U.dts:#include "mt7621.dtsi"
target/linux/ramips/dts/SAP-G3200U3.dts:#include "mt7621.dtsi"
target/linux/ramips/dts/SK-WB8.dts:#include "mt7621.dtsi"
target/linux/ramips/dts/Telco-Electronics-X1.dts:#include "mt7621.dtsi"
target/linux/ramips/dts/Timecloud.dts:#include "mt7621.dtsi"
target/linux/ramips/dts/U7621-06.dtsi:#include "mt7621.dtsi"
target/linux/ramips/dts/UBNT-ER-e50.dtsi:#include "mt7621.dtsi"
target/linux/ramips/dts/VR500.dts:#include "mt7621.dtsi"
target/linux/ramips/dts/W2914NSV2.dtsi:#include "mt7621.dtsi"
target/linux/ramips/dts/WF-2881.dts:#include "mt7621.dtsi"
target/linux/ramips/dts/WITI.dtsi:#include "mt7621.dtsi"
target/linux/ramips/dts/WN-AX1167GR.dts:#include "mt7621.dtsi"
target/linux/ramips/dts/WN-GX300GR.dts:#include "mt7621.dtsi"
target/linux/ramips/dts/WR1200JS.dts:#include "mt7621.dtsi"
target/linux/ramips/dts/WR1201.dts:#include "mt7621.dtsi"
target/linux/ramips/dts/WRC-1167GHBK2-S.dts:#include "mt7621.dtsi"
target/linux/ramips/dts/WSR-1166.dts:#include "mt7621.dtsi"
target/linux/ramips/dts/WSR-600.dts:#include "mt7621.dtsi"
target/linux/ramips/dts/YOUKU-YK2.dts:#include "mt7621.dtsi"
target/linux/ramips/dts/ZBT-WE1326.dts:#include "mt7621.dtsi"
target/linux/ramips/dts/ZBT-WE3526.dts:#include "mt7621.dtsi"
target/linux/ramips/dts/ZBT-WG2626.dts:#include "mt7621.dtsi"
target/linux/ramips/dts/ZBT-WG3526.dtsi:#include "mt7621.dtsi"
target/linux/ramips/dts/elecom_wrc-gst.dtsi:#include "mt7621.dtsi"

这些设备很多,我没怀疑,以前查过芯片出货量。但你知道全国v2ray的总用户才多少么?你觉得全国有多少人有闲有钱购置海外服务器呢?

这些用户数,乘以不想在电脑上使用的概率(99%用户直接跑PC版的),再乘以有linux嵌入操作技能,懂路由懂一些iptables的概率(5%用户都不到),再乘以有了以上技能后,却花费无数小时折腾一台廉价设备的概率(这就像是顶级游戏玩家打国际赛事,却带着一台破旧电脑一样不合理)

我个人估计,全国范围,手动把v2ray装进嵌入式设备的总人数也就几百(用SS的多一些因为有一些路由器固件自带SS),加上现在好一些的路由器都是arm,最终把v2ray装进旧式mipsl设备的用户,真的不多。

我真不知道怎么把这个算法跑起来,直接用这个命令行失败
openssl speed chacha20-poly1305
speed: Unknown algorithm chacha20-poly1305

其实只要给出可选项,让嵌入式设备用openssl这个C库的go lang wrapper,不在乎2x性能提升的服务器端还是用google go tls原生库,这个问题应该能够得到解决,从benchmark看OpenSSL的AES就足够快。

@Kylejustknows 很多人,包括我,都没有用VPS来上v2ray(尽管我买了VPS但我不到万不得已绝不在自己的VPS上跑v2ray用来翻墙),而是购买的每个月10块钱的v2ray服务流量帐户。
得到的就是一个v2ray UUID和一系列能用的v2ray服务器列表。由服务提供者来负责服务器的维护和更换IP等等繁琐操作。
再加上各种刷机路由器固件,其实使用门槛并不高,也不需要懂Linux iptables等等知识。
v2ray具体有多少用户,这个其实也不是重点,现实情况是目前v2ray的性能比起ssr和wireguard要差,这里面的优化空间还是很大的,而不是技术上做不到,受益的不仅仅是几百块的路由器,高端机器的性能也能大幅度增长。

不是做不到,而是,开发难度大,开发所需的时间和精力,远远不成正比,毕竟v2是一个开源项目,没有任何盈利,都靠大家来维护,就和楼上那位开发者说的谁有兴趣可以做这件事,然后提交PR到代码库,通过后就可以发布版本更新了,毕竟这一个过程,可能需要十多天甚至一个月的代码量去修改和测试,才能让他获取多线程。当然最大的修复目的应该还是,降低CPU使用,而不是多线程,因为和你说的,ssr它并不会占用大量的CPU

总之目前看起来优化方向已经明确了,开发难度也不大,也就是将go crypto库的API调用部分,用成熟的OpenSSL库API来替代,最终获得性能翻倍的结果,以及多线程支持。

真不好说,我那个打游戏的BUG,,导致V2占用CPU爆掉,那问题可是搞了好几年现在4.25版本才修复好,看了下代码,,,就3行不到,改了大概20个字符就修复了。。。

就如小樱所讲,主要也是兴趣导向。我们也没有这种路由设备或者说没有需求,加上还有很多工作需要处理,最大的可能还是无人认领。

你可以Fork这个仓库,然后尝试修改(或者维护一个路由性能优化版本),这是最快的办法,并且能够分享给其他所有使用的人。

这个社区也欢迎各位的加入,参与到各个方面的工作。

MT7621的HW crypto设备驱动也快做出来了,因为MT7621处理器具有硬件AES加解密的片内资源。
https://github.com/unclelittlecat/mtk-eip93
到时候可以通过OpenSSL evp系列api调用Linux standard crypto API,来实现同x86_64 AES-NI一样的硬件加速AES加解密,有希望跑满PROXY带宽。

@1265578519 chacha20的测试参数我搞清楚了,用MT7621测了一下64字节报文速度在28MB/s,可见用上openssl完全不会卡,现在的v2ray 2.5MB/s的性能问题不应该怪路由器CPU不行,毕竟其他程序就没这么慢,作为3W功耗的千兆路由器MT7621性价比还是很高的。

openssl speed -evp chacha20
Doing chacha20 for 3s on 16 size blocks: 3162623 chacha20's in 3.00s
Doing chacha20 for 3s on 64 size blocks: 1329310 chacha20's in 3.01s
Doing chacha20 for 3s on 256 size blocks: 380531 chacha20's in 3.01s
Doing chacha20 for 3s on 1024 size blocks: 98785 chacha20's in 3.01s
Doing chacha20 for 3s on 8192 size blocks: 12479 chacha20's in 3.01s
Doing chacha20 for 3s on 16384 size blocks: 6246 chacha20's in 3.00s
OpenSSL 1.1.1g  21 Apr 2020
built on: Sun Jun 21 19:34:09 2020 UTC
options:bn(64,32) rc4(char) des(long) aes(partial) blowfish(ptr)
compiler: mipsel-openwrt-linux-musl-gcc -fPIC -pthread -mabi=32 -Wa,--noexecstack -Wall -O3 -pipe -mno-branch-likely -mips32r2 -mtune=24kc -fno-caller-saves -fno-plt -fhonour-copts -Wno-error=unused-but-set-variable -Wno-error=unused-result -msoft-float -Wformat -Werror=format-security -fstack-protector -D_FORTIFY_SOURCE=1 -Wl,-z,now -Wl,-z,relro -O3 -fpic -ffunction-sections -fdata-sections -znow -zrelro -DOPENSSL_USE_NODELETE -DOPENSSL_PIC -DOPENSSL_BN_ASM_MONT -DSHA1_ASM -DSHA256_ASM -DAES_ASM -DNDEBUG -DOPENSSL_PREFER_CHACHA_OVER_GCM
The 'numbers' are in 1000s of bytes per second processed.
type             16 bytes     64 bytes    256 bytes   1024 bytes   8192 bytes  16384 bytes
chacha20         16867.32k    28264.40k    32364.10k    33606.59k    33962.78k    34111.49k

@kslr 如果没熟手接手的话,我也可以试试,不过我做就得等我先读完https://tour.golang.org/以及crypto/cipher crypto/aes 以及openssl库的用法之后了,粗略看了一下,golang的aes库和其他加密库的调用方式完全不同,要按它的方式实现一个接口,才能尽量少的改动v2ray原有的加解密部分。

你可以先评估一下工作量,如果工作比较多,我更建议的是维护一个优化版本。

如果实现接口,其实v2ray的部分应该不用动import之外的代码,sed搜索替换字符串"crypto/aes"替换为v2ray.com/core/common/crypto/openssl/aes"再编译就可以了。

@nobk

如果 v2ray 不考虑以后开启 CGO 编译,用到外部的东西,我的建议是维护一个优化版本

潜在的麻烦请参考 https://github.com/v2ray/discussion/issues/754#issuecomment-650716506

(歪个楼)其实你可以试一下 VLess,省一些硬件:https://github.com/rprx/v2ray-vless

@rprx 我的服务提供商最近从SSR全面换到V2RAY我才跟过来的,因为他那些服务器还比较稳定整个六月份都没掉链子所以我暂时也不打算换一家。所以他没提供VLess服务之前,我也是用不到的。
在没动v2ray原有代码的情况下,额外维护一个版本没有必要,因为对x86_64 ARM64这些用户而言什么都没改变。而编译嵌入式设备的版本才需要将 import "crypto/aes"这行代码替换成 import "v2ray.com/core/common/crypto/openssl/aes",其余代码也不会有改动,Openwrt工具链的包管理器生成v2ray.ipk安装包时完成这个改动再编译就行了。

看下来我有两个问题:

  1. 观看“单个youtube流”时,路由器到服务器的连接数应该不止一个,因为youtube会从多个内容服务器下载内容。我不完全确定这一点,你可以在打开视频后在路由器上用netstat或ss看看,是否跟我说的一样。

  2. openssl speed -evp aes-128-gcmopenssl speed -evp chacha20-poly1305测一下,结果怎么样?应该会比aes-128-cbc和单独的chacha20更慢一些。

是的aes-128-gcm要慢一些,但也在可以播放4K视频的范围内。

zsh#root@K2P-OpenWrt ~                                                                      22:05:30
openssl speed -evp aes-128-gcm
Doing aes-128-gcm for 3s on 16 size blocks: 1122811 aes-128-gcm's in 3.00s
Doing aes-128-gcm for 3s on 64 size blocks: 319814 aes-128-gcm's in 3.01s
Doing aes-128-gcm for 3s on 256 size blocks: 82985 aes-128-gcm's in 3.01s
Doing aes-128-gcm for 3s on 1024 size blocks: 20945 aes-128-gcm's in 3.01s
Doing aes-128-gcm for 3s on 8192 size blocks: 2628 aes-128-gcm's in 3.01s
Doing aes-128-gcm for 3s on 16384 size blocks: 1314 aes-128-gcm's in 3.01s
OpenSSL 1.1.1g  21 Apr 2020
built on: Sun Jun 21 19:34:09 2020 UTC
options:bn(64,32) rc4(char) des(long) aes(partial) blowfish(ptr)
compiler: mipsel-openwrt-linux-musl-gcc -fPIC -pthread -mabi=32 -Wa,--noexecstack -Wall -O3 -pipe -mno-branch-likely -mips32r2 -mtune=24kc -fno-caller-saves -fno-plt -fhonour-copts -Wno-error=unused-but-set-variable -Wno-error=unused-result -msoft-float -Wformat -Werror=format-security -fstack-protector -D_FORTIFY_SOURCE=1 -Wl,-z,now -Wl,-z,relro -O3 -fpic -ffunction-sections -fdata-sections -znow -zrelro -DOPENSSL_USE_NODELETE -DOPENSSL_PIC -DOPENSSL_BN_ASM_MONT -DSHA1_ASM -DSHA256_ASM -DAES_ASM -DNDEBUG -DOPENSSL_PREFER_CHACHA_OVER_GCM
The 'numbers' are in 1000s of bytes per second processed.
type             16 bytes     64 bytes    256 bytes   1024 bytes   8192 bytes  16384 bytes
aes-128-gcm       5988.33k     6800.03k     7057.86k     7125.48k     7152.35k     7152.35k
zsh#root@K2P-OpenWrt ~                                                                      23:05:23
openssl speed -evp chacha20-poly1305
Doing chacha20-poly1305 for 3s on 16 size blocks: 2206186 chacha20-poly1305's in 3.00s
Doing chacha20-poly1305 for 3s on 64 size blocks: 918455 chacha20-poly1305's in 3.00s
Doing chacha20-poly1305 for 3s on 256 size blocks: 266378 chacha20-poly1305's in 3.00s
Doing chacha20-poly1305 for 3s on 1024 size blocks: 69392 chacha20-poly1305's in 3.00s
Doing chacha20-poly1305 for 3s on 8192 size blocks: 8775 chacha20-poly1305's in 3.00s
Doing chacha20-poly1305 for 3s on 16384 size blocks: 4393 chacha20-poly1305's in 3.00s
OpenSSL 1.1.1g  21 Apr 2020
built on: Sun Jun 21 19:34:09 2020 UTC
options:bn(64,32) rc4(char) des(long) aes(partial) blowfish(ptr)
compiler: mipsel-openwrt-linux-musl-gcc -fPIC -pthread -mabi=32 -Wa,--noexecstack -Wall -O3 -pipe -mno-branch-likely -mips32r2 -mtune=24kc -fno-caller-saves -fno-plt -fhonour-copts -Wno-error=unused-but-set-variable -Wno-error=unused-result -msoft-float -Wformat -Werror=format-security -fstack-protector -D_FORTIFY_SOURCE=1 -Wl,-z,now -Wl,-z,relro -O3 -fpic -ffunction-sections -fdata-sections -znow -zrelro -DOPENSSL_USE_NODELETE -DOPENSSL_PIC -DOPENSSL_BN_ASM_MONT -DSHA1_ASM -DSHA256_ASM -DAES_ASM -DNDEBUG -DOPENSSL_PREFER_CHACHA_OVER_GCM
The 'numbers' are in 1000s of bytes per second processed.
type             16 bytes     64 bytes    256 bytes   1024 bytes   8192 bytes  16384 bytes
chacha20-poly1305    11766.33k    19593.71k    22730.92k    23685.80k    23961.60k    23991.64k
zsh#root@K2P-OpenWrt ~                                                                      23:05:44

@darhwa

我之前测试过,youtube 加载单个视频时居然同时只有一条流,还是 http/1.1,你也可以看一下

@nobk

如果我没理解错的话,替换到的 aes 库是对 c 写的 openssl 的封装,此时编译需要开启 CGO,并且使用对应架构和系统的 c 编译器。。。所以这个特定平台的优化版本,是否属于“额外维护”其实没有什么区别。

因为使用OpenWrt工具链构建依赖openssl的v2ray版本啊,这一套工具链很成熟的,而且有专门团队维护。

@nobk

有针对就很简单,我的意思是无论怎样都算“额外维护”,与是否加入官方构建版本无关。

@rprx 现在讨论这些还太早,我读Go指南也才到flowcontrol/1章节。就算搞出来openssl库的接口了,也要看iperf3 benchmark最终的结果数据,才知道这种路线有没有价值。只不过目前看来这个是付出代价最小的性能提升方式而已。

要是Go和C的混合方式效果还是不好,我重新用C写一份VMESS的redir极简实现,无非也就一两千行代码而已,一两百KB的执行程序,不比编译个16.4MB的v2ray放在路由器上舒心多了,而且速度还快。

@nobk

加油,go 把密集计算交给 c 肯定会提升些性能的

不过这个。。。用 c 重现 vmess,一两千行后面可能得加个零(但有兴趣的话值得一试)。vless 能短时间内实现的原因,一是大量复用了 v2ray 已有的轮子,二是主要是对 vmess 的精简,即使这样也是新增了两千行左右的代码,这还是用 go 语言。。。

@rprx tls+wss的类似v2ray的精简实现,两年多以前就有人用C写出来了,客户端1118行,服务器端753行,C库用了libevent和openssl。base64其实openssl里面就带作者可能不知道,还弄了个不知名base64的实现。
当然我如果用C重写VMESS的redir实现,可能会用libuv+openssl。
https://github.com/TanNang/tls-proxy

@nobk

我的理解是要用 c 写同等功能的 vmess,这样才能保证兼容性,其中至少要有 vmess 编码解码、多路复用等必要功能的代码,然后还有一些非核心代码比如解析配置文件等。以及,非通用的轮子应该算入代码行数。总之,最终肯定也与完成度有关,如果是将现在用到的功能转译成 c,上万行是很有可能的。

@rprx 给路由器用的极简实现,当然只考虑能把包转发到v2ray的server端,就完事了,其实连内置dns和geoip都不需要有,ipset+iptables+一些脚本就可以搞定。分开国内国外域名解析的DNS也有一堆现成的。

This issue is stale because it has been open 120 days with no activity. Remove stale label or comment or this will be closed in 5 days

怎么就从占用率认为是单核了,这个不好确定

在 2020年6月7日星期日,nobk notifications@github.com 写道:

Golang 的协程是默认支持多核的,或者说不应该始终只有一个核心在处理任务。

实际情况是路由器的CPU占用是28%-30%,而不是全部利用起来的CPU占用80%-90%,很明显只用到了单核。


You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
https://github.com/v2ray/v2ray-core/issues/2548#issuecomment-640143287,
or unsubscribe
https://github.com/notifications/unsubscribe-auth/ADB5GWL5HG7KFE7Y7VYU6PTRVLWJNANCNFSM4NWSNJEQ
.

难道不是因为k2p的CPU太垃圾了吗?我10510U咋不卡?

难道不是因为k2p的CPU太垃圾了吗?我10510U咋不卡?

改用PC虚拟机运行v2ray则因单核性能强大,全无卡顿。

你在当复读机?

难道不是因为k2p的CPU太垃圾了吗?我10510U咋不卡?

改用PC虚拟机运行v2ray则因单核性能强大,全无卡顿。

你在当复读机?

宁不懂,nobk就是个用垃圾cpu的zz
https://github.com/coolsnowwolf/lede/pull/6241

难道不是因为k2p的CPU太垃圾了吗?我10510U咋不卡?

改用PC虚拟机运行v2ray则因单核性能强大,全无卡顿。
你在当复读机?

宁不懂,nobk就是个用垃圾cpu的zz
https://github.com/coolsnowwolf/lede/pull/6241

我知道这人是傻逼。不过也要就事论事,这贴本身还是有点价值的。

Was this page helpful?
0 / 5 - 0 ratings