2025-02-23

从觉醒年代谈起

最近在补觉醒年代,发觉有几点细节蛮有意思的.
或者蛮值得把玩的.

一个是新青年单价2毛多.
按照0.2银元理解的话,相当于现在什么概念呢?

Gemini给的人均年收入数据在5-30银元的区间,因沿海和地区已经行业属性而不同.

按30银元年收入等价现在6k月社平工资换算的话,大概一银元等于2.4k.
那么一份新青年的售价大概就是480.

然后是李大钊给工人垫付住院费的桥段.
也是大概30银元.

不换算的话,也就是小孩住院差不多要工人一年工资收入.
换算的话,就是住院费用在7w2.

同时值得注意的是李大钊担任编辑的月工资刚好也是30银元.
也就是说当时的一个报纸编辑的月收入等于工人的年收入.

月入7.2w大概就是现在互联网干活的主力中层的收入水平.

从这点看,Gemini的数据倒也不是完全不make sense.

另外一个剧情是陈独秀拿了120银元的稿费准备给儿子.
算人均一年学费60银元的话,两年工人收入,折合现在14.4w.

另外一个就是蔡元培和陈独秀的工资.
里面提到北大offer的是300银元的级别.

月薪72w,年薪800w+,倒也算符合现在对应的互联网收入分层.
尤其是这个package是纯现金的.

于是,在Gemini的这个框架下,回头看新文化运动和新青年的社会体感.

480一份的报纸,折合60美元.
如果当作月刊订阅的话,一个月240美元.差不多就是OpenAI之类的最高订阅费用.
服务的主力提供群体是差不多年薪百万的那群人.

那么一个不太离谱的现代代换就是新青年属于鼓吹AI颠覆传统产业的影响渠道.

如果考虑和保皇派文化之争的符号变换来看的话,大概就是马斯克的X对左派传统媒体的叫嚣颠覆.
或者说是抖音渠道的AI卖课风潮.

当然,倒也不是揶揄新文化运动和新青年的意义,只是做这种转换可能会有一种更具有现实性的实感.

毕竟,如果考虑后面各自的命运归途的话,会对什么是革命和理想有可能一些不太一样的体会.

就像不管是恨国还是粉红的人,放弃年薪百万去投身一个高风险或者说崇高而直面死亡的事情,是需要怎样的使命感这件事有些比较现实的对价.

更不用说那些年薪千万的人了.

而另外的一面可能更容易陷入沉思的对一些人事的价值的重新认识或者说思考.

跳出历史来看的话,或者说从传统历史教科书里,很容易对新文化运动做出具有局限性的评价.

但是如果身在历史中,又如何能做出这些评价呢?

影片里陈独秀有学车夫吃老北京火锅的桥段.
所以你也不能说他不接地气,不了解中国.

但是当你把年收入的差距摆在那里的时候,把一份新青年的售价和普通人的收入水平放在一起评论的时候,可能就有一种不由自主的荒谬感了.

即使不把白话文之与文言文的话语钱争夺视为如今的渠道流量之争.
但从受众的多寡来说,这个命题本身就站在了一个不属于他的高度.

因为这并不是大多数人能够第一手触达的.
甚至在某种程度上决定了为什么各种主义都救不了中国的原因.

而在这种VC/投资都狂热的倾注在这个风口的时候,有人能提出走工农路线是怎样一种insight.

所以有时候你很难说历史是偶然还是必然.

当然,这些都是基于Gemini的基准收入是符合事实的前提.

作为cross check,deepseek给出了另外一组数据.
主要的差异在于除了地区要素之外,还有城乡差距.

跟剧中的编辑收入对比的话,跟DeepSeek的数据是比较吻合的.

大学教授200-400银元,编辑40-60.
城市工人在8-15银元月收入的水平,这个跟Gemini的出入比较大.

不过继续看的话,农村佃农的年收入确实差不多在年20-50银元的范围.

自耕农的收入会高很多,在50-100银元的年收入水平.
不过这部分应该属于后面所说的小地主/富农.
毕竟是自有土地.

按绝大多数人口是农民并取55下限的话,倒也不能说是错的.

总的来说,可能对于沉默的大多数这个表述需要有更多的角度看待.






2025-02-08

聊聊Parquet

最近backport一个iceberg的读feature回一个比较老的presto版本,发现一些比较legacy的bug.
尝试重新实现绕过的时候,发现了parquet的另外一些比较有趣的事情.

设计上来说,parquet的column chunk里是可以记录min/max和num of null values的统计信息的.
这个也是parquet被广泛利用的一个特性,可以用来跳过不必要的io.

看的时候发觉是支持某种程度的udf的.

也就是说像like之类的模糊查询理论上也能够做一定程度的filter.
毕竟原生的operator是不太支持这种查询的.

不过测试的时候发现一些其他问题.

比如读取的时候其实是支持重新指定schema,也就是只读取/project部分column的场景的.
但是因为project的时候的一些逻辑会导致如果project的列里不包含filter条件的列的话,这个filter是会被丢弃的.

