2019-12-28

Partial Order

考虑partial order.

一个set是partially order的,也就是任意地,a b不一定是comparable的.
imply的就是min/max是一个undefined的问题.

那么在此基础上做的minimize/maximize就是无意义的.

因为实际上可能并不存在这么一个可比性.
cost function可能引入了一个并不存在或者说错误的关系.

比如给定a 由于cost function一般是well defined的.
所以一定会引出a
但实际的ground truth可能是c
所以,某种程度上来说regression/statistics本质上算是一种偷换概念的行为.

因为原则上来说,这是两种不同的表达式.
或者说,实际上只是,而且只能是一个近似.

如果对这个partial order做个partition,使得其subset是well defined的.
那么它可能是完全描述的么?

也不一定.

因为subset不一定是bounded的.

所以这种近似并不能做到100%的等价.

那么它的意义在哪里呢?

给定足够多的数据和足够细的partition方式.
每一个well defined subset的近似度越高,整体的近似度也就越高.

理论上来说,是有可能完全表达训练集/样本数据的.
当存在一个partition方式,使得每个子集都是well defined的话.

如果把order关系看作一个directed graph的话.
那么就可能存在一个non-well defined的三角关系,使得不能存在一个拆分方式能够保留完全的关系表述.

一个例子就是上面提到的a
所以如果单纯是为了匹配准确度的话,拆分子集分别计算可能是最intuitive的方式.
而且考虑给定cost function去estimate效果的话,拆分本身也可以做随机化取最优方式.
或者按某种搜索方式剪裁拆分复杂度.

而如果是为了generalize的话呢?

其实可能也差不多.

因为所谓generalize只不过是对于样本之外的一种外延预期.

也就是对于ground truth的可能会是怎样,应该会是怎样的一种合理假设.
基于这个假设的分布特性,通过已有的样本空间去生成模拟空间.

然后对这个模拟空间做fitting.

从这个角度看meta learning的话,也不过是经典的search和feature engineering的组合而已.

所不同的可能是feature engineering更多是一种对概率分布的估计方法.


2019-12-21

Finite Automata

昨天看星战9,隔壁一个小哥在看到凯洛伦和雷伊最终接吻的时候表现有点兴奋.

感觉挺有意思的.

这并不算一个什么很出人意料的场景.
大抵兴奋的来源在于一种长期的预设立场被最终承认的一种价值实现带来的满足感.

那么从这个角度看饭圈/CP/偶像文化的话,大概也是类似的.

一种本质上同人创作的圈子文化.
限定在一定的共同背景设定上的自发演绎.

跟所谓的原作的契合度其实并没有实际上相关性.
就是作为一种基本的创作素材.

这样的话,一些现象也就不难解释了.

因为素材本身品质的好坏其实并不是这些二次创作者的关心点.
素材的价值在于提供了一个初始的设定/人设,帮助汇集了一些共同爱好/价值取向的人汇集在一起.

本质上是一种萤火效应.
一种类似随机光亮吸引昆虫的某种触发群体本能的一个动机.

用这个解释对偶像人设的一种苛刻性刻板要求的话.
就是一种偏离设定的不满情绪.

因为从这个角度来说,人本身反而是这种群体创作形象的一种现实的re-projection.
是一种反向作为虚拟设定向现实具像化的反向投射.

就好比针对图纸设计的实际工业产出的精度要求.

于是基于此衍生的消费品的着力点就并不在于消费品的意识形态本身.
而在于受众的接受程度或者说付费点.

所以本质上来说这是一个商业对于消费者的取悦行为.

那么它跟一般的商品买卖的区别在哪里呢?
或者说存在么.

基于供需理论的市场交易是建立在撮合机制上的.
也就是给定相互独立的供给和需求关系,在名为市场的机制下,产生一种联系对应关系.

它的一个前提是需求和供给的产生是相互独立的.

而商业在于,给定未匹配的需求提供对应的供给.

所以从这个角度来说,同人消费并没有什么特别的理论上的不同.

考虑另外一种情况.

在商业贩售本身并不可以提供某些内容的情况下,由消费者二次创作出来的内容/要素.

这一点有些作品会作为一部分要素加入到原有的体系当中,当作一种甜点.
视程度的不同会对原有体系产生不同程度的倾斜和偏移.

另外一些作品则是本身因为各种各样的原因并不会或者并不便于/能够在官方体系当中加入这些要素.
但是并不排斥消费群体的二次创作.

再一些就是从根本上排斥二次创作的.

顺便地,针对二次创作的次级二次创作也可以视为稍微调整定义放到以上适用.

那么一部作品的消费成分就有两部分.
一个是原作品本身想要叙述提供的部分.
以及为二次创作部分提供素材的部分.

除了完全排斥二次创作的作品意外,其他的商业化路径无非就是两部分的比例侧重的不同.

考虑存在混合比例的情况.
在给定一个市场最大化效益函数的情况下,自然会针对两部分做不同的倾注投入.
以产生目的的投入产出.

所以从结果上来说,无非就是最广大人民根本利益的代表,或者说反应.

它的一个结果就是针对不同的效益函数作出的比例调整,以及基于此的长期自反馈带来的长久的比例成分变化.

以及基于此的连带的周边体系生态的随迁变化.

从这个角度来说,群体养成可能是某种更高阶一点的技术手段.

因为从商业角度看,依然是群体在引导商业作出变化.
而往上的,则是上层针对养成群体的参数控制和调整的一个结果.

某种程度上来说,也算一种设计精巧的finite automata.

2019-12-15

关于Profiler的一些想法

最近写个profiler,写完发觉大概有点不切实际.

开始是基于一个相对简单的想法.
因为一般debug java的一些线上问题无非就是看下哪些是hot method.
suspect之后一层一层顺着堆栈定位下去.

过程大体是相对繁琐的.

所以想着把这段稍微自动化点.
给定一个entry point,把整个execution过程的调用做个统计列出来.
免得再人工一个个去深入.

于是一个直接的想法就是做instrument.
在每个方法的调用前后加上time span,做耗时统计.

这里当时想了两种方式.
一种是在每个invoke*指令前后插入enter/leave的时间戳.
一种是在每个方法的entry/exit做这个时间戳统计.

第一种相对来说,最后生成的字节码会比较繁琐.
而且如果考虑到异常情况的化,这个time span可能还需要针对每个invoke做一个try-catch/异常处理block.

所以选择是在entry/exit插入.

从另一个角度来说的话,选择后者也实现上会相对的leap/优雅一些.

因为就是一个简单直观的rule.
而且具有相对的普适性.
即使再考虑异常情况的话,也又一个比较简洁的框架模式可以套.

比如对于一个
void target(){
// some code
}
形态的method来说.
插入之后大概就是
void target(){
Bridge.enter();
try{
// orignal
Bridge.leave();
}catch(Throwable e){
Bridge.leave();
throw e;
}
}

针对正常和异常都能相对结构简洁优雅地处理设计统计.

这里一个题外话就是Bridge的设计.

之所以叫Bridge主要是实现上用了一个小trick.

考虑到targe JVM一般是不太能够重启的,而attach的instrument agent有时候代码需要做改动.
尤其是开发时候.

所以实现上这里做了个classloader的处理.

agent在host vm里加载的时候会污染一部分host vm的classloader.
也即是agentmain部分的class会在host classloader里存在.

而如果全部agent code都是在这个classloader里的话,那么要达到代码的hot swap是不太可能的.
除非是transform自身.

于是,这里在agentmain的入口里做个简单的壳.
在agent load的时候切换切换class loader,使得每次attach的session使用自己独立的classloader.
以达到避免污染和hot reload的效果.

大致效果上类似于JSP的一些使用.

因为本质上来说,java的class实例是跟当前调用method的所属的class的classloader绑定的.
这样的话,只要创建一个目标classloader的shell class就能让后续的execution的常规class创建绑定在这个session bounded的loader里了.

在处理了这个热加在和基本的字节码处理框架之后,剩下的就是调用链条的crawl了.

直觉上来说,这也是个相对简单的过程.
因为jvm无非就几个invoke指令,scan一些method的bytecode做个筛选然后递归一下就是了.

只是实际麻烦的点就在于这几个invoke指令的语义.
尤其是invoke virtual和invoke interface.

根据jvm specification.
method resolution主要是基于class往上回溯的.
在interface和class method存在同名的情况下,class method的resolve规则相对靠前.
也就是相对的是favor的一方.

对于两者来说,给定一个invoke some_class some_method的指令.
形式上都是做一个virtual dispatch.

是运行时需要根据具体的instance类型做vtable/itable的lookup找到实际bind的method的.

也就是说,在scan到类似invoke some_class some_method的时候,并不能直接对some_class some_method做递归instrument.
因为除了some_class可能并不是concerted的情况意外,还有就是实际是一个sub class override的情形.

因此实际上要递归的对象/目标是从class/type hierarchy中upper bound为some_class的所有子类.

这样的话,就跟最初预期有了第一个意外.

当初预期做stack trace/调用链递归分析的出发点在于尽可能地只trace interested的部分.
也就是只在调用链条内的方法开销.

所以,在具体的tracing统计了,还做了个简单的per thread的stack matching.
保证被profile的方法的call stack里包含想要trace的entry method.
使得并不是所有特定方法的调用耗时都会包括进去,而是只有特定的调用栈的会被统计进来.

而如果作为upper bounded class的话,虽然形式上来说并没有打破这个约束/优化.
但是实际上的结果是会包含引入非常多的class被instrument.

一个测试方法的数据就是大概2000多个类会被触及到.

尽管理论上来说,这里是可以做一个静态分析的去除一部分的.
因为毕竟是实际上又所有被加载类的信息,加上制定了特定堆栈约束.
也就是相当于给定的一个execution state的initial parameter.

