V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX  ›  lesismal  ›  全部回复第 21 页 / 共 56 页
回复总数  1112
1 ... 17  18  19  20  21  22  23  24  25  26 ... 56  
2023-04-27 18:06:48 +08:00
回复了 Nazz 创建的主题 Go 编程语言 修改 go websocket server 启动方式, 内存占用立省 40% !
这种 over TCP 的不能用于浏览器相关的领域,对于绝大多数 Websocket 用户是与 Web 浏览器的前段交互,所以绝大多数用户都不能用这种直接 over TCP 的 Websocket ,所以这样对比其实本身就没什么意义。

之前也有人在我这问基于 TCP 的,开放了一些字段,现在随便哪里的数据传递给 Websocket 解析器就可以了,基于 TCP/Unix/QUIC/KCP 或者随便什么协议都可以:
https://github.com/lesismal/nbio/issues/240#issuecomment-1304804444

如果是游戏、App 之类的用 TCP 通常也都是自家封装的协议、更简单更定制化。

内存占用的问题,标准库 HTTP 这块确实是,conn 上面挂载的读、写 buffer ,Hijack 的时候又新建了个写 buffer 传给用户,我看 OP 代码里是把新建的这个写 buffer=nil 释放了,写的时候是用 net.Buffers ,但这样不一定是最佳:
1. 标准卡库 Hijack 时创建的写 Buffer 虽然一瞬间又销毁了、但毕竟不是 c free ,不能立即释放。但正常业务 Upgrade 并不是超级频繁的动作,所以影响也不算大
2. net.Buffers 调用 TCPConn 这种,最后是 syscall.Writev ,以前做测试用 net.Buffers 性能比应用层自己拼接 buffer 然后 Write 要稍微差一点点。syscall.Writev 的内核 c 实现也是创建大 buffer 拷贝上去然后在 write ,但是用 syscall.Writev 可能消耗更多的内核资源和时间、而内核是整个系统共用资源时间比较宝贵且竞争,所以可能反倒不如让应用层来做这种划算,所以或许直接复用 Hijack 传过来的那个 Writer 也是相当于应用层的 Writev ,性能也还好。但是我很久没再做这个 syscall.Writev 与应用层自己 Writev 的对比了,不知道现在新版本如何。我自己的库一些实现是避免使用 net.Buffers 的,但是不管怎么用,性能差别应该不大

标准库 HTTP 的解析有些地方也是比较浪费的,重复拷贝、循环之类的,之前想去 pr 一波来着,但是标准库的实现太复杂了、功能也多、并发流也多,有的地方是一个连接可能多个协程处理的。pr 流程也很麻烦,要想 pr 成功太耗费精力了,所以放弃了
OP 可以试下去把标准库 Hijack()这块的代码优化下,Hijack 之后就把 conn 自己身上挂载的读写 buffer=nil ,说不定还有一些其他可以清理的
2023-04-26 22:13:52 +08:00
回复了 yagamil 创建的主题 程序员 保护手腕的最好办法还是尽量使用键盘操作
被动防守不如主动出击,所以,主要还是要多运动、不要长时间电脑前。
2023-04-26 22:10:28 +08:00
回复了 lesismal 创建的主题 Go 编程语言 最近犯闲,想再写点啥项目,有推荐的吗?
@honkki 没有呢,我比较懒,都是搜别人的博客看😂。。
2023-04-23 14:23:40 +08:00
回复了 xitek 创建的主题 程序员 2023 年了,希望果粉们不要掉在苹果的茧房里出不来了
> 其次价格,苹果的 2T 固态能卖 3000 元

OP 净胡诌!你哪只眼睛看到苹果 2T 固态 3000 了?

明明是 1T 3000 !
@0o0O0o0O0o 我们的一些新项目,没有历史包袱,就没有部署 nginx 了。但很多团队里,nginx 这些似乎成了一种技术惯性,不管有没有必要、都部署,整个社区需要很长时间去摆脱这个惯性
#17 go 性能、占用、开发效率能达到非常好的平衡。自定制起来也比 nginx lua/resty 要更有潜力。
@0o0O0o0O0o
其实用 go 最大的好处是:可以省去 nginx 了。:joy:
@lesismal #14

