zoukankan      html  css  js  c++  java
  • Rocket

    https://mp.weixin.qq.com/s/QsL1Bfb0JsOaxWW_muhg_Q

     
    简单介绍CacheCork的实现。
     
     
    1. 基本介绍
     
    Cache的塞子,下游没有Cache节点。把上游节点的Acquire/Release消息转换为Get/Put消息实现。
     
    各个消息处理方法整理如下表:
     
    2. 类参数
     
    包含如下参数:
    a. unsafe:是否安全:至多能安全的支持一个Cache Client;
    b. sinkIds:支持的下游ID数目,用于Grant消息中填充sink域;
     
    3. diplomacy node
     
    介绍TLCacheCork节点如何向上下游传递参数:
     
    1) clientFn:向下游传递上游节点的参数
     
    其中:
    a. supportsProbe = TransferSizes.none:告诉下游节点他的上游节点即CacheCork节点不接收Probe消息;
    b. c.sourceId.start * 2:乘以2是因为在低位增加了1位作为transform编码使用;
     
    2) managerFn:向上游传递下游节点的参数
     
    只处理类型为UNCACHED的manager:
    其中:
    a. 告诉上游节点CacheCork节点支持的sinkIds;
    b. AcquireB是要获取读权限,所以转变为m.supportsGet;
    c. AcquireT是要获取写权限,所以转变为m.supportsPutFull;
    d. 因为只有一个cache client,所以可以alwaysGrantT;
     
    4. lazy module
     
    1) 输入边和输出边成对出现
     
     
    2) 如果没有一个manager支持Acquire操作,则直接相连
     
    这里使用的是edgeIn.manager,也就是输入边的manager,即输入边的下游,也就是CacheCork节点。edgeIn.manager是从edgeOut.manager参数转换而来的(使用managerFn)。
     
    edgeIn.manager都不支持AcquireB,可以反推得知edgeOut.manager也都不支持AcquireB。
     
    3) 需要CacheCork做中转:edgeIn.manager.anySupportAcquireB
     
    A. 取出上游节点
     
     
    B. 取出可以缓存数据的节点
     
     
    C. 限制条件
     
    a. 只有一个上游节点,如果多于一个,则不能有cache节点;
    b. 上游cache节点最多只能有一个,否则不安全;
    c. 下游节点不能支持缓存,否则不安全;CacheCork节点居中阻挡下游cache节点和上游cache节点之间的数据同步,无法保证缓存一致性;
    d. 下游节点的区域类型必须为UNCACHED/UNCACHEABLE/PUT_EFFECTS/GET_EFFECTS中的一个;
     
    考虑安全的使用方式(unsafe = false),限制条件a/b要求上游的cache节点最多只有一个。这是因为CacheCork节点不做Probe的动作,而是alwaysGrantT。所以如果有多个Cache节点的话,会导致缓存一致性问题。
     
    关于d,新版代码中有注释:
     
    D. 要组装的消息
     
    a. 把in.a组装成a_a,再通过out.a发出;
    b. 把out.d组装成a_d,再通过in.d发出;
     
    E. isPut:是否Put消息
     
     
    F. toD:是否可以立即回复的消息
     
     
    G. in.a.ready
     
    根据消息是可以立即回复,决定要使用的组装消息:
     
    H. 组装发往out.d的消息
     
    其中:
    a. 编码位编在第0位;
    b. 因为toD中包含了AcquireBlock.BtoT和AcquirePerm,所以这里的条件实际上只包括AcquireBlock.{NtoB,NtoT}两个;
    c. 把AcquireBlock.{NtoB,NtoT}转换为Get消息,编码值为1;相对比,正常的Get消息编码值为0;
    d. 除去AcquireBlock.{NtoB,NtoT}的情况,如果是Put消息,编码值为1,其他情况下为0:
     
    I. 组装要立即回复的消息
     
    a. 组装从channel a来的AcquireBlock.BtoT和AcquirePerm消息:
     
    b. 组装从channel c来的Release消息:
     
    J. 转换从channel c来的ReleaseData消息
     
     
    K. 处理channel B的消息
     
    我们不会向in.b发请求消息,所以不用处理in.b。我们不支持Probe消息,所以不接收out.b的消息:
     
    L. Grant消息需要添加sink域
     
    a. 创建一个sink id pool:
     
     
    b. 需要回复Grant消息是alloc一个id:
     
    c. 从channel e受到GrantAck时,释放对应的sink id:
     
    M. 未转换的out.d消息:直接移除编码位即可:
     
     
    N. 记录访问的地址是否可写
     
    重构一下,把w扩展为writable,这样比较好理解。
     
    a. 创建一个寄存器组记录信息
     
     
    b. 判断channel a访问的地址是否可写:
     
     
    c. 当channel a请求输入时,记录是否可写的信息:
     
     
    d. 从记录的信息数组中,获取返回的响应消息针对的地址是否可写:
     
     
    e. 判断操作是否可以在同一个时钟周期内返回:
     
     
    sourceWritableVec是一个寄存器组,其中的值每个时钟周期只刷新一次。在同一个时钟周期内,新存入的aWritableOk还没有来得及写入,不能使用dWritableOk这个从寄存器中获取的值,而只能直接使用aWritableOk。
     
    f. 获取一个一直可以用的可写信息:
     
     
    O. 转换AcquireBlock.{NtoB,NtoT}的响应消息:
     
     
    P. 转换ReleaseData的响应消息:
     
     
    Q. 把组装的消息分别发往out.a/in.d:
     
    其中:
    a. 第二个是in_d,不是in.d,即所有的组装消息先发往in_d,in_d则直接连到in.d上;
    b. c_d/a_d先输出到Queue中,应该是为了增加吞吐量;
     
    R. 不发起使用channel b/c/e的请求:
     
     
     
    5. 整理组装的消息
     
    1) 请求消息
     
    A. a_a
     
    包含两种消息:
    a. AcquireBlock.{NtoB,NtoT}转换之后的Get消息;
    b. 其他非即时回复消息:
     
    B. c_a:ReleaseData消息转换之后的Put消息;
     
    2) 回复消息
     
    A. in_d:所有组装消息先输入in_d,而后输入in.d;
     
    B. a_d:即时回复AcquireBlock.BtoT和AcquirePerm的Grant消息;
     
    C. c_d:即时回复Release消息的ReleaseAck消息;
     
    D. d_d:其他回复消息:
     
  • 相关阅读:
    Java:线程的六种状态及转化
    Java:多线程概述与创建方式
    小白学Java:RandomAccessFile
    如何用IDEA开启断言
    如何通过IDEA添加serialVersionUID
    小白学Java:I/O流
    更改IDEA相对路径
    小白学Java:File类
    小白学Java:内部类
    Leetcode数组题*3
  • 原文地址:https://www.cnblogs.com/wjcdx/p/11322887.html
Copyright © 2011-2022 走看看