基于此做一个静态分析/执行引擎对涉及到的invoke做类型限定推导是有可能的.

只是一个是这个代价稍微有点大和复杂.

因为本质上相当于做个interpreter.

尽管如果写了之后可以进一步作为一个fuzzer的基础.

然而即使有了这个interpreter也并不难100%的限定类型.
因为存在一个动态类型是只有运行时才能确定的.

一个简单的例子就是反射.
以及一些涉及类似serviceloader加载机制的纯运行时特性.

于是,既然这种裁剪方式并没有一个相对完美的效果的话,那就不如不做筛选.
而是直接对所有class做instrument.

这样的话,实现上也更直接,不需要去做invoke scan的递归递归扫描操作.
而是直接无差别的transform,然后再在运行时再根据call stack决定需不需要做accounting.

唯一需要考虑的就是避免在做accepting的时候陷入递归.

因为做call stack check的代码也是被instrument的.
所有如果不对一些类做白名单处理的话,就直接递归了.

白名单的构建也尝试过用invoke scan的方式尽可能地构建一个小而完整的集合.
但问题依然是没办法100%保证确切的类型限定.
最终也是会指向type upper bounded的道路.

所以最终实现是用了限定java.lang和java.util将大多数jdk class排除在外.

在这个方案基础上出来的结果是第二个不预期的情况.

最初的构想是做了stack tracing之后,直接列出整个call stack的每一步的耗时.

而实际的结果是,尽管确实有了完整的call stack的每个step的耗时统计.
但问题在于涉及的method invoke太多.

一个方法trace有时候会展开成数十甚至上百的invoke method.

这个在事后其实也不难理解.

简单考虑一个method有个k个invoke,每个invoke针对m个class.
那么一级就是大概有k*m的调用统计.
再对每个k递归的话,就是理论上指数级的展开.
即使考虑其中可能会有重复的部分.

但理论上越是复杂的函数,最终的展开级数就越多.

所以这个在实际上是没有什么太大意义.

而且另外一个问题是因为是transform几乎所有class.
所以attch的time会明显地跟class数量线性相关.

更主要的是之前提到过的.
transform实际上会触发JIT的de-optimize.

针对所有class做instrument的话,基本上就是整个jvm打回warmup状态.

尽管理论上来说,会eventually JIT的.

但是从这个角度来说,基于instrument的profiler是会有一定程度的失真的.
尤其如果问题的实际不在bytecode层面,是VM本身的一些特性的话.

所以可能确实是基于perf couter和jvmti event的方案会更优雅准确一些.
至少,它们对VM的观察不会影响已有的JIT状态和实际的VM的代码层面允许逻辑.

2019-12-07

负利率

负利率也就是说央行在做积极的cash in.

反过来说就银行自身的头寸在减少.

如果要维持增长规模的 话.
那么,要么提高利率,要么加快周转速度.

提高贷款利率的话,需要借入方存在相应等级的ROI.
不然是非rational的.

考虑如果实际负债/债务水平在合理的条件下.
反过来也就是说,确实贷款利率水平存在弹性空间的前提下,进一步提高利率是合理的.

而如果负债水平已经在一个水平之上了, 高利率显然是没有什么空间的.

这是在债务人的ROI在利率水平之上的情况下.
利率水平存在一个upper bound.

那么如果ROI是irrational的呢?
也就说,实际的收益率低于贷款利率水平的情况下.
是什么动机驱动借款的产生的呢?

这里其实是一个递归过程.

把出借方置换成央行,借入方置换为银行.
那么借入方的动机就在于维持规模增长.

则在这种情况下就是一个同态的链式结构.
整个链条的稳定性取决于末端节点的rational的ROI水平.

而实际情况可能更复杂一下,不是一个简单的无环结构.
可能是一个复杂的网络图形态.

但不管怎么复杂,都存在一个单一的链状结构,使得整个链条的稳定性和风险聚焦于末端的状态.

如果末端出现一些不稳定因素的话.
比如default的话,那么网上回推就是 一系列的坏账.

加上环状结构的放大的话,可能就是一个系统性风险.

所以一个很自然的,在复杂系统下的简单防御策略就是控制债务规模.
降低违约风险.
至少是要在一个可控范围内,防止反推压力,以及阻断扩散.

这是在利率空间上维持增长的情况.

考虑提升周转率的途径.

在给定总量缩减的情况下,提高周转率也就因为着在单位时间内是可以达到 缩减前的规模的.
而理论上来说,提高周转率也总是一个逻辑上 较优的一个解.

同样地,如果周转率存在进一步上升空间的话,是没什么问题的.
因为可reduce成不同利率上限的情况.

如果周转率 不能进一步上升呢?

这里如果再细分一下.
即分为不同品质的周转率的 无法进一步提升.

那么显然地,高周转率的产品会具有优先偏好性.

也就是说,在这种情况下,短期贷款会优先于长期贷款.

intuitive的也是.
周期长意味着复合风险高.

所以在这种情况下,短期借贷会较长期更为繁荣.

而如果不是的话,要么说明短期符合利率upper bounded的情况.

或者在现有的规模下无法有效地触发短期借贷.
比如长期借款已经沉默/沉淀下来了,在短期内无法convert成较高流动性的成分.

在这种情况下就会有动机将长期负债转化为短期负债.

非单一债权人存在的情况下,一个合理且直接的做法就是想办法令自己的长期借款结算.
然后产生一个新的短期形态的债款.

这个短期借款可以是自己也可以是新的债权人.
而后者,整个系统来看的话,不过是风险所属方的转移而已.

那么对于针对自身的长期转短期的可行性呢?

长期的风险在于一是抵押品的流动性,二是偿还周期本身.

后者在债务人支付能力既定的情况下,只能是某种频繁短期债务置换方式.
即将一个长期债务等价分割为一个连续可展的短期性质的债务.
降低违约风险和反应时间.

前者的流动性问题的话也类似.
改变抵押物流动性的方式要么是变成可分割的.
要么是转变抵押物的构成方式,化整为零.

相对于分割方式需求的法律等其他因素变量更多之外.
抵押物置换拆分的方式可能更合理且现行可操作.

而对于短期借贷本身来说,因为形式上求解的过程使得周期本身是一个常量.
所以风险的分散可能在于额度.

这么一想的话,能串起来的就多了.




2019-11-25

巴别塔

有时候会想,什么是fake news.
为什么会有fake news.

有时候又觉得,这其实是个伪命题.
因为它可能不过是一种对于失控的一种描述性称呼/代称.

在一个旧有的舆论话语体系下面,一个”大众“的预期大体是可控的.
因为渠道和媒介就那么多.

跟重要的是人的信息半径多多少少受物理界限的约束.

不过车马书信.

事情的变化是从网络社交媒体的渗透开始.
信息的流动变得迅速而形式多样内容丰富起来.

而这种传播的基础是节点的延续性.

也就是说,只有节点间相互承认,一个信息流的声明周期才能更加地长.
于是反过来说,一个存活下来的消息,多多少少是有一定的degree/传播路径/广度的.

那么在整个network bandwidth/人的digest能力还有余地的时候,可能表现出来的就是信息的高附加值属性.
也就是常常怀念的互联网初期的单纯美好.

在一个介于数量相对少而内容相对高的阶段.

随着加入节点的增加,network congestion,信道带宽的价值变得尖锐和有利可图起来.
于是就是所谓的流量经济时代.

imply的就是每一个信息byte的对应成本可计量化.
随之而来的自然是关键节点和backbone的priority处理.

关键节点有各自的maximize策略.
而给定的channel又是有既定的fanout能力的.

所以priority的结果就类似于一种rectifier.
最终就是top n的各种信息的sub shape.

考虑即使是fully connoted的graph.
由于fanout limitation的存在,那么理论上就存在一个信息流不存在一条cover所有节点的路径.
因为它可能被一些节点劣化,从而失去了被route出去的可能性.

那么,也就存在一系列这些部分劣化的路由路径所构成的一个子图.
也就是所谓的echo chamber.

所以,即便是一个完整的全连接图,在给定一个activation阈值的话.
也是可能退化成为一个个的isolated network的.

如果把这个基本网络结果高阶为一种认知抽象或者说社会共识的话.
也就是所谓的各种独立的舆论单元.

每个单独的group/unit/团体有着自己的一种自洽且可能无法在内部证伪的一套理论.

以这套规则审视系统外的变量的时候,自然而然地就难免会有一种不真实感.

毕竟into the unknown就意味着两个子图存在着交集.
也就不能称之为distinct的子图.

fake news大概就是这种局部自洽,全局冲突的一种产物.

对于社会结构的影响在于,一个单一的社会认知/共同认知的可能性的破灭.

就像一个数据中心到一定规模比如会出现分层隔离的网络拓扑.

这是信息流动的便利性带来的overload的一个必然结果和选择.

所以一个团体对于另外一个团体的行为的可预测性和可控性就相对的变得没有意义.
或者说是未定义的.

因为本质上来说,是两套不同的行为体系指导的系统.
也就是所谓的非普世的.

没有一个能够统一思想和道德标准的可能.

所以,说控制fake news和algorithm的操纵性某种程度上来说确实是一回事.

就像做一个BGP/路由/ARP广播.
所期望的不过是以一种合理合法的方式,扩建自己的子网规模.

但从长远来说,多多少少是徒劳的.

只要信息的生成速率至于网络自身的带宽承载能力有一定的优势.
那么scale out总不是那么容易的.

所以某种程度上来说,就社会制度设计层面来说.
基于crowd的consensus架构是很难维系的.

因为没有一个很好的scale out机制.