> 或者 OP 也可以另一种方案,还是先自己封装下 Listener ,tls Accept 得到的 tls Conn 用 RemoteAddr string 存 map 里

ConnContext 就可以了,更简单
@0o0O0o0O0o SaveConnInContext 这个挺好,学到了

@dzdh 要不我把 nbio 的 tls 的 clientHello 以及 clientHello 的 marshal 暴露出来,然后就方便拿到了,我本地改了试了下是可以的了,暂时没有更新到 repo:
https://gist.github.com/lesismal/316b711a7f39cc539cebaad6c8e5b0fd?permalink_comment_id=4545513#gistcomment-4545513



但是 nbio 只支持 http1.x ,http2.0/3.0QUIC 功能太多、我短期内没精力去做了。

或者 OP 也可以另一种方案,还是先自己封装下 Listener ,tls Accept 得到的 tls Conn 用 RemoteAddr string 存 map 里,handler 里取出 tls Conn ,并且反射或者自己 type 一个相同 fields 的结构体但是 ClientHello 大写导出的方式+unsafe 指针强转类型后把 clientHello 这个字段取出来用,但是这样怕 go 不同版本该结构体字段发生变化,要自己额外做一些对应 go 不同版本编译的兼容
#8

修改了下,用标准库的没必要自己封装 Listener ,直接 ConnState 处理就可以了,代码更新了

```golang
package main

import (
"context"
"fmt"
"net"
"net/http"
"os"
"os/signal"
"sync"
"time"

"github.com/lesismal/nbio/nbhttp"
)

var connections = sync.Map{}

func nbioOnEcho(w http.ResponseWriter, r *http.Request) {
res, ok := w.(*nbhttp.Response)
if ok {
conn := res.Parser.Processor.Conn()
yourData, ok := connections.Load(conn)
if ok {
fmt.Println("nbioServer onEcho:", yourData)
} else {
fmt.Println("nbioServer onEcho: not found connection")
}
}
w.Write([]byte(time.Now().Format("20060102 15:04:05")))
}

func nbioServer() {
mux := &http.ServeMux{}
mux.HandleFunc("/", nbioOnEcho)

engine := nbhttp.NewServer(nbhttp.Config{
Network: "tcp",
Addrs: []string{"localhost:8080"},
Handler: mux,
IOMod: nbhttp.IOModBlocking,
})
engine.OnOpen(func(conn net.Conn) {
fmt.Println("nbioServer onOpen:", conn.RemoteAddr())
yourData := "data: " + conn.RemoteAddr().String() // or other things
connections.Store(conn, yourData)
})
engine.OnClose(func(conn net.Conn, err error) {
connections.Delete(conn)
fmt.Println("nbioServer onClose:", conn.RemoteAddr(), err)
})

err := engine.Start()
if err != nil {
fmt.Printf("nbio.Start failed: %v\n", err)
return
}

interrupt := make(chan os.Signal, 1)
signal.Notify(interrupt, os.Interrupt)
<-interrupt

ctx, cancel := context.WithTimeout(context.Background(), time.Second*3)
defer cancel()
engine.Shutdown(ctx)
}

func netOnEcho(w http.ResponseWriter, r *http.Request) {
yourData, ok := connections.Load(r.RemoteAddr)
if ok {
fmt.Println("netServer onEcho:", yourData)
} else {
fmt.Println("netServer onEcho: not found connection " + r.RemoteAddr)
}
w.Write([]byte(time.Now().Format("20060102 15:04:05")))
}

func netServer() {
mux := &http.ServeMux{}
mux.HandleFunc("/", netOnEcho)

server := &http.Server{
Addr: "localhost:8080",
Handler: mux,
ConnState: func(conn net.Conn, state http.ConnState) {
switch state {

case http.StateNew:
fmt.Println("netServer onOpen:", conn.RemoteAddr())
remoteAddr := conn.RemoteAddr().String()
yourData := "data: " + remoteAddr // or other things
connections.Store(remoteAddr, yourData)
case http.StateActive:
case http.StateIdle:
case http.StateHijacked:
case http.StateClosed:
connections.Delete(conn)
fmt.Println("netServer onClose:", conn.RemoteAddr())
}
},
}
err := server.ListenAndServe()
fmt.Println("server exit:", err)
}

func main() {
netServer()
// nbioServer()
}
```
哦对了,基于标准库的代码部分,我忘记处理连接关闭时 Map.Delete 了,得看下 ConnState 之类的 Hook 能不能处理,如果不能处理,那基于标准库还不能这样简单搞、连接断开不清理就相当于泄露了导致 map 无限增长
如果只是要知道 ip 相关,使用 RemoteAddr 就可以了。

