V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX  ›  lxdlam  ›  全部回复第 2 页 / 共 6 页
回复总数  108
1  2  3  4  5  6  
将一个接口 wrap 进一个 db transaction 本身只保证了 db 操作的“原子性”,这还建立在本身 db 的 txn 处于正确的 isolation level 下。

所谓的接口原子性要考虑的问题远比这个复杂,如果使用了其他的后端服务,诸如 Redis 写入、第三方系统 API 调用,当非原子操作产生时,这些服务是否均支持回滚?是否保证回滚时的一致性?这样就需要从业务逻辑去考虑,然后落实到技术层面去解决,比如 Redis 是否需要 transaction 去配合?对于不支持原子的操作技术上如何取消?无法取消的事务如何在业务跟技术层面去做补偿?
我可能是极少数买了 Mathematica for Home&Hobby 的,今年他把 Cloud access 整合之后估计就继续按年续 Service plan 了
104 天前
回复了 stimw 创建的主题 Python pdm 还是 dev container?
目前主用 rye ,只能说非常舒服
@lxdlam 当然,进阶还有更多话题,比如备份经常还有可能备份错,所以多天 snapshot 之类做回滚也是常见需求;根据 321 原则,是否在合理价格内支持两地、多地同步 etc ,这些大部分也都会算在成本点里面
感觉很多东西楼主没考虑到:

- 流量费用如何计算? Ingress 跟 Egress 各自怎么计算?
- SLA 如何保证?数据取回是否会有延迟?全球上传和下载平均速度如何?
- 安全和合规如何保证?不是所有人、所有存储方案都适合用 borg ,如果直接使用 S3 跟 WebDAV etc ,平台怎么保证安全性?如果有监管部门审计需求会如何响应?

在加密备份领域业界最好的方案应该是 Tarsnap ,当然也不便宜;跟你这个方案类似的是 rsync.net ,他们提供的安全性和方式支持非常完善,供参考。
并没有找工作,只是很好奇一件事:你们对 Elixir 的态度如何?
108 天前
回复了 wyhaya 创建的主题 分享创造 Dataflare: 一款简单轻量的数据库管理器
非常好看,用了下也挺轻量级的,支持了一波。提一个功能建议,可以增加 intergrate db shell 的支持,类似于 mongo compass 和 redis insight 下面的 integrated shell
用 Windows 10 专业电竞战斗版 1.5 。

https://www.v2ex.com/i/z8Tz1085.jpeg

图源来自网络。
111 天前
回复了 darkbread 创建的主题 游戏 游戏玩到一半玩不下去需要坚持吗?
我一向觉得游戏的目的是找到快乐,如果找不到快乐了,就可以不玩。
一方面我同意 #3 ,更像是编译器的 bug ,另一方面我本地似乎复现不了这个差距如此巨大的结果,估计可以看下 1.21rc 到现在( go 1.21.6 ) 的差异。

而对于一定程度上的差异( 100000ns per op ),单纯从生成代码上来看,f 生成的函数直接对 r 做了修改,所以需要一次对 r 的 load ,而 g 是对一个临时变量做修改,虽然二者都是一次 load 跟一次 store ,但是 r 毕竟不好说分配在哪儿(也许在 heap 上,也许在 register ,看编译器优化),那么 r 确实可能比起临时变量( go 倾向于分配在 register 上)的读写要更慢。至于为什么会有如此差异,实际上应该是因为编译器识别出来了这个累加 pattern ,而在 f 里因为没有额外操作,所以直接对 r 进行操作,把加数这些都当 immediate value 优化成单次 INCQ 了;而在 g 中,由于又读到了 r + 0 ,编译器首先优化成了将其写入中间变量的操作,又在后续 pass 中发现其实对 r 基本无操作,去掉了这里面所有 r 的主动 reference ,将其完全优化到了完全只读写中间变量,所以生成了这个样子的代码。

以上仅抛砖引玉,我不是 plan9 和 go compiler 专家,只能看个大概,这里面同样可能会有很多说不清的其他因素影响。但是我仍然同意,这种 case 应该 report 给官方去修改,而不是当新时代的语言律师模拟考题,同样,如果在乎这个粒度的性能差距,可能我们会选择更精细的语言和优化方式了,而不是在这继续抄写茴字剩下的写法。
日区 Spotify 已经两年+。

从体验上来说,AM 跟 Spotify 的算法都很不错,冷启动到符合我的喜好学习速度很快,也不会跟 Youtube 一样,播放列表只会循环推完全特定的歌,基本零探索性(比如推一些可能会喜欢可能不喜欢的)。

但是 AM 缺了一些关键功能,比如必须苹果全家桶才能用上比较好的远程控制,但也仅限是手机/电脑 -> HomePod ,诸如 Spotify 的所有端都可以跨端控制有很大距离。同时,除了苹果之外,Android 上的体验也不尽如人意,最终放弃。

从音质上来说,流媒体我完全不在意音质,确实非常喜欢的歌我都会去 mora ,ototoy 买 Hi-Res 或者直接收实体 CD 抓一份,我对流媒体的核心要求还是方便+曲库+算法。