这样的话就难免不得不面向一个不是那么让人舒服的解决方案.

那就是Qos.

因为问题的本质在于过于自由和无限的信息流动性,造成的congestion和bandwidth flaw.
那么一个直接的方式就是rate limit.
和关键节点的degrade.

这可以说是一个很让人沮丧而又不得不承认的一个事实结论.

所以从这个角度看的话.
可能不作为反而是一种略带喜闻乐见姿态的态度.
作为一种长期被批判攻击的体制的忽然的优越性体现.

尤其在consensus机制在被echo chamber/fake news困扰,苦苦挣扎进一步scale out方向的时候.

你很难说最后会不会全体转向QoS.

尽管不算优雅.

but it works.

更重要,或者说可怕的是,可能没有其他方案.
而且从技术层面上来说,做zone隔离,相对来说还是一个fail safe的基本实践.


于是人类又重新建造了一个巴别塔.

2019-11-16

JIT Inline的一些问题

大致这么一段逻辑
```
void test(item){
if(array_list == null){
array_list = new ArrayList<>();
}

if(!array_list.contains(item)) {
array_list.add(item);
}
}
```
这段代码在两台机器和不同用户之间会有些比较明显的性能差异.

具体是有两台机器A,B.
A为一台KVM,B是物理机器.
A宿主机器跟B是同型号CPU.

现象是一个benchmark在A上大概是5分钟不到.
而B是20-30分钟左右.

另外一个就是在B上以root和非root用户偶尔也会有些可见差别.

这个case的实际逻辑是是加载并解析一个配置,并且是单线程的.
所以整体过程应该是deterministic的.
理论上不应该有这么明显的差异的.

perf了一下.
B上面有一段是change_protection_range会相对显著地跟A有所区别.

大概翻了下对应内核版本的实现,看上去有一些huge page/large page相关的东西.
但是看系统参数和JVM配置,largepage相关的选项也并没有打开.

而且对比了下两者的环境变量和生效配置以及相应的.so也是一致的.

所以从系统层面是上来说,应该都是没差别的.

于是看了下VMThread的safepoint信息.

从日志里看是有一些bias lock的revoke情况.
但是从代码逻辑上来说并没有显著的synchronized应用.
这点就有些奇怪了.

把bias lock disable之后greys attach上去做profile.
然后发觉貌似性能是上去了.
两边都差不多是每秒20-30w左右的调用次数.

但是感觉不是很有说服力.

一个想法是bias lock带来的一点object的开销在这种频繁可能会有新对象创建的场景下被放大.
这样的话可能会跟perf的change_protection_range有联动.
因为可能会对cacheline有影响,毕竟一个是KVM一个是物理机器.

为了确定关联性,把profile去掉之后发觉性能差异有出现了.

那么为什么profile会影响到性能呢?
而且是positive的影响.

想起agent在retransform的时候,redefine class会触发deoptimize.

那么,如果是JIT的问题的话,agent deoptimize能提升性能,也就意味着触发了某个优化规则导致的.

尝试不同的compilation policy.
发现在non-tiered compilation(simple/stack walk)的情况下是ok的.
但是开启tiered compilation(simple threshold/advance threshold)之后则有大幅下降.

用perf-map-agent重新perf看了下.
发现non-tiered的情况下,hot code是array list的contains/indexOf.
而tiered的则是test和equals.

到这里其实就已经很明显了.

non-tiered只inline array list的相关调用,包括indexOf里的equals.
所以perf只看到了contains或者indexOf.

而tiered JIT了test和equals.

实际上看生产的assembly,除了做inline之外,同时还对indexOf做了loop unroll.

但是看perf的结果是test和equals同时被JIT了.
那么也就意味着test没有把equals inline进去.

看JIT生产的assembly证实了,对于整个调用链,也就是indexOf里的equals还是callq调用的.

所以应该是某个机制限制了把equals inline进去.
从而loop unroll之后反而引入了函数调用开销.

把inline日志打开可以看到test的inline有两类信息.
一个是callee is too large.
另外一个是already compiled into a big method.

这就可以解释了.

因为test本身不复杂,所以没有触发自身被caller inline进去.
于是hot code也只会inline这个调用链以下的.
而由于inline和loop unroll使得本身的code size变得比较大,在尝试进一步inline equals的时候被拒绝了.

调整这两个相关参数之后再看确实没有了equals的调用,同时性能保持了一致性.

而再回头看为什么KVM和物理机会有性能差异的时候,大概就是因为compiler thread的数量和并发程度不同.
因此在尝试inline equals的时候会出现时机和结果的不一致性.

所以想想的话,从代码风格上来说,确实compact和reusable的会相对来说比较友好一点.

像Stream这种batch process的风格来说的话,确实有可能for之类的手工展开的好.
因为一个loop unroll,一个是函数主题一般都比较小.
再就是手工展开的话,很难说不会触发像上面这种inline不完整反而受累的情况.












2019-11-10

关于Final的一些问题

考虑一些字节码的生成问题.

比如
```
long start = System.nanoTime();
long end = System.nanoTime();
Profiler.INSTANCE.collect(end-start);
```

按照SSA的风格话,大概会是
```
invokestatic
lstore 1
invokestatic
lstore 2
lload 2
lload 1
lsub
lstore n
getstatic
lloadn
invokestatic
```
这样的形式.

如果是手工生成的话大概会是
```
getstatic
invokestatic
lstore 1
invokestatic
lload 1
lsub
invokestatic
```

区别在于压栈的次数.
因为调整了Profiler.INSTANCE入栈顺序.
所以基本上按照最后collect参数规格维护stack的.

如果要自动地做这种重排的话呢?

本质上来说,就是针对一个函数调用入参约定的一个dependency resolution/backtrace.
就一个control flow的graph来说,可能做的还是一些prune/merge的事情.

不过如果再仔细考虑下上面的例子的话.
其实两个并不是等价的.

因为这里隐含的一个假定是INSTANCE是immutable的.
所以push的时机不影响最终的结果.

但如果INSTANCE是mutable的话,那么这种重排其实是有问题的.
因为后面的调用/指令可能会影响INSTANCE的值.

那么有没有immutable的情况呢.

理论上来说,应该是没有的.
因为如果用反射的话,对于final的field也是可以改变值的.

而且这里比较有趣的一个地方就是final本身的实现.

大概瞄了眼c2的相关代码.
主要是getfield和putfield的.

里面提到确实是会对static final和@Stable的field转成constant node.
这个容易理解.

但是putfield并没有针对final做什么过多特殊处理.

那么如果是严格按照bytecode执行的话,问题不大.
因为不管是get/set/static/field,还是反射的读写.
针对的都是同一个东西.

但是如果是JIT过的,那么在生成native code的时候依据的是转换后的constant node.
这样的话,就可能并不是很符合预期.

一个简单的例子就是一个boolean的if condition.

因为field access变成了一个constant,那么就有可能触发一个优化规则把整个if优化掉.
而当用反射把这个值置回true的话,貌似并不会触发deoptimize.

这样的话,即使从代码和逻辑层面上来说if分支应该被执行,但实际可能是并不会被执行到.

那么如果想办法让put指令里触发deoptimize的话呢?
比如动一下FieldAccessor的相关路径和生成的native code风格?

理论上来说应该是代价比较大的.
一个是如果在native code里对field access引入一个stub的话.
则在这个field被修改的时候需要知道哪些native code部分是需要做改动的.

这个如果不是stub的方式的话,基本上是不太现实的.
因为必须维护一个列表.
这样的话复杂度就不低了.

而如果用stub function的话,就没什么太大意义了.
本来就是一个最多二次寻址的问题,变成反而需要用一个更重的function call替代.

于是从这个角度看的话,set final某种程度上来说算是一种挺危险的行为.
因为这个导致的不确定行为可能还跟环境有关.

在触发JIT的情况下和在interpreter的场景还不太一样.








2019-10-08

距离感

最近在日本随便乱逛.
有时候会闯到各种神社里,于是就会翻翻祈愿牌.

多数日文还是看得很勉强的.
但里面也不乏一些港澳人士的中文.

偶尔就会看到关于香港祈愿的.

从字迹和言语风格/内容上看,年龄段不乏一些明显学生和一些上了年纪的人.

起初没什么太多想法.

后来想了想立场问题.

可能现在国内外都可能会指责对方新闻报道的偏颇性.
尤其对于protest方的.

你很难说哪边报道就是对的或者哪边就是错的.
毕竟事实上,材料都在基于事实的.
更何况人群构成纷繁杂乱.
你可能也很难用一个整体的定义去概括盖章一个群体.

这里想谈的是另一个角度.

就是这些祈福牌的作者.

它们应该不是上街protest的一部分.
甚至可能恰恰是因为骚乱而选择到世界其他地方寻求安宁的.

也就是说,态度上可能可以定义为一个中间派或者不发声的部分.

他们不属于谴责抵抗者的一方.
也不属于protest目前行为的支持立场.

但是表明的立场和意愿却不能说是隐晦或者模糊不清的.

可能对于年轻人来说,正如他们会用的一个词.
荣光.
来为这种上街行为做标注.

还有一些可能有一定阅历的,会用光复.

无论是那种形容词,立场上来说,引申的就是他们并不算满意当前的状况.

不满意的点可能跟最近的NBA,之前的奢侈品和诸如炉石暴雪,AppStore一样.

用刚看到的一个观点来说,就是目前国内的这种censorship文化的外延干涉.

就像一国两制.
有些重点在一国,有些人重点在两制.

而以当前的文化策略来说,很难说是一种文化输出,更多的时候像是一种文化侵略.
而且是不受欢迎的一种殖民性输出.

即不管别人接受不接受.

从最近的方向来说,可能会有越来越多的这种文化冲突的发生和发酵.

