2021-07-10

关于Go的一些相对优势

最近用Go重写了之前基于Envoy的一个东西.

性能从原来的32 CPU 20w+ 18ms latency变成40 CPU 40w+ 10ms.

这个结果初看没什么可比性.
但是拆分起来还是可以谈一谈的.

Envoy的版本大概就是到32 CPU的时候就上不去了.
也就是说之后的性能并不随着CPU资源的增加而scale.

这个之前略微谈过.

大致模型就是:
Time = sys_cost + read_fd*(read_bytes*cost_per_read_byte) + write_fd*(write_bytes*cost_per_write_byte).
sys_cost是固有的eventloop的开销.

后两项是抽象的读写每字节对应的动态抽象成本.

说是抽象的原因是考虑到实际的业务场景每请求的处理开销/代价是不太一样的.
所以规约到一个字节角度的动态参数化类函数描述.

然后假设K个eventloop之后的一部分请求能够得到响应.

也就是会有
latency = K*Time = K*( sys_cost + read_fd*(read_bytes*cost_per_read_byte) + write_fd*(write_bytes*cost_per_write_byte)) / N
->
a*sys_cost + b*N*cost_per_read_byte +c*N*cost_per_write_byte

因为cost都是某种特定场景下的常数.
所以最后可以规约为
latency = const_cost + N*cost_per_hybrid_byte

所以当小于32 CPU的时候,随着CPU增加,每个CPU需要处理的N变小,所以会随着scaleup.
而当>32 CPU的时候,后一项已经significantly小于,const_cost了,所以继续增加并不能有什么改善.

所以这是它的一个缺陷或者说应用场景考虑.

而Go由于runtime的关系,模型会有一些比较不一样的地方.

因为它的IO和channel/mutex等操作会触发groutine等调度.
从逻辑上保证P是burning cpu in the right way.

也就是说,当有类似操作的时候,go会让专门的线程(netpoller/sysmon等)去做blocking的工作,而让M继续执行runtime user level的meaningful code.

所以如果不考虑IO等blocking call的capacity的话.
它的latency大致就是直接的
latency = k*CPU/(N*c)
k为一个CPU提供的请求处理能力常数.
N为请求数,c为每请求需要的cpu资源数

所以简化下就是一个简单的
latency=a*CPU/N
的关系.
性能将随着CPU数的增加而增加.

这个跟benchmark的结果的部分结果也是可解释的.
在CPU/GOMAXPROCSS<40的时候,CPU资源的增加和性能的提升是准线性/sub-linear的.

但是继续增加的话,并不能再进一步地提高性能,甚至从抖动的角度来说,还有一定的degrade.

所以,这里就必须考虑把IO等的调度/capacity考虑进去了.

revise一下就是:
latency = (k*CPU)/(N*c-f*blocking)
f代表一个mean的平均调度周期内的从blocking->ready的G的数量.
以及bloking为对应的执行后续的开销.

intuitive的理解就是,divider是原本能调度的非blocking的user level的G减去必须调度的blocking ready的G.

这样的话,回头解释就是.
当CPU<40的时候,本质上是CPU bounded的,也就是其实并不能完全游刃有余地处理全部请求.
因此能产生的ready的数量是随着CPU数当增加而增加的.
所以是一个sub-linear的关系.

而当大于40的时候,基本上可以解释为是CPU已经不是瓶颈了,而主要是runtine处理IO/调度的能力.
所以这时候的f会相对地大量增加.
如果此时f*blocking是dominated的话,那么CPU的增加就会差不多近线形地被f的增加所抵消.

这样的话,就可以解释为什么继续增加CPU资源的时候,甚至可能会有degrade的情况.

这时候可能可以考虑的就是要么减少G的数量,要么减少syscall等blocking call的数量.

本质上,后者也是减少G的数量.

这个在之前一些版本的实验/探索里大致也是有部分实践可以说明的.

早期的一个实现采用了比较多的channel.
比如读写分开,处理数据分开.处理数据的过程也有channel.

这样的实现是会产生多几个数量级的G的.

所以后来的做法就是缩减了一些到公共channel,以及合并了一些原本独立的IO channel/goroutine.
这样的话,就减少了f和调度器的开销.

另外一个尝试就是把部分的写IO换成buffer io.
也就是合并syscall等部分.

但是现有的API做网络buffer io并不是很友好.
因为你需要手动地flush保证一定的latency的keep system running.

不然可能因为没有flush导致上下游都在等对方的IO.

所以要么就是加timer去flush.
要那么就是嵌套的select,外层non- blocking,然后default分支里再加blocking的select.

无论是哪种方式,都需要额外引入一个channel和goroutine.

这样的话就变成了syscall和goroutine/channel对于scheduler来说孰轻孰重的情况了.

而如果选择后者的话,代码复杂度会上升一些.
加上实际测试的效果似乎并不理想,所以最后这部分还是改为了直接syscall的方式.

当然,这里还有另外一个方向就是用mutex.
也就是write的时候用lock而不是channel.
这样的话,就可以在不用buffer io的前提下,speculate地合并一些写.

加上mutex本身也会触发调度,形式上和channel的效果类似.

但是它的问题在于不scale.

在限制CPU为1或者相对低的情况下,mutex通常能走fastpath.
也就是简单cas就能成功,不会触发调度,所以表现是相当地promising.

但是当CPU数量上去之后,资源抢占变得比较激烈,大多数时候都是slowpath,结果就不是很理想了.