一个例子就是比如逻辑上有
select a from table where b > 0 
这种查询.

如果执行引擎只project了a,那么在parquet的io层面是不会触发b>0的过滤的.
连带的执行引擎对io返回结果的假设就不成立了.

这个行为要修倒也不太难.
只是一定程度上来说是个breaking change.

因为从另一个角度来说,返回的结果集存在一个invisible column产生了影响.
从而使得从查询引擎的角度来说,一些假设可能会被推翻.

当然,这个取决于各个上层查询引擎的执行计划构造和pushdown的完备性/防御性了.

不过这里倒是引申出一个问题.
当前查询引擎的pushdown设计是否应该更改为pull-up模式.

毕竟现在流行的一个概念是io设备/存储带有一定的处理能力.

pushdown的本意也是历史原因查询引擎的设计没有考虑到io/存储设备具备这些能力,所以才从优化角度产生了特例进行pushdown的.

如果说一个全新的引擎从设计之初就是考虑了io设备层面具有filter能力的话.
那么相应的就是对不支持的设备的pull-up/fallback机制了.

也就是从
project <- filter <- scan
直接变成
project <- filter-scan
形态.

不过从optimizer的角度来说,似乎是没有区别的.
毕竟在一个嵌套的比如sql查询当中,filter条件可以存在在任何一个层级.

如果按照这种storage with filter的设计的话.

一种是需要把每个subquery也抽象成某种storage,因为这种才能嵌入filter.
但是这样就会造成某些可以在io层面做的filter没有办法push down到io/存储设备.

另外一种是构造独立的intermediate/query区别于最底层的storage io.
但这样同样存在相同的无法push down问题.

而如果把pushdown交给optimizer做的话,就不是pull-up/fallback的本意了.
因为实际上还是存在一个pushdown的优化逻辑.

这样从设计上来说,pull-up/fallabck就成为一种鸡肋了.
无端引入了一种不必要的优化规则.

另外一个比较chaotic的特性是几乎随处可侵入的meta/key-value特性.

虽然目前看着现成的reader框架里是没有接口可以侵入利用这些matadata做进一步复杂的filter动作的.
但是读取的parquet信息里,这部分数据属于read once的东西,而且是required的必定会读的部分,要从代码层面侵入的话,倒也不是很难.

只是从规则上来说,如果真的对这种filter有需求的话,还是能够合并进统计信息里成为正式标准会比较好.

毕竟前面的一些magic特性已经足够让执行引擎对io结果的不确定性打上一定的问号了.

不过可能parquet的人也意识到这个问题.
在metadata里有一个特定的created_by字段.

这个初看可能觉得可有可无,但实际上算是一种变相扩展版本提示.

毕竟根据created_by就知道文件生产的vendor是谁,具有哪些特性是可靠可依赖的.

倒算是一种可扩展性/可玩性很高的设计了.

再一个可能就是生态性方面的问题了.

在写一些测试demo的时候发觉如果真多low level地取读取parquet文件的话,column nested/repeation之类的处理还是挺繁琐的.
而使用稍微一些high level的api的时候,又回发现avro的身影.

原因也简单,毕竟column io最终呈现回给调用方的high level api的结果一般就是通常的row oriented的record.
所需需要选择一种input/output的序列化格式.

问题在于不同的application需要的record类型有差异.

parquet自己选择的是avro.
iceberg这里类查询存储引擎因为面向设计的不同存储类型和文件结构,所以需要有自己的StructLike类型.
spark也有自己专属的Row类型.
presto则是自身对应更高阶递归的数据类型,而且还是此之上又加了一层自己的rowgrow/page/chunk概念.

这就是导致了诸如presto<->iceberg<->parquet的链路会存在很多反复同质又异构的类型拆装.

这个时候人类又才会重新认识到Arrow这类项目的光辉之处.

虽然Arrow的API也是挺low level的就是了.

不过至少提供了一种理论上可能更有的传递路径.

毕竟从结果/实际上来说,现在的大部分查询引擎都是面向column chunk的.
即使实现不同,但概念相近,data pipeline的基本unit也差不多是以这个为基础的.
所以如果能趋向同一个统一格式的话,多少还是会有些生态价值的.

不过从性能的角度来说,有多少好处,有没有好处倒确实挺难说的.

毕竟除了io之外,各个系统之间的memory allocator能不能也一统也可以是个影响因素.
如果不能互通的话,copy transfer还是避免不的.

这种情况下可能统一格式带来的收益就微乎其微了.




一部未完成的适配

看完了一部未完成的电影. 这部片片子比较有意思的是一开始那段自嘲. 秦昊关于既然拍了也播不了,只是私下小圈子里自嗨的事情又什么意义的质问. 片里导演也 讪讪地承认生活的现实. 到这里其实沿着原有的思路,把补拍和一些意外穿插进去,可能还是一个不错的文艺片. 至少于戏里戏外的导演来说...