因为个人和集体的关系,国内外的认知差距可能还是有一定的.

尽管从通俗文化层面上来说,国内也越来越有自己的生活别人无权干涉,以及别人过得怎么样怎么想与自己无关的倾向.
但是意识状态层面还是有着诸多的禁忌和相对保守的一面.

而外面可能更多的是相对脱钩的.

虽然可能会把爱泼斯坦之类的事拿出来做做一种制度攻击的例子.

但换个角度来说,在没有爆出来之前算是一种潜在隐规则.
它的界限在于,并没有正式的社会性的显式影响.
从某种程度上来说,在未曝光前尚属于私域问题.

而经过媒体见诸公众之后,才成为一个社会道德问题.

区别在与社会性.

同样的逻辑或许也可以套用在民族感情和政治立场上面.
只要经过了发酵成为一种公开谈论的事情,就是属于社会情绪情感层面的.

而公开谈论这点,对于西方认知中的中国来说,是一个清晰但缺乏明显标尺的问题.

或者对于可能是所有商业公司/团体/机构来说都是如此.

而在做商业来往的时候,为了利益上的考量,做出一些censorship的让步或者说退让,也不能说是完全不可取/不能接受的.

但有公司比如Google的先例也反映出了这种博弈的单方面强势性/弱势感.

totalitarianism文化从本质上来说是一种绝对服从式的文化.
其中可能有其自身的内在合理性,甚至对于一个实际的庞大系统来说,某些不尽为人满意的构成部分,都是被非常必要的.

就像一个中心化的分布式系统来说,一个效率和能量强劲的中心节点几乎是系统正常运作的基础.
为了整体系统的正常和合乎效率的运作,一些privilege/authority是必要的.

但是这并不构成绝对服从的正当性.

但文化上的东西有时候很难有一种明确的界限或者说距离感.

就像有些公司会限制着装IM头像之类的作为一种纪律性要求,目的是作为一种效率提升的形式工具.
但你很难说这里的合理性,而不考虑其可能的真实用意.

很多时候就是一种无意识的本能性干涉.
或者说武力扬耀.

所以当这种有意无意的干涉本能作用于另一种文化的时候,就存在了冲突的可能性.

而双方合作的前提在于对条件考量的最终接受程度.

如果说这种被动的censorship代价行为了一种不可接受的共识的话,那大概至少对以合作代价的再计量是有相当影响的.

你很难说全球化会不会变成两极化.

毕竟全球化的问题之一除了经济上的转移和新殖民之外,再就是文化冲突渗透到各个领域的一些表现.

有时候是融合再生.
有时候是弱势小众团体的权力极化.

想起years and years里,有支持vivienne rook的大概这么一句.
Let's take the world down.

背景大概是世界已经这么不可理喻了,不如推一把使其更加疯狂的一种末世情绪.

2019-08-04

谈谈黄金

黄金之所为为黄金,在于它是一种普世的价值度量标准.

可能也算一种历史的偶然性和必然性结合的一个产物.
在没有现代经济信息网络之前,达成了一种对于异构经济/货币系统的交换中介共识.

某种程度上来说,也许是因为有着一些专门的或者发达的贸易商队国度的活跃.
将一种稀有奢侈品作为一种平准机制.

就像瓷器香料之类的,也在某种历史时期内有着显著的等值交换属性.

只不过因为工艺发展的原因,保值能力不算好.
因为稀有性受到冲击.

而稀有性之所以重要的原因在于凭证信用的支撑.

或者说某种程度上的不可伪造性.

作为一种一般等价物来说,它除了表征不同商品/物品之间的可交易order关系之外.
还代表着非交易过程中的某种价值储藏容器.

固然的,无论货币或者商品的存在之在于交易发生的时候才有意义.
价值本身也是在交易的时候具有比较实际的反馈.

但是交易本身不是随时连续不断发生的.
在非交易时期,这种商品与商品之间的等价关系就以货币这种抽象形态存在.

而既然称之为一种储藏容器,那么就代表着它需要又一种一定程度的不变性.
或者说时间无关的兑付/交易能力.

因为如果在t时间之后,容器本身不可用或者其代表的支付/购买能力不如初期.
那么也就谈不上是一种凭证储藏了.

所以黄金的稀有性和恰巧作为一种金融的长久形态保有能力成为一种合适的容器表征.
而同样的作为贵金属的白银在这方面就弱得多了.

那么在现代来说,为什么金本位有时候会显得不合时宜呢?

现代金融的交易方式主要的基础是信用本身.
以及信用衍生的各种副产品.

所以它本身是以各种直接或者间接的担保品作为兑付凭证的.
而这些凭证是在一定的市场范围内被一定的参与方所共同认同的.

也就是说,尽管可能抵押品具有形形色色的形态的承兑模式.
但是重要的是市场的参与者对于这些抵押品的通用货币兑付能力并没有很大的异议.

即使是以及其廉价的纸质或者不存在实体的electric的合同来说,交易双方都对违约风险有一个可控的接受共识.

因此黄金的rarity/immutability对比并没有更优越的表述能力.
反而可能因为其本身的一些属性而具有这样那样的不便利性.

所以,金本位的退位似乎是个必然的过程.

但是考虑这种互信的过程其实隐含的是市场稳定的假设.
也就是交易各方对于各种承兑能力的确定性的一种信心.

而一旦这种信心不存在的话,就是所谓的经济危机的出现.

不管是基于信贷违约的企业行为,还是国与国之间的货币冲突政策.
前者带来的是抵押品的货币价值假设的湮灭.
而后者是一种更大程度上的国家社会级别的兑付危机.

就像次贷和津巴布韦法币的形态.

这时候的黄金就像一国金融危机下的央行角色.
作为最后信用的一种事实担保.

也就是为什么称呼黄金为避险手段的一个原因.

在非全球性经济危机的前提下,即使有个别国家或者区域的货币会产生比较大的动荡.
但是总的来说,因为存在几个相对信用能力不错,且有一定影响力的货币存在.

于是事实上的,作为全球通用价值衡量标准实际上就是由这一组货币的汇率所反映出来.

而一旦这组货币本身不再存在相对稳定的关系.
或者有较大分歧.
或者因为内生的一些原因,自身内部的变化,因为权重的问题不必要的扩散成为全球性的一种危机形态.

这种微妙的平衡关系就会让基于这组货币的定价原则变得具有相当的不确定性.

因为买卖双方之间对于同一物品的市场价格,在不同货币体系下不再具有统一共识的前提下.
交易就不太可能顺利的发生.

因为以同一货币计量的时候,双方对于这个度量并不能够达成一个共识.
也就是类似货币稳定时候,对于价格本身存在争议的情况.

而这时候,就只有古老的黄金还存在着一定的价值common sense.

所以这也就是为什么即使非金本位的今天,一国依然会有黄金储备的需求.
以及为什么在正常情况下,一国可以以另一国的货币/债务作为一种桥梁表示.

后一种方式由于是一种间接方式,所以本身是相对于直接锚定储备来说,具有更多的不确定性的.

但是是否就意味着实际上有必要重启或者认为依然是金本位呢?

实际上,在真地发生信任危机的前提下,黄金储备也很难说能够出任一种平准价值体系.
因为交易双方可以可以退回到原始的物物交换.

除非是一种群体性复杂交易链条,需要一个充当价值缓冲的外在物质充当交易催化媒介,促成交易.

本质上来说,在这种情况下,人们需要的是一种本身可交换的低违约风险的信用兑付凭证.

可交换和信用凭证两点是很容易满足,或者说构造的.
比较麻烦的是低违约风险这点.

违约的风险在于交易的不对等性的事实发生.
或者说通俗的,资产的减值的发生.

又或者字面地,履约能力的异常.

所以考虑把合约作为一种不可变载体记录下来的诸如blockchain之类的方式是没有意义的.

有时候可能反而是一种多余的策略.
因为如果信用本身还存在的话.
可不可变其实并不是本质上的需求.

充其量不过是程度和进程上的区别.

违约风险的规避一个在于对事实违约造成的减值情况的对冲.
一个是对履约的强制力保证.

而后者在一定程度上来说,也是一种对冲方式.
不过就程度而言可能可以称之为积极对冲.

所以说到底,在没有信用互信的基础的情况.
其实也就是最初的野蛮时代.

这时候讲究的可能是强制力了.

也就是所谓的武力.

2019-07-29

从排序想起

考虑,从set S中根据偏好P选取一个元素E.
本质上就是用P对S进行排序的问题.

或者说order的问题.

考虑通常意义上的三个关系.
大于,等于,小于.

考虑没有symmetry/cyclic的情况.
即,大于小于的一个order chain不构成一个环.

那么大于小于可以合并为一个符号.

定义等于为=,非对称的大于小于为!=.

则给定任意a,b.
两者要么是=,要么是!=.

换一套符号表示的话.
f({a,b})= {=,!=} = {0,1}就算某种形式的binary classification.

考虑到前面的非对称限定,f({a,b})可能undefined的话.
回归三值,=,>和<,就是triple/muti classification. 那么从这个角度看. 排序的数组就是某种形式的index结构. 索引的是所有可能组合的分类结果情况. 也就是从element e->number index -> {=,>,<}的一个路径.

formalize的话.
就是给定一个set X,如果存在一个映射f.
满足f(x \in X) = N.
使得C(f(a),f(b)) = {=,!=} = {0,1}

如果是一个multi class的话,给定number of class=K
C(f(a),f(b)) = C_k(f(a),f(b)) = 1; C_{k-1}(f(a),f(b)) = 0.
也就是将为零的递归下去.

但是这个f不一定存在.
因为可能根本不是有序定义的.