所以这里一个思路就是对于mutex和channel的选择.
在抢占相对没那么严重的情况下,mutex似乎是比chan更好的一个选择.

回到IO的问题上.

这里的本质是Go目前没有一个比较好的感知IO ready情况的一个API.
理想状况下,需要是一个类似
func Write([]byte) <-chan IOResult
的API,
这样的话就能比较方便地做
for{
   ioCh:=w.Write(buf)
   select{
     case r<-ioCh:
       //if r.Err() != nil
     case newBuf <- bufChan:
      // gather more
      //. buf = append(buf,newBuf...)
   }
}
之类的.进一步减少groutine和syscall.

当然,初看起来这个自己实现也就是make一个channel然后go一下的问题.
ioCh := make(...)
go func(){
  defer close(ioCh) 
  size,err:=w.write()...
  //ioChan<- &{size,err}
}()

这里的问题一个是构造g的开销.
一个是不可避免地还是增加了一个g.

尽管看目前的runtime实现对g结构是有个resue/pooling的.
但是,多多少少还是涉及一些初始化的问题/开销.

而且更重要的是形式上来说,相比一个continue polling的goroutine并没有什么优势.
反而可能产生了更多的问题.

如果从runtime层面去做的话,可能就是在netpoll wait/pollDesc wait的相关路径更改/增加新的ready的回调方式了.

比如当前是的路径是挂起当前的g.

而按照上面API设计的话,可能就是netpollready的时候加个special case.
看是否有对应的g或者新的代表return chan的struct field,然后fake一个g或者更直接地,通过 channel kick start对端的g就是了.

当然,实际会更复杂一些.
比如加入之后还需要考虑pollDesc里的各个timer的处理等.


2021-06-29

从萨尔瓦多谈起

前段时间有个关于BTC的消息,就是萨尔瓦多将其作为一个官方货币/法币.
细节上来说,是发行了一个挂钩BTC的另外一个虚拟货币,作为一个流通使用的货币.

这个有趣的点在于提供了一个以前没想过的层次或者说侧面.
也就是像对于这类没有什么经济支柱产业点小国来说,BTC的可能是某种程度上的积极意义所在.

一般来说,一个国家如果没有什么完整的工商业体系,或者说没有什么支柱经济产业的话.
那么大多数时候的商品是需要通过国与国之间的跨国商业活动实现的.

而不同国别之间就存在了法币不同的情况.

这样的话,就自然而然需要有一种互通的汇率存在.

理论上来说,这个是两国之间协商互认的一个事情. 
以什么比率是可以私自决定的.
因为交易只设计两方.

但实际上这种理想情况是不太可能存在的.
一般都是多国贸易.

那么这样带来的一个问题就是种类繁多带来的系统复杂性.

所以,一般来说,会选择一个统一的可信货币作为本国汇率的锚点.

也就是一般所说的挂钩美元.

当然,也可以直接将美元作为自己的法币.
从大的方向上来说,有区别,但不大.

以锚定方式的话,至少从形式上保留了一定的货币独立性.
对于美元的变化相对来说,有一个缓冲区/时间因素.

而直接以美元作为法币的话,自然就没什么可以操作的了.

挂钩美元的话,自然理论上也可以自由定价.

比如一些汇率干涉和管制手段,单方面的维持某个牌价.

这个的话,也自然对应的会有市场驱动下的黑市牌价之类的.
作为一种群体性的价格纠正/共识机制.

所以除非是采用严格的汇率管制手段,限制/管制汇率交易,不然定价和平价总会回归到市场行为.

也就是说,当采用锚定美元的方式,并且不做或者做不到外汇管制的话,那么汇率价格的形成就会落到国际市场上.
即相对直接的买入卖出持有抛售行为上,从而形成一个公信价格/汇率.

因此为了保证相对稳定和可信的对美元汇率,一国的就需要针对美元和自身货币在市场上做相应的维持动作.

而一般他国对弱势国家的货币持有意愿是不高的.
一个是没有需求.
另外一个是风险敞口大.

当美元贬值的时候,相对来说就是本币升值.
而为了维持固定汇率,一国就需要做相应的贬值动作.

理论上来说,作为市场上几乎唯一的买方,唯一能做的就是抛售相应的美元资产,买入自身货币.
以维持对应的比率关系.
而这样做的影响就是减少了美元储备.

类似的,当美元升值的时候,就需要追加美元储备.
而追加的方式并不能通过本币的外汇市场操作达到,而需要通过以其他可能的方式增加对应的美元资产.
不然的话,固定汇率就失去了平准依据.

所以对于小国来说,需要有相当大美元资产储备和缓冲来保证国内经济的稳定性.
使得不会因为美元的波动而影响日常经济.

但小国之所以是小国就是因为没有太强的经济优势和创汇能力.
加上如果不做管制的话,国家财政是不太可能有大量甚至足够的美元储备抵御波动的.

尤其如果一国比较动荡,自由兑换的美元可能就很难通过循环回流到国库,从而形式和结果上的,进一步削减美元储备,降低本币信用,形成一个负反馈.

那么回到开头的萨尔瓦多的做法.

形式上来说,它是引入了另外一个资产标的BTC,作为锚定的目标.
并且理论上允许虚拟法币和BTC的兑换.

也就是间接的,维护了虚拟法币和美元等其他货币的一个一定汇率.

单本质上来说,因为手续上需要经过虚拟法币到BTC到一个兑换过程,所以实际上可以认为是某种形式的汇率管制.
所划的防火墙不是拒绝交易,而是作为代持.

