V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX  ›  ipwx  ›  全部回复第 39 页 / 共 201 页
回复总数  4006
1 ... 35  36  37  38  39  40  41  42  43  44 ... 201  
2021-12-17 14:43:00 +08:00
回复了 kingofzihua 创建的主题 Linux 问一个协程方面的问题
@statumer C# 那种可以通过一个线程池(专门排队做阻塞任务) + 非阻塞的 IO 。不过确实,非阻塞 IO 的库开发需要时间。所以这就造成了 Go 语言在网络微服务等领域特别被人追捧,因为在这里面编译期自动插入 hook 确实省事得多,一下子就可以适配所有阻塞的库。

这其实就是工程性的妥协了。C++ 和 C# 没有编译器的 hack ,导致大家不得不开发真正的非阻塞库。但是反过来,这样就倒逼 C++ C# 这种语言用户开发出真正高性能的非阻塞库了。然而毕竟真正需要高性能非阻塞的库不多,Network IO, MySQL / PostgreSQL / MongoDB ,加上一定的 File IO 和基础框架,就解决了。

其他的并不需要处理这种事情。应用逻辑方面需要解决“锁”的阻塞问题,其实“不阻塞”才是更正确的方案。逻辑复杂的应用从多线程并发阻塞模型换成 Actor model ,你会发现写起来就是第二次工业革命和第三次工业革命的区别。

Go 语言编译器允许大家偷懒,大家自然没有动力去精益求精,“够用就行”。反而抑制了更精巧的程序 —— 当然这也是做 “工作” 和做 “艺术品” 态度的差别吧 hhh
2021-12-17 14:34:19 +08:00
回复了 kingofzihua 创建的主题 Linux 问一个协程方面的问题
@lxdlam 在我看来 f(n) 就应该也是 async 的,虽然对于这方面 js 我不太熟。

我的技术背景是 C++、Python 比较熟,曾经用 Scala 写过 Future / Promise 的程序不过已经很久没有用了。C++ 自己写过 Actor framework ,Python 曾经用过 tornado 和 gevent ,现在挺喜欢用 async / await 。

因为我的这些背景,所以我觉得程序员非常准确明白所有这些并发方法(线程池、event loop 、callback 、future promise 、async await )是基本功,而且不同任务可能偏重于不同的技术。当一个任务需要特别准确把握延迟的时候,随意上下文切换是不可接受的,那么就得手撸 event loop ,顶多在 event loop 上自己封装一下比如 actor model 或者 future / promise 呗。

所以我比较 anti go 语言这种类似于线程的协程吧,总感觉它管得太多了。
2021-12-17 01:33:36 +08:00
回复了 kingofzihua 创建的主题 Linux 问一个协程方面的问题
@statumer 我原先也完全是你这个理解思路,直到我在这一楼层里面看到了有人说 Go 语言的协程是可以切换上下文的——

https://www.jianshu.com/p/fb1ccbd0d0ff

我 tm ,瞬间五雷轰顶,并且明白了为啥 Go 吹那么多的原因。引用我 125L 的观点:

> Go 这种内置协程时间片切分的机制,在我看来,是一种工程实践上的妥协。
> 无论多轻量级的切换,一定是耗时的。减少不必要的切换可以使得总体耗时降到最低。
> 如果能控制 IO 非阻塞让渡控制权,而且每对 IO 之间的操作都比较轻量(微妙级),就完全可以只在 IO 上切换。这样总体效能是最高的。
> 但是工程上不能保证所有类库都这样,也不能保证所有程序员都写的对,所以 Go 的这种协程才有用吧 hhh

所以本质上这是一个,因为不会用 event loop 的程序员太多了,Go 语言大爷们就说:算了,你们这群傻逼,干脆我语言创造一个比系统线程更轻的协程给你们用算了。

----

所以总结一下,Go 语言的协程和其他语言的协程是不同的。C++、Python 这种经典语言的协程 tm 根本不可能内置 Go 虚拟机的时间线分片。JVM 和 C# 也从未想过要这么干。微软的 Fiber 还差羽而归。因为它们发现,替程序员越俎代庖搞这种抽象,吃力不讨好。反正追求性能的有 event loop 或者基于 event loop 的单线程协程,为啥还要搞个不上不下的多线程(有上下文切换)的协程呢?

毕竟任何上下文切换,哪怕你说 Go 协程切换只要三个寄存器,tm 还是实打实有这个耗时的啊。
----