但如果存在的话,如何去寻找这一个f呢?

如果ab所在的set S是有限的话.
那么实际上C是一个确定的集合.

此时的f只要任意一组满足C的数列就行了.
而这样的数列可以在排序过程中构建.

如果S是不确定的呢?

这样的S可以分开为一个确定的集合S_0和一个非确定的集合S_u.
确定的部分如上构建.

S_u的元素可以是S_0中相邻gap之间的任意一个数.
因为未知的S_u的元素必然是在S_0的L(S_0)+1的区间内.

于是未知元素的问题就是对于这几个区间归属的概率问题.

实际上,如果这个f确实存在,且是严格有序的.
那么新元素的问题实际上是一个插入问题.

所以f_u实际上是一个关于f的插入生成.

如果f不存在呢?

考虑S都是可比较的情况.

f不存在以图视角看待的话,S的路径存在回环.

因为如果不存在的回环的话,意味着元素都存在单向路径.
也就是存在严格的有序状态.

那么一个近似的解自然就是切断回环路径.

这样的话,主要就是图的partition问题了.

但这可能没有一个很好的方式去估算?
因为实际上这个图是fully connected的.
每一条边的移除都可能影响每一对节点的最短路径开销.

所以可能更实际的方式是做子图划分.
以期望得到的子图是符合预期的.

尽管同样地,似乎这种划分也不见得就有一个很好的代价衡量方式.

2019-07-21

自生长的动物园

微博timeline上看到这么句评论:
"不是,我们听周杰伦被嘲笑的时候,那些嘲笑的人还在听伟光正呢"

这是个蛮有趣的角度.

这一代人在成长的时候可能也没少冲突过.
最明显的就是当初对于韩寒的各种评价和所谓80后的各种stereotype.
只不过冲突的媒体平台是在纸媒和广播电视.

而现在的刷周杰伦,与其是说周杰伦不如是目标的蔡徐坤.
因为实际上一致存在的行为群体是蔡的粉丝团,以及其固有的榜单行为.

80后的这波行为更多地像是一种对既有话语权威的一种可能是最后宣誓主权.
或者说挣扎.

就像上一代对80后的批判攻击一样.
80后对后代的这种冲突也是基于他们自己构建的互联网社交平台之上的.

某种程度上来说,每一代人都在构建属于自己特色的一种交流沟通媒介.
而每一代的下一代都在这个媒介上或创新或颠覆出自由独有的文化圈子.

两者的冲突可能更像是一种意识形态上的冲突.

如果把时间拉回几年,从贾君鹏开始.
对比现在这场狂欢性质的群体行为的话,其实算是一种复刻的行为.

一种无厘头的群体式的兴奋与模仿.

它产生的是一种自发的,带有莫名激励性的一种传播扩散方式.
本身并没有很明确的功利性的目的.
甚至于从根本上来说,这是一种随机性很强的娱乐方式.

你知道它产生的特点和要素.
但并不一定能够体量级地工业化复制.

所以在80后打造这这个互联网社会里,这种被成为现象级的群体行为被赋予了一种mysterious的性质.
靠广告流量腾挪借力出来的互联网经济模式对于这种大范围的自发性参与有着天然的向往和需求.

而在这10几年间,流量/规模几乎是互联网社会所有商业模式的基础.

也因为此才有了数据驱动的运营方式.
作为一种简洁直观,有时候确实高效的衡量方式.

本质上来说,刷数据这一套游戏规则就是80后自己创造和鼓励出来了.
而稍显讽刺的是,被大规模应用的实际场景却并不是80后自己的偶像/娱乐需求.

就像最初那句一样.
周杰伦的数据并不好看.

这是在80后自己缔造的规则上成长起来的用户的一种常识.
是他们用于评论和衡量一个明星或者更宽泛的,一件事情价值的最原始最直观的本能反应.

恰恰是这点,作为的规则创造者的80后却反而认为是有违常规的,不合逻辑的.

就像当初韩寒退学走自己认为对的道路一样.
独立自主和你应该如何之间的意识形态的矛盾.

所以这场冲突的吊诡点就在于.
规则缔造者本身对于规则的自然执行者间会有如此对立矛盾的立场.

或者说,形式上地,规则对于最初的制定者来说已经失控到他们自己无法接受或者说适应的情况了.

又或者说,文化的演变到现在其实是一种不可避免会有冲突的地步.
因为互联网本身的出现使得任意两点之间的交流成为可能.

就像以前贴吧的各种亚文化圈子.
它们可能甚至不能被主流接受,或者说根本不被主流道德所容忍.
但是从观察的角度来说,确确实实有着数量不少的同类人.

一个可能更明显但在今天来说稍显不太合时宜的例子就是ACG/二次元圈子.

这个本来是一个非主流的文化元素.
但是放在今天来说,已经可能说是主流的一部分了.

甚至于从趋势上来说,更多的商业投入是倾向于这种新开发的文化领域的.

背后的逻辑可能各种各样.
但至少,这个本来亚文化的圈子逐渐成为社会中坚力量的时候.
文化的代次更迭让曾经的非主流变为常态应该也是其中一个因素.

所以粉丝刷榜单刷流量,从这种分类思路上来说,无非就是另外一种新生的亚文化圈子.

所不同的是,它作为一个非当前主流的典型被拉出来做了对比样本.
而从发展的角度来说,可能更说明这个群体正在成为一种主流文化的冲击和替补因素.

因为从结果上来说,这场文化上的冲突狂欢并没有显示出一方的压倒性的胜利.

这里可能必须承认的就是,也许80后认为这种刷榜单刷流量的行为并不怎么正确.
但事实上执行这一种价值观和行为准则的人并不能算是一个社会的小规模群体.

而且更重要的是,这种结果多多少少是80后自己一手造就的.

至于对不对,就是一个相对复杂的问题了.

刷话题刷榜单可能并不比参加演唱会买专辑来得又道德负罪性.
本质上是一种个体所能承受/付出范围内的一种方式表达.

甚至于打榜本身并不算是一个新的运营概念.

那么这种排斥感的根源是什么呢?

从结果上来说,流量明星吸收了更多的文娱资源.
这个是主动的也是被动的过程.

在给定一个相对静态固定的文娱投入的前提下.
一方的倾斜也就意味着另一方的退让.

从市场的表现上来说就是文化符号的次代更迭带来的不适应感.

因为目之所及的商业目标是一个更为新兴的消费群体.
是一个有异于自身的一个文化载体/社群.

所以说,这可能更像一种困兽之斗.

而讽刺的是,制造这种指标性牢笼的人,正好是其自身.

宛如一个自生长的动物园.





2019-06-23

谈谈Libra

考虑下电商平台的折扣优惠券.

一件商品价格为P.
用户在购买时平台提供折扣抵用D.

那么用户实际的付出就是P-D.

这时候跟商家结算的时候就存在一个差值D.

而如果平台把D以广告流量折扣券的方式跟商家结算的话.
那么实际上商家手上持有的就是现金P-D和价值D的广告消费券.

也即是说名义价格P的交易,实际上真正参与流通的现金之后P-D.

如果换个角度.
把D看作是买家的存款利率,卖家的贷款利率.

那么上述行为就可以看作是.
在期初卖家贷款以利率D生产价值为P的商品.
然后买家在期末以本金P-D利息D的存款购买商品.
而平台就作为发钞/产生信用的央行.

然后把它跟Libra和其他crypto currency的监管问题放一起看.

Libra所谓监管问题的点在于所谓的发钞权.
以及以此为由的所谓的对央行权威性的威胁.

而实际上能产生信用的,跟是不是Libra或者是不是央行其实关系并不大.
而且也并不是说能产生信用的,就是央行所排斥的.

央行排斥的是对于货币政策干涉手段有效性的影响工具.

之前看到有个关于负利率的文章.
观点就是建立一套非现金的货币体系作为现金货币体系的补充.

因为在负利率前提下,可以通过持有现金规避负利率的调控影响.
而如果是电子货币的话,实际上就不存在这种形式上推出流通管制的可能.

所以Libra的问题在于,在给定各国货币政策的前提下,它会不会有所反应.

按照白皮书的说法是一种一揽子锚定的形式.

而关于它的可靠性/可控/可信程度,可能更形象的比喻就是当前的人民币.

这样的话,对于央行来说,Libra不过就是一个汇率问题.
而且某种程度上来说,可能更受央行的欢迎.

至少可以作为一种负利率的实施工具.

以及就当前crypto currency标配的gas概念来说,就是更为直观和细致的一个交易费用手段.

因为当前的利率控制手段的传导终端因为复杂性,多数也只能从银行间业务作为触发起始.
并不能直接地渗透到每一笔单独的交易当中.

而gas的则是一种更直观且更微观的一种手段.

且因为blockchain本身的匿名性或者说分布式形态,这种调控可能更为不易察觉/有效.

那么Libra的问题是什么.

因为目前来说,像Brave有所谓BAT(Basic Attention Token)的概念.
这个延伸下就是一个简单的量化程度的问题.

就目前的广告模式或者说互联网的盈利模式来说.
Libra可以把每一个动作和行为都量化为一个直接的coin/token价值.
对于content creator或者广告商来说,可以有实时且准确细致的消费收入明细.

这个的潜在问题就类似于SEo的问题.

要么或者即使跟Gooogle一样,把每一个行为的量化方式做得难以逆向.
但是从技术和数据上来说,不是不存在被game的可能.

这个可能还不是个太大的问题.
因为反欺诈/anti flaw并不算是一个可选的东西.

它的问题在于内容创造者和广告上对于最大化收益的一种动机.

因为它能够有办法知道如何去做能够最有效地获得收入.
或者更有效率地获得收入.