只要虚拟法币所代表的BTC不实际地流出本国,对于本国来说,就是一定程度的dark pool操作.
并不影响BTC的对应储备.

这种方式跟美元的方式区别在于,最终用户得到的是BTC.
本质上不是一个可以快速流通变现的东西.
而当得到的是纸钞美元的话,一般情况下是可以快速流通的.

所以这是BTC作为外汇管制手段的一方面.

另一方面,因为限制了美元的持有,所以在黑市方面的价格形成压力和影响会相对地没那么大.
也就是在汇率价格形成机制上,对抗因素减少.

当传统情况下需要对锚定的美元价格动作的时候,由于缺少对手盘,所以少了出于套利的交易目的行为.
这样的话就允许不那么及时甚至不维护对应的汇率关系.

因为即使本币在市场上丧失信用,但并不影响一国以美元储备进行的商贸活动.
而由于国内锚定的是BTC代理的美元价格,所以也不会因为原有的本币波动造成影响.

当然,这里假定的是BTC本身的波动可以忽略.

这样的话,形式上就有点类似于是直接使用美元作为本国法币使用了.
因为无论对内对外来说,都直接间接的是以美元等值计价的.

唯一的不同在于,BTC的代理管制所构造的dark pool,使得一国可以在以类美元法币的形态,采取一定程度上的自主货币政策.
即通过调整dark pool的杠杆率来实现相对弹性的国内价格调整.

这点是在原有框架内,不做外汇管制的经济弱国里做不到的.

而如果都采用这种方式的话,可能确实对经济体系是一个不小的冲击.

因为国际贸易回归到ledger状态. 
单一或者多元强势货币的波动就可能没那么直接的影响.

而且这种体系天然地把国内经济活动和国际间经济活动隔离的.
原则上,国内到国际都是可追溯的.

以及因为本质上是存在防火墙代理隔离的两套系统,所以相对来说可以是彼此独立的经济体形态.
也就是说,可以不存在关联影响.

那么,这说明BTC确实有一定积极意义么?

也不是.

抛开本身的波动性和负面因素.
这套系统需要的不过是一个国际国内的代币缓冲隔离带.

所以它可以是任何形式的数字货币.

甚至是不是货币形态都不重要.

因为本质是个制度性要求.









2021-05-16

Eventloop及其他

最近一段时间写Envoy有些比较纠结的地方.

一个主要是eventloop模型,叠加C++本身的一些特性或者说问题.

写Java写Go的时候习惯于executor.submit或者go something.
毕竟closure带上上下文,交给调度器处理不在context的逻辑,一来心智上没什么负担随借随还.
二来毕竟多核,指不定并不实际影响latency,或者影响甚微.

而eventloop模型负担就比较重了.

因为本质上是一个topdown的设计,需要手工介入分时的概念,去衡量那些应该优先调度/调整顺序.

一个例子是写redis的proxy,外加一些协议层面的统计信息.
在实际debug情况下的测试结果,把统计关闭和打开大致会有几倍的性能差距.

原因也比较tuition.
相较于比较简单的协议解析来说,metric的各种lookup和string的allocation等反而开销更大.

所以一个直觉的处理方式就是异步化处理.

但是就eventloop模型来说,单线程其实没有所谓异步化处理.
最多也不过是对work queue的一些顺序调整.

当然,理论上来dealy到io事件之后处理是有可能利用一些本来就会花在poll上的时间的.
但也只是理论上.

实际上如果说真地在跑或者有了一定负载的话,大约也是io busy loop的.
所以delay到哪里其实代价都差不多.

另外一点就是envoy本身在libevent2上封装之后暴露出来的delay api要么是不停地塞到work queue的head,导致诸如delay([](){ doSomething(); delay(other)})这样的调用会直接递归出不来.

要么是timer base的delay方式粒度最小是1ms.
这多多少少不是让人很舒服.
因为是一个确定性的latency,而且不一定能容忍.

所以eventloop叠加callback或者coroutine之类的实现,本质上还是一个topdown的思维模式.
能做的最多就是次序上的调整,和基于此的一些speculative的开源节流方式.

而如果在这个思维模式下,加上C++的话又会有语言层面的一些纠结点.

既然已经在抠运行时调度的一些开销问题了,那么应对这些动作本身的开销也会多多少少考虑一些.

像比如要做delay的话,就必然涉及到把context带过去的问题.
直接如上的用lambda传递的话,在其他GC语言里可能就没那么多考虑.

毕竟即使考虑能做的也不多.
像Go可能还能做一些逃逸分析方面的考量,利用stack.
而Java类的基本就不用花这些心思了.

C++ lambda/std::function等就基本意味着要做value pass,触发copy.
而且一般来说就是memory allocation了.

当然理论上来说,可以写个stack allocator.
但对应的要做或者改造的地方就比较多了.

比如stack是哪个stack,如何保证这个stack是safe/accessible的.

一个简单的思路就是类似go的g0或者grouting stack.
用eventloop的frame层面的stack.
然后不够了fallabck会std allocator之类的.

但至少在envoy的场景这个是不太能做的.

毕竟寄宿在一层框架之上.

另外一个思路是可以在filter或者filter factory层面preallocate.
也就是在所属框架必然有的orignal/context object本身开辟一部分.

实际上也还是把自定义filter等组件作为一个goroutine stack来做allocation了而已.

这里带来的另外一个问题是这个allocation的lifecycle问题.