但是在一个没有泛型被认为是大道至简的语言里面,这种独一份的奇葩设计也没啥可奇怪的。
2021-12-16 16:47:59 +08:00
回复了 zzzain46 创建的主题 问与答 同样一个 csv,为什么导入 db2 比导入 MySQL 快很多
(强烈怀疑它没有优化好
(要用 transaction batch insert
2021-12-16 16:43:41 +08:00
回复了 zzzain46 创建的主题 问与答 同样一个 csv,为什么导入 db2 比导入 MySQL 快很多
你用了啥工具导入。。。有区别的
2021-12-16 15:10:58 +08:00
回复了 dwlovelife 创建的主题 程序员 最近学 Python ,关于作用域的问题有点不明白
如果你在 foo 里面 a = 200 ,然后在 foo() 之后 print(a),你会发现 foo 里面的 a 和外面的 a 就不是一个 a 了。

我觉得这是 Python 让人不满意的地方。因为没有声明,赋值即声明,所以会搞不清楚作用域。

事实上如果你运行如下代码:

def main():
....print(a)
....a = 1

a = 2
main()

你会得到一个异常:

UnboundLocalError: local variable 'a' referenced before assignment

原因是 a = 1 这句话在 main 函数里面定义了一个变量 a ,因此你在 print(a) 这一行就引用不到全局的 a 了。
2021-12-16 11:10:48 +08:00
回复了 rophie123 创建的主题 Node.js nodejs 前后端一把梭的优势在哪?
@ob 你可以用 bootstrap-vue ( doge )

https://bootstrap-vue.org/
2021-12-16 00:40:13 +08:00
回复了 rophie123 创建的主题 Node.js nodejs 前后端一把梭的优势在哪?
1. vue.js + webpack 配合其他语言不是难事,比如我经常配合 python 。
2. vue.js 就是比 html bootstrap jquery 好写啊。。。
2021-12-15 17:54:04 +08:00
回复了 liuidetmks 创建的主题 程序员 v 站有 C 程序员使用 protothreads 协程吗?
@liuidetmks 哦原来 C 语言的模拟 coroutine 其实是自动机 hhh

这样来看,这种其实更类似于 on_message(message_type) {
switch (message_type) {
case xx: ...
case xx: ...
}
}

只不过用了语法糖自动展开了
2021-12-15 13:44:23 +08:00
回复了 Livid 创建的主题 Python Snakeware
@kidonng Python 的标记收集 GC 很少运行啊,大部分 gc 都分摊在每一行上面了
2021-12-14 13:39:18 +08:00
回复了 kingofzihua 创建的主题 Linux 问一个协程方面的问题
@joshu 说实话,Go 这种内置协程时间片切分的机制,在我看来,是一种工程实践上的妥协。

无论多轻量级的切换,一定是耗时的。减少不必要的切换可以使得总体耗时降到最低。你不会想要一个 for (1000000) 的计算任务被打断一千次吧,对吧对吧。

如果你能控制 IO 非阻塞让渡控制权,而且每对 IO 之间的操作都比较轻量(微妙级),你完全可以只在 IO 上切换。这样总体效能是最高的。

但是工程上不能保证所有类库都这样,也不能保证所有程序员都写的对,所以 Go 的这种协程才有用吧 hhh
2021-12-14 12:08:56 +08:00
回复了 kingofzihua 创建的主题 Linux 问一个协程方面的问题
@lxdlam 哦对。不过 Erlang 我也不太熟 23333

Akka 受限于 Scala 这个语言太。。。。学院派,不太关心工程实践,语法糖 >> 性能和可维护性,导致它不太广泛使用。
2021-12-14 12:08:08 +08:00
回复了 kingofzihua 创建的主题 Linux 问一个协程方面的问题
@kingofzihua 另外 actor 模型可以很容易插入中间件。在一个 IO actor 和一个业务 actor 之间你可以完全不用更改两边,插入流控 actor ,或者插入错误重发 actor 。一个业务 actor 也可以搭配各种不同的协议 actor ,比如把一个 HTTP 协议 actor 丢在 SSL 信道 actor 或者 TCP 信道 actor 上都不用更改 HTTP 协议 actor 的任何一点代码。
2021-12-14 12:05:31 +08:00
回复了 kingofzihua 创建的主题 Linux 问一个协程方面的问题
P.S. @kingofzihua 补充一句,actor model 里面每个 actor 其实是个状态机。差不多就是


def __init__(self):
....self.state = 0

def on_message(self, msg):
....if state == 0:
........do something with msg
........self.state = 1
....elif state == 1:
........do something with msg
........self.state = 2

核心就是这个 on_message 处理函数。你是期待框架把新的数据推送给你(或者别的专门读数据的 actor ),而不是在每个 actor 里面都调用 read 。

这个的好处在于,你可以把 IO actor 和业务 actor 切分,业务不用管太多 IO 细节,实现了解耦。单元测试的时候你可以直接对业务 actor 伪造输入进行测试。特别爽。

而且状态机可以回退,这个就可以实现很复杂的东西。
2021-12-14 11:48:49 +08:00
回复了 kingofzihua 创建的主题 Linux 问一个协程方面的问题
…… 不过实现一个基本的 actor framework 也不是那么困难的。。。

再比如我自己在自己的项目里面用 C++ 实现了一个。
2021-12-14 11:48:01 +08:00
回复了 kingofzihua 创建的主题 Linux 问一个协程方面的问题
@kingofzihua 对既然提到了 actor model ,楼主如果有兴趣可以去看看 actor model ,这个东西的思考方式会让你改变很多对并发的看法。比较成熟的 actor model 的实现大概只有 scala akka 。

actor model 的核心在于,每个 actor 只有一个工作线程。actor 尽量避免阻塞。即使你在 10 个线程的线程池上运行 10000 个 actor ,每个 actor 要同时处理其他 9999 个 actor 发来的消息,也保证只有一个线程在运行一个特定的 actor 。这个是 actor model 最重要的特性。
2021-12-14 11:45:10 +08:00
回复了 kingofzihua 创建的主题 Linux 问一个协程方面的问题
@2i2Re2PLMaDnghL 就我个人而言,Actor 模型和 callback / future / 协程不是一个维度的。

actor model 的优势在于 state + mailbox 。每个 actor 上面有个单独的等待队列,即便你在线程池上跑 actor model ,也不会让一个 actor 在多个线程上运行。这使得你可以很安全地编写出来双向交互的 actors ,而不用担心每个 actor 内部的数据存在竞争关系。

线程、协程、callback 、future ,数据流一般是单向的,一个 IO 线程在启动一个后台任务以后就陷入等待,不会处理任何其他事务。而 actor model 每个 actor 都有一个微型 event loop ,完全是全双工的。

你可以很容易用线程池实现 actor model ,避免阻塞调用就能实现完全非阻塞。你也可以在协程上实现 actor model 。或者你也可以在 event loop 上实现 actor model 。总之 actor model 是高于并发的一个抽象模式,核心在于数据封装。
2021-12-13 16:37:29 +08:00
回复了 kingofzihua 创建的主题 Linux 问一个协程方面的问题
通常一个应用程序服务器可以划分为两部分线程组:

1. IO 线程,处理网络 IO 、数据库客户端、等待后台任务、(轻量计算)汇总各种结果。
2. 计算线程,应当是固定数量的线程组成的池,这样一个计算任务丢进来可以排队。

也可以是分离的进程乃至于不同机器处理这些不同的事情。如果是不同进程,可能就会上 zmq 之类的 ipc message queue 。如果是不同机器,那么就会上 rpc 、http api 、redis 或者更重量级的 mq 。
2021-12-13 16:34:21 +08:00
回复了 kingofzihua 创建的主题 Linux 问一个协程方面的问题
@kingofzihua

1. 对,协程只对非阻塞 IO 起作用。
2. 但其实,所有上述的并发方法都是针对阻塞 IO 减少开销的。对于 CPU 密集型任务,如果只有 2 个核,同时跑 4 个矩阵计算是没有意义的。
3. 在实践中,通常把 IO 任务和计算任务分开。IO 靠比如 Promise/Future ,event loop ,协程搞。如果需要调用计算任务,就扔到一个固定线程数的线程池上跑,然后协程进入 await 。等计算完成 await 被唤醒,再继续做后面的 IO 。
2021-12-13 16:16:55 +08:00
回复了 kingofzihua 创建的主题 Linux 问一个协程方面的问题
@0o0o0o0 其实感觉 async/await 就是协程的一种(个人认为最优美的)表现形式。然这需要大量语法糖支持。

Python 和 JS 的 await 都已经上线了,用起来其实挺爽的。只是 Python 方面的支持库力度还不行。

C++20 的 coroutine 虽然语法糖标准已经发布了,但是根本没有支持的库(差评)。还得等几年。
1 ... 35  36  37  38  39  40  41  42  43  44 ... 201  
关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   967 人在线   最高记录 6679   ·     Select Language
创意工作者们的社区
World is powered by solitude
VERSION: 3.9.8.5 · 28ms · UTC 21:10 · PVG 05:10 · LAX 13:10 · JFK 16:10
Developed with CodeLauncher
♥ Do have faith in what you're doing.