固然,这个可能是以更优化内容/更精准的targeting来做到.
但也并不能否认会往一个更坏的方向靠拢.

而从目前的所见来说.
可能后者会是个更可能的事情.

当然,这算不上是Libra的问题.
可能特定地对Libra的问题在于Facebook本身.

至于非特定Libra的问题,或者说Libra们的问题就是.
可能不是人人都能使用,而是人人都能发行.

2019-06-03

关于Ceph的CRUSH算法

考虑crush map的bucket选择.

对于一个obejct o,choose的时候需要经过一个hash过程得到一个pseudo random的id x.
也就是对于任何一种bucket 类型,有
x = bucket_hash(o).

假定bucket的长度为n,x的放置位置为y的话.
bucket specific的choose policy为p.
有y=p(x)

对于uniform bucket来说,这个p为
y=p_uniform(x) = x % n

除了uniform的bucket之外,其他bucket type都是有weight权重的.
同样,记录位置w_i为位置i的用权重值,且有0<=i1的prod替换的sum.

也就是,这里的straw其实是一个权重放大倍数比list高得多的一个进阶版本.
而且跟list不同的是,它的argmax没有< w_j的条件限定.
因此它的寻址复杂度是O(n)的.
而list因为条件限定的情况,实际平均表现最差也只是跟straw一致.

在考虑现在ceph的默认policy,steaw2.
这里对hash做个额外的限定,0
这个主要是ceph的实现里有个lookup table的优化.
给定0
所以实际上starw2的hash是一个到[0,1]区间的一个mapping.
对应的log(k)取值区间大概是[-11,0].

所以这里简单重定义-11<=hash(x)<=0

y=p_straw2(x) = argmax(\{j; hash(x)/w_j \})

这里可以看出,只要bucket item的权重不变.节点增减的变化只由argmax的骨架部分决定.
这个跟list也有点类似,但是它是位置无关的.
不像list有对于左右有相对确定的基础cost估计.

但也因为位置无关,所以它存在一些极端情况.

对于节点减少的话,则所有argmax为这个节点的数据都会受影响.
这个是符合intuition的.

对于增加节点,argmax的max value可能都指向变动的那个节点.
这样的极端情况就是造成整体数据的挪动.

但是由于w_j的存在,这个也是可干涉/存在可控性的.

而对于节点数量不变,只是权重改变的情况.
跟节点增加类似.

所以,straw2的基本上算是忠实指向w_j的.

然后考虑hash.

由于hash会对x走一个log的重新分布.
所以实际上考虑的数据分布性质的话,只需要考虑log分布之后的就行了.

也就是在大概[-11,0]的区间内的数据分布问题.

把w_j作为一个tuning parameter/placement parameter考虑的话.
那么理论上,针对现有的实际数据分布是可以做到人工精确干涉的.

而且这么考虑的话,其实starw2的计算也并不需要搞那么复杂.

因为归根到底还是通过w_j来控制的.

2019-05-14

变化

美股作出反映大概是在谈判破裂确定之时.

那么假设大家都是rational的话,一个方向的确定就说明了一个不确定性或者至少两个可能存在的消失.

这两个可能无非是继续谈和谈不了.

既定的谈不了的结果是slump的话,那么另外一个方向自然就是非slump的.
也就是继续negotiate的话,经济趋势是有可能持平或者向上的.

那么加征关税为什么会意味着中短期美国经济会有不愉快呢.
或者说为什么这次会这么敏感.

毕竟这并不是第一次.
以及如果确实因为关税原因存在不确定性的话,市场总会在前期会有分歧波动的.

考虑下现在headline的关注点和方向.

一个是影响面的数据/描述.
这不是新的内容.

一个是关于选举方向的.
这个可能就是impact factor.

作为选举双方来说,差异性的存在所引导的方向多少是需要有不同的.
大多数时候来说都是简单独立的.

那么理论上就应该是贸易和反贸易的立场.

因为立场的不同导致的对贸易情况的走向具有的不确定性可能才是市场犹豫的点.

而现在选择了方向的话,那也就是说这个分歧点/不确定性可能不存在的.

那么这样的话,就貌似合理解释了.

对于川普来说,提高关税和拒绝应该都是在合理的结果预测行为序列中的.
但是可能意外的市场和对手的行动选择可能算是意料外的.

所以市场的不良反应对于一直以来树立的政策倾向来说,造成的选举影响可能一下子就负面了.

某种程度上来说,这是一个trap.

而对手选择贸易冲突这个路线展开的一个期望就是同样的对中国贸易的依赖减少趋势.

考虑目前的攻击点来说,主要就是制造业和农业的回归或者说复兴.

所以至少在这一点上,方向应该是不会有太大差异了的.

国际贸易基于的是广义的成本考虑,不管是狭义的生产制造成本,还是从长期的供应链流程来说.
结果导向的都是最终成本的减少/利润率的提升.

因为是整个产业链条的优化选择,那么对应的自然而然的是paradigm shift.

单纯的贸易成本对冲应该是不能够覆盖整个贸易冲突面的.
所以,产业流向和分布的重新组织再结构几乎是必然的.

而考虑到体量的问题,这个基本上也是全球性范围的一次调整.

考虑到目前的技术普及水平和人工成本,美国要短时间内补全和对冲完影响的话,也不是很容易的事情.
但是考虑的机械化程度和相对宽松有利的民间私营经济环境,通过技术手段来补足应该是可以预见的.

所以某种程度上来说,可能只是个长痛不如短痛的被动革新过程.

把同样的时间和尺度范围放到大洋彼岸来看的话.
可能结果就没那么乐观了.

诚然目前依然是一个制造中枢.
但是从中国制造的蓝图本身看的话,倡导向高端制造业转型imply的就是目前主要还是中低端制造业为主.
而这个的另外一个消息面是向其他新兴发展中国家转移.

这个产业转移可能不是一个短期内能完成的事,尤其考虑到新兴国家本身产业和政治生态的一些问题.
但也不是说不可能.
而且也并不一定还需要,正如技术发展的革新一样.

第二个是国内本身的可能略显利己和投机的社会氛围.
像目前的一些热点方向本身可能并不是太有利于社会的发展以及更重要的,有相对可靠合理的长期盈利模式.

虽然陆续有相关的动作和政策去做一些规范和限制.

但对应的,也是社会经济文化更方面的更趋管制和指导方向明确的现状.

这也就意味着实际上的是一个国家计划指导的全面的发展策略.
imply的可能就是有更多的方向性死亡的出现.

另外一点就是在总体budget有限的情况下,要做到社会效用最大化的话.
可能扶植和倾向的方式方法也会更不太利于规模小的公司和产业个人.

毕竟在确保资源和资质的尽可能充分兑现的前提下,门槛相对可能会比较高.
从执行的角度和执行层次的深度以及基层终端执行素质来说,提高门槛可能是成本最低最容易实现的一个方式.

像如果重点是第一二产业的话,那么作为文娱服务主要的第三产业可能就没那么大的权重了.

但至少这样才有所谓的共克时艰.

不然失去的可能就不单单是十年了.



2019-04-14

谈谈软件工程

考虑人的工作产出为x,时间为t,对应需要支付的成本为s.
那么一个profit=x*t-s

如果令s的支出跟t简单相关则有
profit=(x-c)*t.

简单地,所谓的剩余价值约束工作时长.

这里有两个隐含假设.
一个是x是恒定的,也就是单位时间贡献不浮动.
而是s跟t线性相关.

也就是这里收益和成本都是简单线性描述.

考虑x为一个带一定衰减的函数.
比如X(t) = W*(1-e^-t).
一个bounded by W且随时间增长效率递减的函数.

那么profit=\int_{0}^{t} W*(1-e^{-t})dt - c*t
->
profit=t+e^-t+R-c*t
->
profit=e^(-t) + (c+1)*t + R

如果以天为周期小时为单位计量的话.
大致回报也是线性的.

一般地来说,在给定的时间范围内,只要X的derivative为正的话.
也即是时间计量的margin为正.
那么incentive就自然会是增加时长.

那么如何构造在一定时长后margin为负的情况呢?

最简单的负值构造自然是线性的.
对应的就是抛物线.
即X(t)=a*t^2+b
->
profit=a*t^2+b - s*t
->
profit=W(c-t)^2 + d

在这种情况下才可能存在给定某个工作时长为最优解形式.
如果是存在最大值的话,那么应该有W>0

也就是这个X应该是一个会在某个时间点之后incur performance degrade的曲线.
这不算是一个不现实的约束.

其他的形式呢?

考虑相对一般的形态.
profit=return(t) - cost(t)
或者
profit=\int return(t) - \int cost(t)
对应的return和cost曲线的对t的integral差异.
即投入和成本曲线的差额.

对于单个个体来说,如果需要maximize profit/on return的话.
相对stable的IC曲线应该是会让问题相对简单的.

这就需要每个人的投入产出以及对应的成本是相对可计量/具有统计意义的.

大多数情况下个人的cost是相对可预测/固定的.
所以这个求解的关键在于个人的time investment return的模式问题.

只要产出模型是有正margin的,那么单纯延长时间是没问题的.

比较麻烦的是那些曲线比较复杂,或者根本不连续甚至在一定周期尺度下具有随即性质的.
这种可能是根本没有明确的解析解的.

从群体尺度来说的话.

在数量到达一定程度的时候,个体的模式浮动性特征是比较容易被表征出来的.
也就是说,到达一定规模之后,理论上来说是可以规约到某一种特定的产出模式上作为当个个体求解的.

但是也并不是就一定存在解.

因为形式上来说,解的存在性和形态取决于产出模式.

那么软件工程是或者说应该是什么样的产出模式呢?

可能软件工程这个提法本身就是比较微妙的.