what if delay的operation执行的时候,这个hosted object free了?

不过在Envoy层面来说,这个问题不算大.

一来是从设计上来说,用了比较多的smart pointer,尤其比较严格的uniq_ptr.
object ownership关联关系方面的负担没那么重.

二是本身暴露的借口大多也有利用object自身的一个smart pointer做liveness check的.
在callback的时候会检查一下,所以也不用太担心.

但即使这样的话,也需要对lambda context bind的object做一些比较特殊或者类似的设计,以保证能够像envoy的这些security一样work.
而这样就意味着,如果没有follow这些practice的话,就容易或者说必然segment fault了.

关于这这点,一来是很难或者说不太容易做到这种API设计层面的约束.
二是即使做到了,接口结构层次也会显得不是太优雅.

总之,就是不太容易或者基本做不到在eventloop模型下,做一些优先级代价方面的取舍.

因为实际上无论如何都是要在一个线程内执行,只是先后的问题.
从线程自身的时间线来说,长度开销没有太大的区别.

那么跨eventloop调度呢?

Envoy的public API或者能使用到的API角度来说,是没有直接获取其他eventloop对象的.
在Envoy里叫做dispatcher.

但也只是不能直接.

因为它还提供了一个thread local相关的API借口.
是通过一个中心的main dispatcher向其管理 worker dispatcher post message切入到这些worker的context的实现.

也就是说能通过它间接地实现eventloop之间的非定向消息传递.
而既然又了非定向,结合一些比较ugly的诸如dispatcher name之类的标识ID之类的,也能实现定向message delivery.

只是做起来比较恶心.
而且还需要做一些额外的synchronize,保证在所有event loop确认触发了相应的事件/回调.

但这样一个明显的问题就是这种同步带来的不适感.
因为直觉上是对于各个eventloop的执行或者说性能不太友好的.

一个相对能够类比的例子就是GC的stop the world.

理论上体现到曲线上可能是会有一些毛刺感.

当然,就delay/async化metric统计来说,可以不用管同步问题.

一是不是特别重要.
二来,如果metric的值生成是instant/in place的,不同步处理最多也就是expose的方面有delay,影响不是很关键.

这样的话,另外一个点就是pass这些message的方式问题.

比如简单的一个std::list<Metric>,抛到另外一个eventloop的话,必然涉及到list的线程访问安全问题.

这个简单粗暴就是lock/mutex.
但考虑到像前面提到的,metric的生成速率本身比较高的话,mutex的同步开销就可能变得显著了.

一个相对优雅一些的做法是closure的binding方面做手脚.
把list move semantic,做clear cut,剥离竞争关系,一边是清空,一边是接管并顺带处理析构相关的开销.

这个算是一个观感尚佳的解决方案.

实际的问题是,这个异步eventloop可能处理不过来.
尤其前面场景,开启metric和关闭的性能是几倍到几十倍的差距.

这样的话,即使是1对1的eventloop配比关系有可能不够.

即使不考虑极端情况下worker eventloop已经把CPU跑满的情况,也需要考虑配比系数是怎样的.

而如果配比系数是adaptive的,那么随之而来的就是scale的算法和更重要的计算所需要用到的数据的synchronize或者不那么精确的approximate/estimate.
再就是进行scale时候的各个eventloop的同步以及已有callback/work queue如何/要不要re-balance的问题.

再极端一点的就是算法稳定性问题相关的,scale interval问题.
以及随之而来的re-scale的代价值不值等的问题.

最后下来可能就是重新发明了forkjoin pool/go primitive而已.

所以有时候会想,eventloop+manual memory management之于gc+runtime scheduler算是存在着代际的差异了.

至少从生产力层面来说.

而且如果说前者对于实现细节更有取舍控制权的话.
至少对于C++的实现来说,是需要有一些保留意见的.

像这里用到的例子,有比较让人不满意的差异的主要来源于debug build.
如果切换到release到话,可能差异就不是特别显著了.

这个imply的可能就是上古名言,不要过早优化所指向的真实含义.

编译器能做的优化可能比你想的更dirty/ugly.

像上面提到的lookup/string allocation等的开销.
再怎么写,可能不如丢给编译器inline加大范围的SSA/register allocation等.

就像后者的再怎么写,不如JIT的赌一把.

2021-04-18

定向

前几天的一个随想.
大意就是BTC的单位价值,对于不同时期的产出单元应该是不同的.

因为用马克思的剩余价值角度来看的话,后期BTC的算力投入是比前期大很多的.
在假设算力成本没差别的前提下,由于投入不同衍生的结果价值自然应该是不同的.

然后这里反过来的一个点就是现代货币理论的一些东西.

现代或者说西方经济学的一个重要概念说信贷.

信贷是一种对货币流动性加速的一个发明.

在没有资产负债表概念之前,交易是当场结算的.
而借贷的产生衍生出的信贷实际上就是一种异步就算.

信贷/credit则是在此基础上的进一步泛化.
如果把借贷作为是一种被动债务产生的话,信贷则是相对主动产生的.

主动就代表一定的主观性.

比如贷款评估的时候,一个资产对应的货币量是多少,这个本质上来说是非常主观的.
因为逻辑上,这个只需要借贷双方认可接受就行.
跟实际上或者说第三方认不认可没有关系.

所以一个东西,A认为能借/贷10,B认为能借/贷10w是不矛盾的.

但是把这个债务打包作为资产进行二次或者次级交易的时候,引入的是一个新的第三方.