特别补一个,Apple 的 iTunes Match ,就是所谓的“云盘”,其实非常难用。iTunes 的标签修复有非常大的苹果延迟,就是你并不能完全知道到底这个 tag 修复有没有被正常推到音乐库里面,有可能在 mac 上看起来修了,换个设备发现压根没变化。同时,上传音乐的时候苹果会去自己的音乐库 match ,如果有就会用自己的替代,这样如果你抓了 44.1khz 16bit 的 flac ,但是苹果并没有这个音质的版权,他会给你 match 回 aac 版本,音质倒退。
@ShadowPower 上面 #67 老哥也提到了,其实这个范式在函数式社区很常见,我们重点不关注你是不是所谓的“错误”,而关注类型本身,考虑用类型做 matcher 去配合值做 transformation 。这些年一些工业界的看起来很新的方法都来源于此,比如经典的 parser combinator ,如果你把 `Result<T>` 这个二元类型异构容器思考成 `Pair<&str /* remain input */, Result<T /* Token type */>>`,其实这里面的函数组合跟我上面说的 error monad 是一致的。更进一步来说,函数式的底层数学抽象 lambda calculus ,其实就是一种 combinatory logic ,天生以组合为主。在这种背景下,函数式语言采用这种思考是非常直接的。
@lxdlam typo:这种双类型语言 => 这种支持双类型(甚至更多类型)组成异构容器的语言
单从两种范式上来说,值类型跟异常类型错误直接比较很难比较清楚:

- 值类型还是将错误当作值,本身没有控制流操作,所以当作值处理可以轻松当作比如 data 的一部分到处传递处理等等,缺点就是缺乏强制力,简单把值 ignore 掉就可以丢掉错误,而大家都倾向于懒一点;
- 异常类型可以打断并接管控制流,更加强大,guarantee 也更好,如果 runtime 实现得不错(比如 Java )那用起来其实还是很舒服的,缺点就是这个特性很容易被误用(相信大家都听说过或者见过用 exception 传值的业务代码)。

两种范式各有优劣,其实没有直接关系,语言风格而已。

而单纯讨论值类型错误,Go 的实现有自己的优势。错误这个东西本身就是很容易产生很多 concrete type 的,基于 duck typing 的 interface 化,其实大大简化很多操作,比如直接把已有 error wrap 起来,然后实现一下 `Error` 和一些 helper function ,就能快速搞一个新的错误出来,开发效率是很高的(没有 thiserror 和 anyhow 之前,Rust 搞个自定义错误有多痛苦,相信很多朋友深有体会)。
Go 最大的问题其实在于,他采用了值类型错误,但是类型系统支持非常 basic ,导致大家处理错误非常痛苦。比如在类型系统比较现代的语言中,这种双类型语言或多或少能实现一定程度的 monad ,这样我们就可以写出类似于:
```
let val = some_function().map(fun).map(foo).map(bar);

match val {
Ok(v) => println!("Value is: {}", v),
Error(e) => println!("Failed! error: {}", e),
}
```
在这里面,我们我们确实不关心中间错误,直接 chain 起来,处理最后错误就行,而如果我们关心比如到某一步的错误,我们单独接一下这一步的结果就可以拿到中间结果再做处理。无论是看起来还是读起来,其实都非常清晰明了。而可惜的是,Go 因为一开始设计压根没想这个问题,导致现在的打补丁的 generics ,很长线看起来都很难支持这种比较完备的 monad 特性。所以,我们只能一步步 if-else ,或者将这三个函数塞到一个 slice 里面,用 `reflect` 循环每个函数 apply 去每一步拿一下 type 信息做一些非常丑的补丁。
稍微补一句:为啥这里需要比较好的类型系统才能实现?在上面的流程中,实际上 `map` 接到的函数签名类型是各不一样的,有比较好类型系统的编译器在这里可以做非常好的静态推断;或者我们完全交给动态类型,损失一定 runtime 性能也能做到。而可惜的是,Go 既要选择尽量静态类型,又没把静态类型做很好,就卡在这了。
150 天前
回复了 lear7 创建的主题 问与答 为什么现在软件质量不如以前?
一个角度,其实是优胜劣汰:只有以前稳定、优秀的软件才能在现在才会被多次提及,一种幸存者偏差。
巴别塔圣歌。

作者对语言系统有一定理解,对语言、文化氛围的塑造有出色的把控能力,唯一缺点就是结尾略显机械降神,缺点意思。
177 天前
回复了 lxdlam 创建的主题 酷工作 [北京] 3D AIGC 明星企业持续招聘技术实习生
@northbrunv 会一个即可,如果会 Vue 更好。
单纯只看的话确实 Sumatra PDF 最好用,也是 Windows 平台上个人体验 LaTeX 预览配合最好的 previewer
- 宏:基本上来说宏就是把编译器当做自己的预处理器来做 codegen ,从提案和实现上来看,Swift 的实现还是比较累赘,简化宏的构建和未来使用上,应该还有些工作可以做。
- 跟 C++ interop:本身也是把脏活累活交给 LLVM ,编译器多做一步 parsing ,然后做 codegen ,生成另一边的 binding ,重点看易用性,这一块做的比较好的是 Julia ,不仅可以直接 call C/C++(需要用 Cxx.jl 包)函数,更可以直接在 Julia 里面写对应代码,下面直接调用。Swift 的易用性目前看起来还是不错,期待明天的演讲。至于 CMake 编译工具的整合,是一个很 intuitive 的结果,Swift 支持编译器插件之后,这种加 custom pass 的工作就变得很简单了,比如 zig 也支持直接混合编译 C/C++/zig 代码库。
1  2  3  4  5  6  
关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2489 人在线   最高记录 6679   ·     Select Language
创意工作者们的社区
World is powered by solitude
VERSION: 3.9.8.5 · 38ms · UTC 14:24 · PVG 22:24 · LAX 07:24 · JFK 10:24
Developed with CodeLauncher
♥ Do have faith in what you're doing.