记得上学的时候就有各种CMMI/敏捷/测试/设计模式等方面的各种宏观架构.
各种方法论解构下来不过就是拆解.

背后的逻辑不过就是把不可控控制在一个认为可控/bounded的范围内.

它可能笑起来像金融的risk control/estimate.
但是至少金融有一套稍微能跑起来自洽解释的计量和数值系统.

而软件工程理论是不具有这些特征的.
最后无论以什么方式拆解出来的方案/步骤/方案,最后指向的是一个单一的计量标准.
也就是时间.

是的,金融方面也不过最后会量化为交易价值.

但两者的不同在于,时间的定量本身是未定义.
或者说没有标准的.

就像敏捷提出来优与瀑布或者更传统的软件开发模式的时候.
一个论点就是拆解的时间单元比对方更小,从而更flexible,更能应对各种可能发生的情况.

至少在这个陈述里面,它没有回避说软件开发的难点在于 各种可能发生的情况 这种风险.
但是逻辑上却微妙地归结到更小而短的周期能够让这种风险的发生几率更低.

那么如果这个观点如果是对的话,imply的就是软件开发的风险在与周期长.

这样就实际上陷入了一种递归指责.
或者说是一个逻辑陷阱.

在没有办法定量指出风险的具体含义的时候,提出了解决风险的方式.

所以,能实施成功的话,也只是因为刚好恰当地风险主要因素确实是时间.

那么,软件工程的风险到底是指什么呢?

可能在于软件工程这个提法本身.

coding本身有所谓的工程化的么?

或者说工程化本身的含义是什么.

一般的工程化可能跟接近于科学的定义.
即是一种能够量化衡量的可重复实验/过程.

coding本身是不太具有量化标准的.
就像文章或者绘画.

即使以统计的角度来说,量化能覆盖的也不过是风格上的问题.

但是完全没有能够bound的东西也不尽然.
至少API/protocol算是一种.

但是这是在integrate阶段的.
这个时候才会有简单的satisfied or not.

所以如果软件工程如果说存在的话.
也应该指示的是在delivering service过程中的这些隼合情况.

实际上,这些理论上是包含在automation里的.
包括compile/build/test/deploy基本都是不需要也不应该由人去干涉的.
而是根据各个节点的specifications来judge的.

再回头看那些工具和方法论.

那么当所谓risk出现的时候,大致就是各个pipeline stage的合规情况出现问题.
这时候这些理论是怎么解决这些问题的呢?

并没有.

或者说也有.

因为在这些理论框架下需要满足的constrain是时间.
如果把它作为所有risk的一个proxy来看待的话.
由于这些工具所处理和解决的都是在满足time bounded的前提.
于是在proxy回实际的处理方案的时候,关注点也通常在如何回避对时间的default.

于是实际执行上,如果build或者test或者deploy或者任意阶段出现问题.
那么可能的做法就是直接抛弃约定,做default处理.

所以这里的核心矛盾就在于.
或者说一个简单的模型描述就是.

给定一定的time resources.
以及一组random generated的consumer.
如何用limited的resource去satisfy的问题.

而这个是无所谓解的.

除非是能够bound consumer.
要么有一定的确定可预测的范围,要么具有某种可描述的模式.

所以,归根到底还是know your issue.









2019-04-06

由铁路售票想起

候车的时候想了个问题.

其实列车售票是一个segment的allocation问题.