理论上来说,只要这个新的第三方C认可,交易也可以进行下去.

以此类推地,可以到N.

问题在于这种基于主观性互相认可的匹配具有相当的随机性和不效率化.
因为撮合具有相当的随机性.

所以为了便于流动和转手,需要有一个市场存在.
而市场的构成是对于某个规则有明确认可度的个体集合.
目的是减少撮合交易的摩擦或者是匹配难度.

也就是说,市场内的个体需要对交易的物品有基本的定价共识,从而减少不必要的重复价格互认过程.

于是就有了各种估值模型.

所以本质上来说,一个或者说一类交易品的价格形成过程更多的是一种consensus.
参与个体的一种群体默契或者说潜规则认同.
模型或者公式的正确性理论上来说,并没有什么实际价值.

一个简单的例子即使股票市场的不同公司估值模型.

拿某中止上市的某集团来说,会有以科技公司估值和以金融公司估值的市值差异.

这个的字面理解就是不同的公司类型有不同的估值模型和方式.
因为不同行业的公司有着不同的经营模式和现金流/盈利模型.

而之所以需要有不同的领域模型来解释和推算是因为如果按照纯粹的盈利/收入/分红能力来price的话,有些公司是没办法有正的价格的.

比如众所周知的互联网公司,在初期可能是没有盈利能力的.

活着更一般的,没有盈利活着弱盈利能力的公司,是没办法有一个让人舒服的价格的.

即使不考虑市场交易对价格促成的影响.
单纯就一个新上市公司如何估值来说的话,如果它没有盈利能力是不是就不能有一个价格了呢.

这是合理但不feasible的.

因为证券化就是为了融资,而需要融资往往就是因为缺乏当前的现金流.
所以,如果按照这种合乎逻辑但不实际的思路的话,证券市场就是自相矛盾的存在.

因此需要有一个默契的共识,来促成交易的表面合理性.

对于已经有类似已经上市了的公司,就会有按照现有公司的一些数据做基本forecast得出的估值方式.

intuition是既然同类在现今市场上按照这个行成逻辑有这个现实价格,那么通过类比自然能逻辑上合理地得出一个预测当然值.

这个看上去解释的过去的就是所谓的市场共识.
它不一定需要正确,但是需要是大家默契接受的评价标准.

之所以说不一定正确是因为,即使模型数据能吻合,但是实际上这个是长期市场交易撮合形成的价格.
代表的是过去特定历史时期的特定历史事件和市场情绪构成.
这个并不代表将来新公司能有相同或者类似的发展机遇和路径.

所以,本质上来说,这是一种默契的对诡辩的普遍接受.
毕竟在一定程度上make sense.

既然价格/模型的形成是在特定场景下的特定自我说服的话.
那么带来的一个问题就是,价格对表的货币当量.
但是,价格的形成因素又不具有相对可比性,但却能有有具有可比性的货币数量来互相衡量.

这就比较有趣了.

一个可能稍显复杂但是可以说明的例子就是不同的crypto currency之间的价格问题.
它们都可以跟现实法定货币做兑换.

同时每个crypto又有自身的相同/类似或者不同的产生机制,和对应的各异的波动性表现.

另一个例子就是更一般的任意两个商品的价格对比.

本质上来说,它们都是不可比的.
但是,通过或者这种一般等价物使得交易可以促成.

问题在于此时的货币作为一般等价物的合理性.

最初的等价合理性在于点对点之间的peer认同.
次一级的是公共市场的参与者内部间的consensus.

一般的认同共识则是基于日常的广泛生活交易串联穿插起来的.

比如市场A的共识对于市场B是没有意义的,因为B中的个体不需要A.
但是AB可能需要一个共同的C市场的需求,所以他们有了共同的交集和货币流动.

到这里的话,另一个有意思的推论就是.
当A的generate的量或者速率/成本低于B的时候,在通过C交易的时候,A就B有着货币产生效率上的天然优势.

比如A市场的单次交易能产生X数量的货币利润,而B内的对等交易只能产生0.1X的货币盈余的话.
在共同市场C上,A对B就有绝对的货币量优势或者说购买力优势.

所以,这就是基于信贷的货币理论的一个必然结果.
它实际上抹去了一般等价物的基本先验,而只保证的相对/有限/limited等价的存在.

另外一个问题是记账方式带来的危机周期性.

因为基本的逻辑都是延迟结算或者说option运作.
在假设vest/realize没问题的时候,资产负债表是可以配平的.

但是如果中间环节有问题的话,自然就会有不对成的情况.
而不对称的结果就是账目上的货币湮灭/消失.

当维持系统运转的货币量出现流动性或者说根本性的数目缩减的时候,自然是不太期望能够继续正常运行的.

虽然理论上,可以通过同样的合理虚构填充这部分流动性和数值,也就是通常所说的干预手段.
但前提在于能防止账目的进一步崩坏和没有其他新生的账目问题.

而这点事没办法保证或者说不可能的.

因为总存在考虑不到的链条节点.

于是表现出来的就是必然的周期性.

所以似乎信贷是一个可以解释很多事情的东西.

它的根源在于对一般等价的模糊化处理.
或者说没有一个相对明确的定义.

因为它的等价概念衍生于一个行为,也就是交易本身.
而跟交易涉及的标的物是没有什么关系的.

从形式上来说,交易物本身甚至可以不是实际存在的.
比如信贷自身.

那么马克思的一般等价定义呢?