如果是需要其他信息(但楼主不讲明是需要什么的前提下我还真想不出 conn 除了 remote addr 还需要啥信息这么有必要去特殊处理),基于标准库包装一下 Listener 自己 map 映射存上也可以,或者基于 nbio OnOpen 。

基于标准库和 nbio 的区别是:
基于标准库的方式在 handler 里没法拿到 Conn ,因为只有 Hijack 一种方法拿到,但拿到后标准库 http server 就不继续处理该 Conn 了、Hijack 得到的 Conn 处理权转给了用户;
nbio 的 http handler 里除了 Hijack 的方式、也可以通过类型断言拿到 Conn 并且不涉及处理权的转移。

完整代码:
https://gist.github.com/lesismal/316b711a7f39cc539cebaad6c8e5b0fd

代码只示例了 4 层的 Conn ,如果需要 tls ,另外再加点处理、OP 可以自行探索
2023-04-18 19:23:47 +08:00
回复了 Xyg12133617 创建的主题 问与答 女友五一要去见前男友,我有点不想坚持了
2023-04-18 14:19:35 +08:00
回复了 yingzijiejie 创建的主题 Python 关于《流畅的 Python (第 2 版)》一书的用纸
我来支持下 OP ,我个人是不反感这种纸张的。
记忆里电力、机械工业等其他出版社的计算机类书籍,也不少这种薄纸。好几年没看纸质书、好些都送给朋友了,《深入理解 linux 内核》《 linux 设备驱动程序》《算法导论》。。。记不清楚是哪些书比较透了,印象最深的好像 O'Reilly 的不少中文版都是这样,很像 uni*/linux ,实而不华。
印象里纸张比较好的要属《 Unix 环境高级编程》,但确实厚重,如果可以选,我希望它薄一点,透不透我倒是不觉得影响阅读。
2023-04-18 14:04:25 +08:00
回复了 lesismal 创建的主题 Go 编程语言 nbio 近期的一些功能更新,来骗点 star
@blackvv666 感谢支持,欢迎交流,有建议、疑问、bug 之类的随时来 issue
@icyalala
对,大家基本观点是一致的。

string 在传统语言里的设计也是不太友好,支持二进制通用才更舒服,但也确实省了一点标识头。

capnproto 好久以前看到官方自己的数据非常牛,但这个我一直没在自己项目里用过,你们实际项目有用到不?好用不?
2023-04-17 17:35:07 +08:00
回复了 chai2010 创建的主题 程序员 凹语言中文语法设计
@pkwenda 不过文坛马上就是 AI 的天下了,所以损失了也无所谓:dog:
@Nazz 你没看懂我意思,我说的不是现有的 MessagePack 实现性能有优势

#51
但是单就性能而言,这里还是有个市场占有率的问题。因为 MessagePack 用户没那么多、像 #45 @hengyunabc 所说的,作者也没那么大精力和动力去做更大的性能优化。如果很多很多人用,MessagePack 的性能应该是可以做到比 simdjson 更强的,因为需要处理的字节数、逻辑肯定是比 json 少一点的,simd 指令能用来优化优化 json 也可以用于 MessagePack ,比如 simdjson 作者去实现 MessagePack 。
1 ... 17  18  19  20  21  22  23  24  25  26 ... 56  
关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2350 人在线   最高记录 6679   ·     Select Language
创意工作者们的社区
World is powered by solitude
VERSION: 3.9.8.5 · 43ms · UTC 05:04 · PVG 13:04 · LAX 22:04 · JFK 01:04
Developed with CodeLauncher
♥ Do have faith in what you're doing.