给定一条线路{s_0,s_1,...,s_n}.
一个从A->B的请求实际上是某个{[s_i,s_j]; 0<=i 且每一个s_i有对应的一个quota,q_i表示可allocate的数量.

那么一个naive的approach就是做一个atomic的能rollback的transaction,做一个decrease.
这样的话,在q_i <<< concurrent_request,远小于并发请求数的时候.
在给定collision分布的情况下,某些q_i就不停地<0导致transaction rollback,从而造成一个failed allocation.

考虑一个稍微简单的定义.
给定一个sequence或者whatever,{s_i;s_i=0 or s_i=1}
也就是这个离散连续区间的值为0或者1.
或者说,这条线路各站余票只有0或者1两种情况.

对于一个allocation request,a_i_j,则要求的是.
sum_i_j s_i = j-i+1,即使i,j区间均为1.

而一组concurrent request则可以认为给定一组a,求一个satisfied的allocation subset.

这个有点类似有冲突的广告bid.
或者所谓的背包算法还是什么?

考虑optimized的目标是让是个subset尽可能地大.
或者说有尽可能多的request被满足.

那么这个最优解怎么求呢.

从最大或者最小的span开始allocate是不行的.
因为很容易构造一个反例,使人如果这个最优解存在,这种策略是不work的.

考虑对non-overlay的span一次allocation.
这是一个not necessary optimal的solution.
因为没有conflict.

考虑这个allocation set中的某个请求r,存在另一个range conflict的请求r_c.

当r_c的span是r的一个子集的时候,用r_c替换r是可以improve的.
因为此时r_c release原来r range的某些slot.
这使得这些slot有可能被更多的请求allocate到,从而增大了allocation set.

如果反过来的r_c是r的一个super set的话,那么同理,是不能improve的.

考虑只是partial overlay的情况.

令L_r为r的长度,L_r_c为r_c的长度.

那么在把r剔除之后的空出来的长度L至少会是L_r + L_r_c - 1.
不然的话,r和r_c能够同时fill整个range,不会有overlay.

于是对于r的improve就递归为这个L区间的optimal solution了.

则当最终converge的时候,也就是对于当前solution的所有r,都找不到任何improve的时候.

这个是最优解么?
还是说只是一个local minimal?

应该说只是一个local minimal.
因为本质上这是个step one的back search.
存在且容易构造如果回退两步能fill 3个request的情况.

而回退两步能产生更优解的原因应该是在于有了更多的continual的space.

所以可能first fill的时候,应该以保持尽可地避免fragment?

于是理想的做法应该是优先给予线路两侧的短途?







2019-03-16

关于锁的一点想法

考虑namenode或者某种rpc service队列.

假设有k个处理线程,每个请求处理时间是r的话.
则有t时间内的throughput T=k*r.

如果每个请求会收到一个global/share lock或者之类的互斥影响的话.
那么单个请求的开销r应该增加一个extra cost c.
即T=k*(r+c).

对于锁竞争之类的,cost c通常不会是一个常数.
考虑存在一个概率p能描述这个dynamic的话.
即c=p(c)

则每个请求的开销为r+p(c).
考虑有n个请求的话,那么在并行k的情况下.
每个线程处理m_i个请求,则该线程处理时长为\sum_{m_i} r+p(c).
->
cost of thread m_i = r*m_i + \sum p(c).

其中有n=\sum_k m_i即所有线程的处理请求总数加和为n.

当each m_i sufficient large的情况下,
cost of thread m_i ~ r*m_i + m_i*mean(p(c)).
即竞争带来的dynamic cost趋向于它的期望.

考虑线程处理是work stealing的策略的话.
那么并行带来的处理时长应该是每条线程差不多.

因为考虑只有两条线程的情况.
其中a跑了一个task,那么另外一条b要么跑comparable的task,要么lighter,或者heavier.
如果是lither的话,那么b将先完成,并抢先执行下一个.
这时等价于将a的当前task的cost减去b的task的开销,重置回假设初始.
而如若是heavier的话,交换a b即可.

对于k>=2的情况可以将划分为logical两条线程divide and conquer.

于是在这种情况下每条线程都是equality comparable cost的.
而任意一条在m_i sufficient large的情况下有
cost=r*m_i + m_i*mean(p(c))
->
per request cost=r+mean(p(c))

在p(c) dominate r的情况下.
比如在lock contention的情况下,process cost << wait lock. 实际请求开销小于锁竞争的情况下. 那么throuthput ~ mean(p(c))的. 那么考虑p的实际分布可能的形式. 以读写锁为例. 请求require read lock的概率为p,write lock的概率为1-p. 有k个线程竞争. 则,request read lock的情况. 当,all read lock的概率为p^k 因为shareable,所以cost=(p^k)*0 = 0 at least one write lock的概率为1-p^k. 如果获得锁,则有cost=0. 未获得锁的话,存在另外一个描述lcurrl,lock cost under read request lose. 即cost=(1-p^k) * (lcurrl) 请求为write lock的情况下,且获得的情况不论概率,其cost为零. 获取失败的情况下,存在yet another描述,lcuwrl,lock cost under write request lose. 那么mean cost=(p) * ((1-p^k) * (lcurrl)) + (1-p)*lcuwrl. ->lcurrl*p - lcurrl*p^(k+1) + lcuwrl - p*lcuwrl
->(lcurrl-lcuwrl)*p + lcuwrl - lcurrl*p^(k+1)

由于lcurrl和lcuwrl都是在给定p下的某个分布的mean值.
所以对于给定的p,有
(lcurrl-lcuwrl)*p + lcuwrl - lcurrl*p^(k+1)
->
mean cost = a*p^(k+1) + b
其中,a>0,1>=p>=0,k>0,b>0

当p->0的时候,或者k越来越大的话,mean cost -> b -> lcuwrl.
即lock cost under write request lose.
也即写锁竞争失败之后的expected cost.

如果锁是fair的.
那么设计上来说,每个线程得到的几率都是对等的.
于是随着k的增加,lcuwrl也会相应增加.
因为稀释.

而如果是non-fair的,则依赖于具体实现了.

2019-03-12

快消社会

今天看到条消息,是F5收购Nginx.
这好像已经不知道是第几个知名重要的开源软件最终被收编的故事了.

也不能说被收编之后nginx会怎么样.
只是总有种一个时代过去了的感觉.

想到月底Google+也要关闭了.
可能有点什么能说的.

哀叹互联网从开放进取到现在的逐渐封闭,似乎也是个没什么太有意义的话题.
不过难免的总会有一点凄凉感.

互联网能走到今天,大概也是因为这种开放的唾手可得感.
开始的信息都是只有你想不想获取,大抵是没有获取不到的.

至少相对于今天的各种paywall和不可索引/内网黑洞来说,是几乎没有什么门槛的.

而现在,不论是国内外,都趋向于各种封闭不可或者难以延伸的圈子.
或者说用户很难自我发现的一个状况.

前段时间,reddit上有个culture war subreddit关闭的事情.

大概背景就是,这个subreddit如其名,可能是有各种比较激进或者非主流甚至有些反社会的内容.
里面会有一些和平非和平理性非理性的讨论.
维护者称之为national conversation.
大概可以称之为一种比较真正意义上的公开性的讨论.

一方面是因为troll,一个社区庞大之后的无可避免的被无法融合的外来文化冲突.
另一方面是作者自身的一些反思.

也就是moderate的一切正确性/正义性.

用一种可能比较容易理解的话来说就是审查/审核的边界线.

社区维护者或者更泛化地来说,每个人都有自己各自的立场和观点.
那么在判断一个东西是否普适或者符合某种社会道德规范的标准也就实质上的因人而异.

所以什么内容是对什么内容是错,这个本身就不太可能有一个完美的解释.

在这种情况下的审核或者说过滤就天生地容易引发内容之外的矛盾冲突.

有时候就是所谓的网络暴力.

这就是说,在开放性的同时,本身对于一部分人来说,这就是错的.

或者说,开放性的最后演化方向可能几乎必然是走向封闭.
或者说失败的.
因为开放并不代表着能包容全部,以及被任意包容.

Google+当初是个很有意思的几乎是社会实验性质的设计.
它的input/output信息流都是用户可以控制的.

有点类似今天的朋友圈,你可以选择只看哪些人的信息流,也可以控制你的信息流能被哪些人看见.
最关键的是,这两点都是高度自由可选的.

但是这种技术或者说产品设计上的优越性并没有让Google+成为一个成功的产品.
甚至于某种程度上因此失败的原因.

Google最初被人诟病的理由之一跟buzz类似,是过于结合Gmail/Google产品,使人没有一种社交安全感.

这是一个技术和人性的冲突性伪命题.
因为本质上来说,用户对信息流的流向是完全可控的.

但是依然令人不安的原因根本上来说并不在于能不能控制信息流向.
而在于这些信息被人看到后其他人的反应符不符合自身的预期.

也就是说,这种不安感实际上来自于那种对不预期结果的不可撤回干涉性.

这就像有些聊天工具的撤回功能一样.
本质上来说,它并会改变别人已经看到接收的事实.
但是,因为可撤销性给予了一种可挽回可弥补不预期结果的一种可能性.

尽管很多时候是一种假性安慰.

因此对于大多数人来说,这并不会让人觉得Google+的这种设计有安全感.
也自然不太可能有大而普遍的UGC产生.

这是关于outbound的一方面.

另一方面是所谓的鬼城问题.

实际上,Google+可能有些不算小的活跃圈子.
知道的可能就是一些ACG内容的.

里面会有一些很紧密的闭合关系.
而且由于Google+本身的circle的设计,可能会有二层或者三层的private circle存在.

类比的话就类似微信或者其他IM的群组功能.
在基于组员clsoed对外不可见的情况.

这在某种程度上印证了开放社会是不太可能长久存在的.

因为这些private circle的存在或者说建立的理由大致有几个.
一个是回避杜绝某些话题.
一个是基于封闭关系链的安全感.
一个是某种程度的优越性集体意识.

这些是一种有意识的分裂且不太可逆的过程.
加上echo chamber的作用,除了本身内部存在矛盾分裂的时候,是很少会出现在开放空间的.

所以,像Google+这种社会实验表明,大体上来说,开放空间本身是不太可能存在的.
因为其反人性的一些问题.

而像culture war的问题则说明,即便有幸地在某个阶段能沉淀出一个比较合适的社区共识.
但是维持这种共识的不变性和健康性也是一个未知数.

这点也是很多BBS走向衰落的一个因素.

对于那些相对长青的社区来说,无一例外地算是有很好的某种程度的文化传承.
一个例子就是S1.

一个可能不太好但却从另一个层面说明问题的可能就是知乎.
尤以谢邀之类梗为重.

它反映的对外的stereotype,某种程度上是来源于社区理受相当部分用户欢迎和关注的内容.
也即是一种用户文化的传承或者说侵略对抗的结果.

一个社区的存在,在这个层面上来说,是依赖于主要用户的一种文化气质的.

也即是说,一个社会的氛围形式是如何,相当程度上是受之中的大多数人所左右形成的.

那么,回到互联网的封闭倾向问题上来说.
可能也是基于同样的理由.

RSS类开放社会的消亡,开源软件的商业化服务化,software infrastructure的便利化黑盒化.
可能都算是一种自然选择.

毕竟,可能快消社会?

2019-01-13

毕竟人类

考虑一种调用风格.

Promise.costly(()->receive())
.transform((packet)-> mmap.transferFrom(packet))
.sidekick(()->logging.info("saved"))
.catching((exception)->logging.error("save fail",exception))
.addListener((channel)->channel.close())

这里大致是对CompletableFutre和guava对ListeningFuture的一些包装.
稍微链式了一下,以及改动了点语义.

大致涵盖的几个data flow是.
一个正常情况下的receive packet -> save -> close.
一个sidekick是在正常receive之后的并行log部分.
一个是receive exception情况下的catching部分.
以及不管是正常还是异常情况下都并行触发的addListener部分.

最终返回的reference的value是跟transform返回的签名一致.
也就是除了transform,其他都是旁路性质.

这点跟completable是不太一样的.
虽然底层实际用的就是completable future.

这么做的原因主要是不想总是try catch.
或者像go一样检查返回值.

而且为了简单,lambda的声明都是带throw的对应的functional的版本.

所以实现上是把最初的exception一路propagate过来的.
这点跟completable/listening都算一致的.

问题主要是这个compute graph的trigger或者说traversal方式.
或者说transform这些callback的调用应该是同步还是异步的问题.

因为底层实际上就是Comp了table future.
所以实际上就是thenApply之类的调用的.

如果同步的话,实现上是会当场back trace的.

也就是当一个这个graph当中的一个stage完结之后会尝试看依赖项目是否也是可以执行.

这里的一个好处就是execution path可能尽可能地总体时间短.
因为基本上算是instant的.

这样的话,几率上来说对cache可能也会有点好处.

但这样的话为什么不直接写成正常的平坦的workflow呢.
而且可以没有那些基本的代价开销.

一个理由可能就是整体流程比较长.
或者存在一些不太确定的blcoking的部分.
所以通过这种人工的方式拆分出time slice.

某种程度上来说跟go的goroutine/chan/syscall调用时候隐切换是类似思路.
通过一种人为的软调度去提高throughput.

但是同时带来的一个问题就是可能latency相对会高一些.
因为是每个execution context的slice都会被切分并在不同的实际被queue或者stack.

所以,即使是说用async的方式处理stage.
但同样地还有是用first in first out还是last in first out的形式.

像Stream API的parallel使用的common pool就是forkjoin pool的last in first out.

这个在某种程度上来说是兼顾througput和latency的一个选择.
毕竟stack的距离可能没有queue的距离来得远,每个切换的数据访问的差异可能相对没那么大.

至少意图上来说,是有一定的cache friendly的.

但是这里同样会有个问题.

比如
LongStream.range(0,regions).paralle()
.mapToObject((region)->file.map(region))
.flatmap((region)->region.pages())
.map((page)->crc.update(page))
.collect()
这类flatmap的stream generation.

可能隐式地来说,会有一个形式上的synchronize point.
因为pipeline的某个节点是generator,而generate的动作可能又是有一定开销的.
比如这里的mmap,基本上手受限于磁盘的.

这样的话forkjoin thread的local queue/stack就应该都是这些相对比较耗时的task.

也就是说,对于其他task来说,除了enqueue/dequeue和queue work load的影响之外.
还收到来自未来的运行时的不预期的一些开销因素.

所以相对来说,LIFO的不确定性比较高.

另外一点就是对于原生Future这类从设计一开始就没有考虑callback的wrap方式.

guava的actor暴露的是一个ListenInPool的选择.
也就是扔到一个你提供的线程池里blocking get,然后再回调.

在实现的时候开始也采用了类似的做法.
类似Promise.costly就是在一个cache thread pool.
而对应的Promise.light才是在一个forkjoin pool里.

一个不太好的情况就是类似之前go的syscall造成的大量thread的问题.

把future listen在一个cache thread pool的问题就是可能某个瞬间产生大量future的话,会意外地尝试非常多的thread.

当然,一个思路就是限制thread数量.
但是引入cache pool的原因就是想避免一些意外bug或者intended的不会返回的future耗尽thread的问题.

折中的办法是先把future queue起来.
然后类似早期go的net poller,定期的poll遍历touch一下.

代价就是有额外的这个poll的delay.

另外一个模仿点就是timeout.
基本上就是select timeout channel的future形式.
scheudle一个delay的future cancle.

可能本质上来说,就是在各种模仿.

毕竟人类.

聊聊卡布里尼

最近看了部片叫卡布里尼,算是可能这段时间来比较有意思的一部电影. 故事也不算复杂,就是一个意大利修女去美国传教,建立慈善性质医院的故事. 某种程度上来说,也很一般的西方普世价值主旋律. 但是如果换一套叙事手法,比如共产国际的社会主义革命建立无产阶级广厦千万间的角度来看的话,也不是...