它基于的是所谓人类劳动.
这是一个相对明确的实体或者说概念定义.

但是它的问题在于.
一个是本质上来说,它是undefined的,不同商品的无差别劳动是不可测量的.
在实际运用中,它的量度还是通过市场行为来观测的.

也就是说实际上并没有解决模糊化这个问题.
或者说至少没有直接地解决.

另一个是对于现存的信贷行为,它是解释不了的.
因为即使套用框架,你也没办法将一个未发生的事情做无差别劳动计量.
至少,不能解释估值概念/框架.

但是它提供了一个思路.
就是不再以交易作为货币一般等价的概念基础.

这里带来的一个概念可能就是货币政策可能不再以量,或者至少不再最终以量的多寡作为最终评价/衡量政策效果的标准/结论.

因为量的概念在不同的交易当中是不可比的.

反过来也就是说,在不同的渠道,不同的量的干预/扭曲程度/方式是有不同意义的.

2021-03-27

飘

最近的冲突两方都有观点抛出了一个词,价值观不符.

这个确实可能是比较内涵的一个点.
从疫情初期的内外政策区别和舆论态度都可以算是一个体现.

今天看到两条消息,或者说两方论证.

一个是谈到棉花产量问题,连带的质量技术和产需都很大却库存积压的问题.
另一个则是对前一方的各点回应.

综合地来说,双方都没有否认进出口量大以及库存问题的存在.
区别在于,库存问题是选择性统计时间造成的数据偏差.

另外一点就是后者还提到了BCI成立后,恰恰接着的就是棉花行业的不景气.

所以如果以贸易问题作为问题焦点或者说事件立足点的话,那么对应的就是棉花的倾销性出口的事实存在了.

BCI的准入问题算是一种较为常规的行业准入协定限制,作为一种简单的提高产出成本的最简单可行的壁垒性措施.

按照一般价值观来说,就是一种联合性的君子协定或者说潜规则条约,明面上的是什么其实不是很重要.
当然,如果名正言顺自然更好.

作为贸易的一方,根据行业惯例和规则加入有限自然无可厚非.

但问题在于这条规则并没有起到预期的作用.

因为提高的成本不足以覆盖双方之间的产出成本差异.

这一点远一点的原因也是价值观和行业准入协定的影响.
只不过对象是劳动福利本身.

用行业壁垒理解工会和劳动福利的话,换算成经济效益就是用工成本.
当参与者按照相同的协议成本的时候,就是纯粹的明面生产水平和成本比拼.
也就是通常所说的公平市场竞争.

但是在用工成本不同的情况下,或者说没有达成一致共识的前提下,原有行业门槛的成本就变成了原成员共有的一个成本劣势.

这个可以用互联网广告和传统行业广告的区别来做类比.

信息技术产生的渗透广度从效率上来说是远远高于传统行业的广告模式的.
而且致命的矛盾就是,互联网的渠道是完全独立或者创新于传统广告业的.

这就是使得原有的行业壁垒在新生产力或者说竞争模式下变得毫无意义,同时维护行业壁垒的投入成本变成了一种没有回报的坏账.

所以,从本质上来说,这是两种生产用工方式完全不同造成的成本核算的不对称问题.

从竞争的角度来说,就是一方的成本低于另一方,导致的结果就是相对来说没有什么竞争力.

再考虑到如果成本优势方有生产优势以及规模优势的话,无论是倾销和正常的市场化行为,最终都会造成其他方市场份额的萎缩甚至退出消失.

从这个角度看威胁论的话,也就不是没有什么现实意义.

因为从一些产业来说,确实已经到了被动需求出口供应的地步.
极端的发展就是所以生产都将在一国产生.

对应的就是它过的生产和就业出现一个未知或者说并不理想的预期.

而这个又恰恰是自由市场共识或者说潜规则体系所不相容的制度或者说运作机制.
无法通过一个现有的有效方式,协同成本差距.

所以这种担忧和无力感是实实在在的.

换个角度来说.
这种担忧是虚构的或者说不切实际的么.

也不是.

即使是按照自由市场的逻辑来说,商业上即使可以通过规则条例确保规模限制.
但是也最多只是规模限制.

一个有效同时也微妙的比喻就类似于芯片行业.
可以约束产量规模甚至制程技术,但本质上来说,技术优势或者说差距不是那么容易填平的.

所以用最终的全面产品倾销来理解这种对抗性思路可能也不是太过离奇.

而这种概念在稍远一点的历史时期就是所谓的航海殖民时代.

这是一点.

另外一点就是强迫劳动的问题.

抛开前面的隐含逻辑,看描述的话.
一方给出的争端指责是大规模的劳工迁移和非自由意愿的劳动.
另一方的对应则是作为扶贫政策的常规操作.

双方都没有否认的一点就是确实存在着劳动人口的迁徙.

以及双方都认同或者说采纳的一份视频材料.
里面提到了一位工作人员描述工人为懒惰的片段.

这里无论是以强迫来动还是以扶贫工作的角度来看,确认的一个事实是工人工作有一定的非主动积极性.

这点怎么理解本质上会是个比较难界定的问题.

以宏观和制度性角度来说,这可以理解为一种压力驱动的进取模式.
应对的不给定外界驱动力难以达成进步的方式.

就像健身或者说考试学习等.
需要一种反人性/舒适区的手段.

但是如果以个体角度来看,就是一个被强迫竞争的态势.

一个同样也是有效且微妙的比喻就是延迟加班和内卷的问题.
它形式上就是一部分人的投入和另一部分人的期望投入存在不对称的情况.
而在外部考核评价体系下,不对称的投入期望成为一种数值上的类成本劣势.

尽管以个体的利益评估体系来说不应该做,但却被迫投入的一个情况.

中性地来说,两种情况都是一种外界驱动的被动加大投入的方式.
所不同的是,回报率的计算方式跟立场有关.

所以,以纯粹论据或者说价值观体系来说,两种说法都不算错.

这就是为什么说,抛出价值观冲突这点算是一个明确或者说某种程度上明朗化的一个表现.

不同的价值观带来的是不同的行为方式,以及行为预期.
不符合预期的行为自然一般会被认为非理性和不可理解的.

以及不同预期在协同交互过程中,自然对回报会有不同的理解和对应期望.

不一致反倒是一种必然.

2021-03-21

从三角债谈起

在给定的循环三角债情况下,即比如A欠B 100,B欠C,100,C欠A 100的情形.

那么作为央行或者说银行信贷方来说,就有一个直接naive的方式作配平.
即给ABC各100的额度,然后后续就能恢复流转.

这种方式产生的信用额度就是300.

但是一个更optimal的方式是给其中一个100的信用,然后也一样可以让系统流转起来.

所以单就经济刺激和货币宽松来说,额度倒也不一定是体现最终实际规模的一个标准.

但可能反过来说,更反映的是解决切入的侧重点的问题.

通过给消费终端注入资金水平,用凯恩斯的思路就还是利用消费需求反推生产.

但通常来说这里的思路实质上依赖的并不真是末端消费者的消费行为所带来的产业链回溯.
而是末端消费产品的生产商的需求逆向扩张的结果.

也就是说,如果即使消费端有大量的资金购买/流入某个商品领域,但是这个商品本身能够惠及或者需求的产业链上游有限,或者说普及面不够广的话.
那么至少从投入成本和收效的角度来说,就是300和100的区别.

另外一个问题就是,从消费者角度来看.
注入的资金的性质或者说实际用途的效用分类问题.

假如是在一个相对静态或者说变量环境没那么多和复杂的情况下,单纯的提高可支配收入自然是可以理论上等比例地提高对生产需求的反馈.

但是如果消费曲线本身不是那么静态,或者说是在萎缩的前提下呢.

比如因为没有工作机会造成的收入停滞/衰退,消费的目的从改善型回归到的基本的生存需求上.

那么这个消费刺激的回馈场景就相对来说可见的.
会比较集中于基本和底层的衣食住行的低层次保障性消费上.

而一般地来说,像基础食品制造和加工的需求增加或者说恢复并不见得能对就业情况带来一些比较积极明显的改善.
因为现在工业文化在这类基础性保障供应上比没有太多的劳动力方面的需求.
或者说单位劳动力的生产能力剩余比较充裕,足以覆盖增加的部分.

所以它的实际效用可能还不及100.

然而,问题在于既然从效用角度来说,并不是一个显而易见的较优方案的话,为什么还会选择执行呢?
尤其在同期有其他一些产业链刺激鼓励决策/政策意向的前提下.

如果考虑说产业发展并不需要或者还没到需要一个自上而下设计推进的阶段的话,那么按照以往的理论,最终也还是能够推导倒消费终端和劳动者层面.
也就是促进就业和恢复经济的道路.

一个可能是劳动力结构问题.
或者说产业结构问题.

如果大多数劳动力/产业是一些比较小而分散的非规模经济的话.
那么即使有一个倾向性明显的产业鼓励政策,由于不在同一个层面,也就自然无法被惠及和影响.

比如多是一些自由和个体小微企业的话,除非是行业强相关.
不然产业链长度是有限的.

另一个可能是时间问题.
或者说紧迫性问题.

因为虽然理论上来说,刺激性方案可以在结论上产生一些产业连续乘数现象.
但是实际的执行上会有一个时间因素在里面.

如果在效果产生之前就已经破产或者无法生存的话,结果的推演如何美好也是没什么太大意义的.

但这里的另外一个问题就是,从额度或者说数量上来说,能覆盖的也就是几个月的生活成本而已.

这样的话,问题就变成是这个时间周期是预期的一个安全恢复边际呢,还说是一个在当前成本支出情况下,所力所能及的一个极限extend了.

从市场rumor来说,利率飙升是一个几乎没什么歧义的共识.
毕竟长期成本放在那.

但问题在于,这个动机是纯粹的预期成本带来的还是带有一些其他情绪和因素.

如果参杂的是对于国债的一个偏好增强的话.
那么同样的理由就可以理解为一种对风险偏好方式的情绪改变.
再进一步的就是对非国债的一种避险趋势或者说本能.

而这点跟对就业改善预期的不期望也是大致有一定的趋同性思路的.

这样的话,把持续宽松承诺和持续上升的国债收益率两个本该相悖的东西放一起看的话,似乎也不是那么不相容.

问题在于,如果远期来说是宽松的话,而利率水平又上升,那么指向的就是inflation了.

这个反映到国际上的话,就会是一个相对比较有趣的问题了.

如果作为锚定货币的话,对方要继续锚定inflate之后的汇率的话,就会比较困难.
因为不一定能适用同等宽松的策略.
而如果不能的话,那么从负债角度来说,就是一种财富的转移/成本的嫁接了.

再进一步的如果经济体本身就有一些问题的话,可能就是连锁反应了.

而作为非锚定货币但是主要信用支撑载体和通货的话,可能对应的就是多元化分散了.
减少对单一货币信用的依赖程度,减少通胀的被动输入依赖.

从货币母国的角度来说,可能就是国际信用/地位的相对浮动变化了.




2021-02-13

乐高的玩法

前两天拼乐高的时候想了下,感觉应该会有竞技类型的比赛.
毕竟理论上来说,这个还是可以有一些策略和训练性质在里面的.

如果不考虑一些其他商业因素的话,乐高的建模以现在的技术水平来说,可能也就是一些3D渲染的应用.

一个比较近似的例子就是Minecraft,以有限组合的类pixels.
每个积木单元可以是基础的构件.
至于形态的多样性主要就取决于渲染效果的近似性需要的.

有些需要更柔和精确的就可能会作为一个特化元件.

这个在没有computer assisted的时代应该个挺有挑战和挺有意思的事情.

当然,在现在来说可能依然是.
一方面是传统的元件拟合设计.
另一方面可能是更商业化的,如何平衡特化/利润/独特性/通用性/成本/品控的一些列综合因素解了.

前面说的竞技性的点在于,本质上来说它就是一个模式识别的过程.

因为渲染构造和元件复用的因素,一般来说每个元件与元件之间是有一定的组合亲和度/概率性的.

类似于棋牌类项目的起手式/模式之类的.
给定一个初始状态会有一个对应的状态概率空间的展开.

当然具体到乐高本身的展开又可能会有些不一样的地方.

元件的展开和元件空间的构成的结果是一些更高一些维度的组件性质概念.
或者说是更大规模一点的元件.

就像神经网络的low level的feature叠加成更高level的表达方式.

所以,理论上来说,这就是一个物理空间概念上的拟合矩阵.
复杂度和parameter数量对应的就是元件的设计和叠加连接方案了.

抽象地说,这就是一个算法的快速解的比较过程.

给定一个拟合目标如何更快速地还原构建出近似解.

具体到实际就是需要对元件的组合规律有所了解和记忆.

这里面又涉及到如何从一堆细散物件里准确找出需要的元素.

所以就是一个识别,分类,检索,构建,叠加的过程.

如果把初始的器件筛选过程比喻为磁盘IO的话,就类似于有顺序随机读写之类的实现性能差异.
而选择以那种高级元件为构建目标就是上层的buffer管理之类的了.

之所以说是buffer是因为像建筑类,主要就是一些重复度高的building block的批量制作过程.
就像做计算时候的cacheline等管理.

从这个角度来说,这种竞技性就是技巧和设计或者说流程架构上的效率区别的比较.

那么顺着这个思路,就像一些游戏的速通记录一样,在一定程度之后会有一种相对认可和公开的模板模式作为一个相对优解的出现.

于是第二层的竞技因素就在同样步骤和方式的前提下,单纯比拼速度的形式了.

如果以日漫ACG的方式表现的话,大概又可能会有拼装手法/手势上的一些纯体育竞技方向的技巧差距拉开.

不过这个实际搜索了下确实有类似的contest.
只不过速度没有想象中那么快.

至少从视觉观感上来说,不如魔方等同为既定技巧下的速度竞赛.

不过这可能是因为竞争或者说接受度没那么广.
以及看到的素材本身不代表实际顶尖竞赛水平.

那么除了这些点之外呢?

尤其speed contest方面还有其他玩法么?

因为之前的都是基于构建.
那么自然的可以有拆除或者重构建的竞赛方式.

最简单的就是给定一个模式,以最少和最快等标准从中拆除然后再构建的方式.

再进一步的,可以是拆除资源是共享的引入资源限制和竞争关系.
这样的话又会带来其他一些的变量.

比如各类元件资源的数量是给定和既定的.
同时需要构建的元件的对应数值也是确定的.

那么在数量方面至少就产生了策略对抗性玩法.
因为某种元件可能是有限的甚至是唯一解的.
如果获得不到或者不够就意味着速度优势并没有什么价值.

以及如果再进一步的,加入竞赛者之间的资源掠夺方式就又会使得变量进一步膨胀.

就像典型的RTS游戏.
speed rush和资源型都可以是一种制胜策略.

其他的一些思路诸如密室类key玩法.

因为本质上来说,可以把它看作是一个programable的东西.
既然是这样话,那么它包括的就是build run and test一系列中间流程以及最终的runnable的产物.

中间流程可以成为竞争点的话,自然最后的runnable的成品也可以是要素之一.

而且如果把整个串起来的话,就对规划性和策略预判有更高的要求了.

因为从即使前面阶段能够获胜,但最后runnable的东西不适合不可用也没有意义.
毕竟这最后一点的设计可以是在初期unreveale的.

这就像地下城模式的剧情和角色天赋转职适应性一样的设计.

所以回头看的话,这几乎就是一个可以把所有game play因素搬到线下的一个东西.

或者更确切地说,就像一个转生RPG的一个重要初始道具.
后期的发展和剧情推动以及互动元素都在于这个的build run的全过程.





牛来餐馆

看了欢迎来龙餐馆. 总的来说,作为一个院线电影,成品多少是有点不太匹配的. 看起来更多像是一部网络大电影. 尤其涉及到一些大场面特效的时候,可以看得出服化道的降本增效. 剧本层面有一些比较有意思或者说闪光点. 就是试图用一个餐馆或者厨师来串起一个比较宏大的叙事题材. 这个可以说是...