精华内容
参与话题
问答
  • const buf01 = Buffer.alloc(10); console.log(buf01.toString()) const buf02 = Buffer.from([10,20,30]); console.log(buf02.toString()) const buf03 = Buffer.from('创建方法'); buf03.write('hellouuuuuuu');...
    const buf01 = Buffer.alloc(10);
    console.log(buf01.toString())
    const buf02 = Buffer.from([10,20,30]);
    console.log(buf02.toString())
    
    const buf03 = Buffer.from('创建方法');
    
    buf03.write('hellouuuuuuu');
    console.log(buf03.toString())  //从缓冲区读取数据
    
    var mn = Buffer.concat([buf01,buf02]);
    
    console.log(mn) 
    
    
    展开全文
  • Buffer Manager

    2017-05-06 04:28:33
    As a part of the team you will be responsible for the Buffer Manager. Data blocks being read by DBMS from the hard drive are stored in the main memory in a fixed number of pre-allocated buffers. Each...
  • 习惯用 Json、XML 数据存储格式的你们,相信大多都没听过Protocol Buffer Protocol Buffer 其实 是 Google出品的一种轻量 & 高效的结构化数据存储格式,性能比 Json、XML 真的强!太!多! 由于 Google出品,我相信...

    前言

    • 习惯用 Json、XML 数据存储格式的你们,相信大多都没听过Protocol Buffer
    • Protocol Buffer 其实 是 Google出品的一种轻量 & 高效的结构化数据存储格式,性能比 Json、XML 真的强!太!多!

    由于 Google出品,我相信Protocol Buffer已经具备足够的吸引力

    • 今天,我将讲解为什么Protocol Buffer的性能如此的好:
      a. 序列化速度 & 反序列化速度快
      b. 数据压缩效果好,即序列化后的数据量体积小

    阅读本文前请先阅读:

    1. 快来看看Google出品的Protocol Buffer,别只会用Json和XML了
    2. 手把手教你如何安装Protocol Buffer
    3. 这是一份很有诚意的 Protocol Buffer 语法详解

    目录

    目录


    1. 定义

    一种 结构化数据 的数据存储格式(类似于 XML、Json

    1. Google 出品 (开源)
    2. Protocol Buffer 目前有两个版本:proto2proto3
    3. 因为proto3 还是beta 版,所以本次讲解是 proto2

    2. 作用

    通过将 结构化的数据 进行 串行化(序列化),从而实现 数据存储 / RPC 数据交换的功能

    1. 序列化: 将 数据结构或对象 转换成 二进制串 的过程
    2. 反序列化:将在序列化过程中所生成的二进制串 转换成 数据结构或者对象 的过程

    3. 特点

    • 对比于 常见的 XML、Json 数据存储格式,Protocol Buffer有如下特点:

    Protocol Buffer 特点


    4. 应用场景

    传输数据量大 & 网络环境不稳定 的数据存储、RPC 数据交换 的需求场景

    如 即时IM (QQ、微信)的需求场景


    总结

    传输数据量较大的需求场景下,Protocol BufferXML、Json 更小、更快、使用 & 维护更简单!


    5. 使用流程

    关于 Protocol Buffer 的使用流程,具体请看我写的文章:快来看看Google出品的Protocol Buffer,别只会用Json和XML了


    6. 知识基础

    6.1 网络通信协议

    • 序列化 & 反序列化 属于通讯协议的一部分
    • 通讯协议采用分层模型:TCP/IP模型(四层) & OSI 模型 (七层)

    通信协议结构

    • 序列化 / 反序列化 属于 TCP/IP模型 应用层 和 OSI`模型 展示层的主要功能:

      1. (序列化)把 应用层的对象 转换成 二进制串
      2. (反序列化)把 二进制串 转换成 应用层的对象
    • 所以, Protocol Buffer属于 TCP/IP模型的应用层 & OSI模型的展示层

    6.2 数据结构、对象与二进制串

    不同的计算机语言中,数据结构,对象以及二进制串的表示方式并不相同。

    a. 对于数据结构和对象

    • 对于面向对象的语言(如Java):对象 = Object = 类的实例化;在Java中最接近数据结构 即 POJOPlain Old Java Object),或Javabean(只有 setter/getter 方法的类)

    • 对于半面向对象的语言(如C++),对象 = class,数据结构 = struct

    b. 二进制串

    • 对于C++,因为具有内存操作符,所以 二进制串 容易理解:C++的字符串可以直接被传输层使用,因为其本质上就是以 '\0' 结尾的存储在内存中的二进制串
    • 对于 Java,二进制串 = 字节数组 =byte[]
    1. byte 属于 Java 的八种基本数据类型
    2. 二进制串 容易和 String混淆:String 一种特殊对象(Object)。对于跨语言间的通讯,序列化后的数据当然不能是某种语言的特殊数据类型。

    6.3 T - L - V 的数据存储方式

    • 定义
      Tag - Length - Value标识 - 长度 - 字段值 存储方式

    • 作用
      标识 - 长度 - 字段值 表示单个数据,最终将所有数据拼接成一个 字节流,从而 实现 数据存储 的功能

    其中 Length可选存储,如 储存Varint编码数据就不需要存储Length

    • 示意图

    最终存储的字节流

    • 优点
      从上图可知,T - L - V 存储方式的优点是
      1. 不需要分隔符 就能 分隔开字段,减少了 分隔符 的使用
      2. 各字段 存储得非常紧凑,存储空间利用率非常高
      3. 若 字段没有被设置字段值,那么该字段在序列化时的数据中是完全不存在的,即不需要编码

    相应字段在解码时才会被设置为默认值


    7. 序列化原理解析

    请记住Protocol Buffer三个关于数据存储 的重要结论:

    • 结论1: Protocol Buffer将 消息里的每个字段 进行编码后,再利用T - L - V 存储方式 进行数据的存储,最终得到的是一个 二进制字节流

    序列化 = 对数据进行编码 + 存储

    • 结论2:Protocol Buffer对于不同数据类型 采用不同的 序列化方式(编码方式 & 数据存储方式),如下图:
      数据类型 对应的编码方式

    从上表可以看出:

    1. 对于存储Varint编码数据,就不需要存储字节长度 Length,所以实际上Protocol Buffer的存储方式是 T - V
    2. Protocol Buffer采用其他编码方式(如LENGTH_DELIMITED)则采用T - L - V
    • 结论3:因为 Protocol Buffer对于数据字段值的 独特编码方式 & T - L - V数据存储方式,使得 Protocol Buffer序列化后数据量体积如此小

    下面,我将对不同的编码方式 & 数据存储方式进行逐一讲解。


    7.1 Wire Type = 0时的编码 & 数据存储方式

    Wire Type = 0时的编码 & 数据存储方式

    7.1.1 编码方式: Varint & Zigzag

    A. Varint编码方式介绍

    i. 简介

    • 定义:一种变长的编码方式
    • 原理:用字节 表示 数字:值越小的数字,使用越少的字节数表示
    • 作用:通过减少 表示数字 的字节数 从而进行数据压缩

    如:

    • 对于 int32 类型的数字,一般需要 4个字节 表示;
    1. 若采用 Varint编码,对于很小的 int32 类型 数字,则可以用 1个字节 来表示
    2. 虽然大的数字会需要 5 个 字节 来表示,但大多数情况下,消息都不会有很大的数字,所以采用 Varint方法总是可以用更少的字节数来表示数字

    ii. 原理介绍

    • 源码分析
    private void writeVarint32(int n) {                                                                                    
      int idx = 0;  
      while (true) {  
        if ((n & ~0x7F) == 0) {  
          i32buf[idx++] = (byte)n;  
          break;  
        } else {  
          i32buf[idx++] = (byte)((n & 0x7F) | 0x80);  
          // 步骤1:取出字节串末7位
          // 对于上述取出的7位:在最高位添加1构成一个字节
          // 如果是最后一次取出,则在最高位添加0构成1个字节
    
          n >>>= 7;  
          // 步骤2:通过将字节串整体往右移7位,继续从字节串的末尾选取7位,直到取完为止。
        }  
      }  
      trans_.write(i32buf, 0, idx); 
          // 步骤3: 将上述形成的每个字节 按序拼接 成一个字节串
          // 即该字节串就是经过Varint编码后的字节
    }   
    
    

    从上面可看出:Varint 中每个 字节 的最高位 都有特殊含义:

    • 如果是 1,表示后续的 字节 也是该数字的一部分
    • 如果是 0,表示这是最后一个字节,且剩余 7位 都用来表示数字

    所以,当使用Varint解码时时,只要读取到最高位为0的字节时,就表示已经是Varint的最后一个字节

    因此:

    • 小于 128 的数字 都可以用 1个字节 表示;
    • 大于 128 的数字,比如 300,会用两个字节来表示:10101100 00000010

    下面,我将用两个个例子来说明Varint编码方式的使用

    • 目的:对 数据类型为Int32 的 字段值为296 和字段值为104 进行Varint编码
    • 以下是编码过程

    Varint编码过程

    从上面可以看出:

    • 对于 int32 类型的数字,一般需要 4 个字节 来表示;
    • 但采用 Varint 方法,对于很小的 Int32 类型 数字(小于256),则可以用 1个字节 来表示;

    以此类推,比如300也只需要2个字节

    • 虽然大的数字会需要 5 个字节 来表示,但大多数情况下,消息都不会有很大的数字
    • 所以采用 Varint 方法总是可以用更少的字节数来表示数字,从而更好地实现数据压缩

    下面继续看如何解析经过Varint 编码的字节

    Varint 编码方式的不足

    • 背景:在计算机内,负数一般会被表示为很大的整数

    因为计算机定义负数的符号位为数字的最高位

    • 问题:如果采用 Varint编码方式 表示一个负数,那么一定需要 5 个 byte(因为负数的最高位是1,会被当做很大的整数去处理)
    • 解决方案: Protocol Buffer 定义了 sint32 / sint64 类型表示负数,通过先采用 Zigzag 编码(将 有符号数 转换成 无符号数),再采用 Varint编码,从而用于减少编码后的字节数
      表示负数时采用Zigzag编码
    1. 对于int32 / int64 类型的字段值(正数),Protocol Buffer直接采用 Varint编码
    2. 对于sint32 / sint64 类型的字段值(负数),Protocol Buffer会先采用 Zigzag 编码,再采用 Varint编码
    • 总结:为了更好地减少 表示负数时 的字节数,Protocol BufferVarint编码上又增加了Zigzag 编码方式进行编码
    • 下面将详细介绍 Zigzag编码方式

    B. Zigzag编码方式详解

    i. 简介

    • 定义:一种变长的编码方式
    • 原理:使用 无符号数 来表示 有符号数字;
    • 作用:使得绝对值小的数字都可以采用较少 字节 来表示;

    特别是对 表示负数的数据 能更好地进行数据压缩

    b. 原理

    • 源码分析
    
    public int int_to_zigzag(int n)
    // 传入的参数n = 传入字段值的二进制表示(此处以负数为例)
    // 负数的二进制 = 符号位为1,剩余的位数为 该数绝对值的原码按位取反;然后整个二进制数+1
    {
            return (n <<1) ^ (n >>31);   
            // 对于sint 32 数据类型,使用Zigzag编码过程如下:
            // 1. 将二进制表示数 左移1位(左移 = 整个二进制左移,低位补0)
            // 2. 将二进制表示数 右移31位 
                  // 对于右移:
                  // 首位是1的二进制(有符号数),是算数右移,即右移后左边补1
                  // 首位是0的二进制(无符号数),是逻辑左移,即右移后左边补0
            // 3. 将上述二者进行异或
    
            // 对于sint 64 数据类型 则为: return  (n << 1> ^ (n >> 63) ;
    }
    
    
    // 附:将Zigzag值解码为整型值
    public int zigzag_to_int(int n) 
    {
            return(n >>> 1) ^ -(n & 1);
    // 右移时,需要用不带符号的移动,否则如果第一位数据位是1的话,就会补1
    }
     
    
    
    • 实例说明:将 -2进行 Zigzag编码:

    Zigzag编码

    • Zigzag 编码 是补充 Varint编码在 表示负数 的不足,从而更好的帮助 Protocol Buffer进行数据的压缩
    • 所以,如果提前预知字段值是可能取负数的时候,记得采用sint32 / sint64 数据类型

    总结

    Protocol Buffer 通过VarintZigzag编码后大大减少了字段值占用字节数。

    7.1.2 存储方式:T - V

    • 消息字段的标识号、数据类型 & 字段值经过 Protocol Buffer采用 Varint & Zigzag 编码后,以 T - V 方式进行数据存储

    对于 Varint & Zigzag 编码,省略了T - L - V中的字节长度Length

    Varint & Zigzag数据存储方式

    下面将详细介绍T - V 存储方式中的存储细节:Tag & Value

    1. Tag

    • 定义:经过 Protocol Buffer采用Varint & Zigzag编码后 的消息字段 标识号 & 数据类型 的值
    • 作用:标识 字段
    1. 存储了字段的标识号(field_number)和 数据类型(wire_type),即Tag = 字段数据类型(wire_type) + 标识号(field_number
    2. 占用 一个字节 的长度(如果标识号超过了16,则占用多一个字节的位置)
    3. 解包时,Protocol Buffer根据 TagValue 对应于消息中的 字段
    • 具体使用
    // Tag 的具体表达式如下
     Tag  = (field_number << 3) | wire_type
    // 参数说明:
    // field_number:对应于 .proto文件中消息字段的标识号,表示这是消息里的第几个字段
    // field_number << 3:表示 field_number = 将 Tag的二进制表示 右移三位 后的值 
    // field_num左移3位不会导致数据丢失,因为表示范围还是足够大地去表示消息里的字段数目
    
    //  wire_type:表示 字段 的数据类型
    //  wire_type = Tag的二进制表示 的最低三位值
    //   wire_type的取值
     enum WireType { 
          WIRETYPE_VARINT = 0, 
          WIRETYPE_FIXED64 = 1, 
          WIRETYPE_LENGTH_DELIMITED = 2, 
          WIRETYPE_START_GROUP = 3, 
          WIRETYPE_END_GROUP = 4, 
          WIRETYPE_FIXED32 = 5
       };
    
    // 从上面可以看出,`wire_type`最多占用 3位 的内存空间(因为 3位 足以表示 0-5 的二进制)
    
    //  以下是 wire_type 对应的 数据类型 表
    

    wire_type对应数据类型

    • 实例说明
    // 消息对象
     message person
     { 
        required int32     id = 1;  
        // wire type = 0,field_number =1 
        required string    name = 2;  
        // wire type = 2,field_number =2 
      }
    
    //  如果一个Tag的二进制 = 0001 0010
    标识号 = field_number = field_number  << 3 =右移3位 =  0000 0010 = 2
    数据类型 = wire_type = 最低三位表示 = 010 = 2
    

    2. Value

    经过 Protocol Buffer采用Varint & Zigzag编码后 的消息字段的值

    7.1.3 实例说明

    下面通过一个实例进行整个编码过程的说明:

    • 消息说明
    message Test
    {
    
    required int32 id1 = 1;
    
    required int32 id2 = 2;
    }
    
    // 在代码中给id1 附上1个字段值:296
    // 在代码中给id2 附上1个字段值:296
    Test.setId1(300);
    Test.setId2(296);
    
    // 编码结果为:二进制字节流 = [8,-84,2,16, -88, 2]
    
    • 整个编码过程如下

    编码过程


    7.2 Wire Type = 1& 5时的编码&数据存储方式

    Wire Type = 1& 5时的编码&数据存储方式

    • 64(32)-bit编码方式较简单:编码后的数据具备固定大小 = 64位(8字节) / 32位(4字节)

    两种情况下,都是高位在后,低位在前

    • 采用T - V方式进行数据存储,同上。

    7.3 Wire Type = 2时的 编码 & 数据存储方式

    Wire Type = 2时的编码&数据存储方式

    • 对于编码方式:

    编码方式

    • 数据存储方式: T - L - V

    数据存储示意图

    此处主要讲解三种数据类型:

    • String类型
    • 嵌套消息类型(Message
    • 通过packed修饰的 repeat 字段(即packed repeated fields

    1. String类型

    字段值(即V) 采用UTF-8编码

    编码 & 存储方式

    • 例子:
    message Test2
    {
        required string str = 2;
    }
    
    // 将str设置为:testing
    Test2.setStr(“testing”)
    
    // 经过protobuf编码序列化后的数据以二进制的方式输出
    // 输出为:18, 7, 116, 101, 115, 116, 105, 110, 103
    
    

    实例

    2. 嵌套消息类型(Message)

    • 存储方式:T - L - V
    1. 外部消息的 V即为 嵌套消息的字段
    2. T - L -V 里嵌套了一系列的 T - L -V
    • 编码方式:字段值(即V) 根据字段的数据类型采用不同编码方式

    编码 & 存储方式

    • 实例
      定义如下嵌套消息:
    message Test2
    {
        required string str = 1;
        required int32 id1 = 2;
    
        
    }
    
    message Test3 {
      required Test2 c = 1;
    }
    
    // 将Test2中的字段str设置为:testing
    // 将Test2中的字段id1设置为:296
    // 编码后的字节为:10 ,12 ,18,7,116, 101, 115, 116, 105, 110, 103,16,-88,2
    

    编码 & 存储方式如下

    编码 & 存储方式

    3. 通过packed修饰的 repeat 字段

    repeated 修饰的字段有两种表达方式:

    message Test
    {
        repeated int32 Car = 4 ;
        // 表达方式1:不带packed=true
    
        repeated int32 Car = 4 [packed=true];
        // 表达方式2:带packed=true
        // proto 2.1 开始可使用
    
    // 区别在于:是否连续存储repeated类型数据
    }
    
    
    // 在代码中给`repeated int32 Car`附上3个字段值:3、270、86942
    
    Test.setCar(3);
    Test.setCar(270);
    Test.setCar(86942);
    
    • 背景:对于同一个 repeated字段、多个字段值来说,他们的Tag都是相同的,即数据类型 & 标识号都相同

    repeated类型可以看成是数组

    • 问题:若以传统的多个 T - V对存储(不带packed=true),则会导致Tag的冗余,即相同的Tag存储多次;

    不带pack的存储方式

    • 解决方案:采用带packed=truerepeated 字段存储方式,即将相同的 Tag 只存储一次、添加 repeated 字段下所有字段值的长度Length、连续存储 repeated 字段值,组成一个大的Tag - Length - Value -Value -Value对,即T - L - V - V - V对。

    带pack的存储方式

    通过采用带packed=truerepeated 字段存储方式,从而更好地压缩序列化后的数据长度。

    特别注意

    • Protocol Bufferpacked修饰只用于repeated字段 或 基本类型的repeated字段
    • 用在其他字段,编译 .proto 文件时会报错

    8. 特别注意

    • 注意1:若 required字段没有被设置字段值,那么在IsInitialized()进行初始化检查会报错并提示失败

    所以 required字段必须要被设置字段值

    • 注意2:序列化顺序 是根据 Tag标识号 从小到大 进行编码

    .proto文件内 字段定义的数据无关

    • 注意3:T - V的数据存储方式保证了Protobuf的版本兼容:高<->低 或 低<->高都可以适配

    若新版本 增加了 required 字段, 旧版本 在数据解码时会认为IsInitialized() 失败,所以慎用 required字段


    9. 使用建议

    根据上面的序列化原理分析,我总结出以下Protocol Buffer的使用建议

    通过下面建议能有效降低序列化后数据量的大小

    • 建议1:多用 optionalrepeated修饰符
      因为若optionalrepeated 字段没有被设置字段值,那么该字段在序列化时的数据中是完全不存在的,即不需要进行编码

    相应的字段在解码时才会被设置为默认值

    • 建议2:字段标识号(Field_Number)尽量只使用 1-15,且不要跳动使用
      因为Tag里的Field_Number是需要占字节空间的。如果Field_Number>16时,Field_Number的编码就会占用2个字节,那么Tag在编码时也就会占用更多的字节;如果将字段标识号定义为连续递增的数值,将获得更好的编码和解码性能

    • 建议3:若需要使用的字段值出现负数,请使用 sint32 / sint64,不要使用int32 / int64
      因为采用sint32 / sint64数据类型表示负数时,会先采用Zigzag编码再采用Varint编码,从而更加有效压缩数据

    • 建议4:对于repeated字段,尽量增加packed=true修饰
      因为加了packed=true修饰repeated字段采用连续数据存储方式,即T - L - V - V -V方式


    10. 序列化 & 反序列化过程

    • Protocol Buffer除了序列化 & 反序列化后的数据体积小,序列化 & 反序列化的速度也非常快
    • 下面我将讲解序列化 & 反序列化的序列化过程

    10.1 Protocol Buffer的序列化 & 反序列化过程

    序列化过程如下:

    1. 判断每个字段是否有设置值,有值才进行编码
    2. 根据 字段标识号&数据类型 将 字段值 通过不同的编码方式进行编码

    由于:
    a. 编码方式简单(只需要简单的数学运算 = 位移等等)
    b. 采用 Protocol Buffer 自身的框架代码 和 编译器 共同完成

    所以Protocol Buffer的序列化速度非常快。

    反序列化过程如下:

    1. 调用 消息类的 parseFrom(input) 解析从输入流读入的二进制字节数据流

    从上面可知,Protocol Buffer解析过程只需要通过简单的解码方式即可完成,无需复杂的词法语法分析,因此 解析速度非常快。

    1. 将解析出来的数据 按照指定的格式读取到 JavaC++Phyton 对应的结构类型中

    由于:
    a. 解码方式简单(只需要简单的数学运算 = 位移等等)
    b. 采用 Protocol Buffer 自身的框架代码 和 编译器 共同完成

    所以Protocol Buffer的反序列化速度非常快。

    10.2 对比于XML 的序列化 & 反序列化过程

    XML的反序列化过程如下:

    1. 从文件中读取出字符串
    2. 将字符串转换为 XML 文档对象结构模型
    3. XML 文档对象结构模型中读取指定节点的字符串
    4. 将该字符串转换成指定类型的变量

    上述过程非常复杂,其中,将 XML 文件转换为文档对象结构模型的过程通常需要完成词法文法分析等大量消耗 CPU 的复杂计算。

    因为序列化 & 反序列化过程简单,所以序列化 & 反序列化过程速度非常快,这也是 Protocol Buffer效率高的原因


    11.总结

    • Protocol Buffer的序列化 & 反序列化简单 & 速度快的原因是:
      a. 编码 / 解码 方式简单(只需要简单的数学运算 = 位移等等)
      b. 采用 Protocol Buffer 自身的框架代码 和 编译器 共同完成

    • Protocol Buffer的数据压缩效果好(即序列化后的数据量体积小)的原因是:
      a. 采用了独特的编码方式,如VarintZigzag编码方式等等
      b. 采用T - L - V 的数据存储方式:减少了分隔符的使用 & 数据存储得紧凑


    接下来我会讲解Protocol Buffer的源码分析,感兴趣的同学可以继续关注carson_ho的微信公众号
    示意图
    示意图


    请帮顶 / 评论点赞!因为你的鼓励是我写作的最大动力!

    展开全文
  • 缓冲区的4个概念: position :当前位置 mark :标记位置(可以reset直接跳到标记位置) limit :允许读取的位置 capacity:缓冲区大小 缓冲区的使用相当于position的移动(最大到limit位置)每读多少就移动...

    缓冲区的4个概念:

    1. position :当前位置
    2. mark :标记位置(可以reset直接跳到标记位置)
    3. limit :允许读取的位置
    4. capacity:缓冲区大小

    缓冲区的使用相当于position的移动(最大到limit位置)每读多少就移动多少。 

    import org.junit.jupiter.api.Test;
    
    import java.nio.ByteBuffer;
    
    public class BufferTest {
        /**
         * 存取过程
         */
        @Test
        public void saveAndRead(){
            String str="test save";
            //存过程
            ByteBuffer byteBuffer=ByteBuffer.allocate(1024);
            byteBuffer.put(str.getBytes());
    
            //取过程
            //首先切换模式flip()一下
            byteBuffer.flip();
            //创建一个数组
            byte[]dataStr=new byte[byteBuffer.limit()];
            byteBuffer.get(dataStr,0,2);//读取缓冲去的字符流到dataStr数组中起始位置0,读2个字节
        }
    
        /**
         * 常用方法
         */
        @Test
        public void methods(){
    
            //1.创建一个指定大学的缓冲区
            ByteBuffer byteBuffer=ByteBuffer.allocate(1024);
    
            //2.put方法存入数据
            byteBuffer.put("Hello world".getBytes());
    
            //3.切换读取模式
            byteBuffer.flip();
    
            //4.get方法读取缓冲区
            byte[] dataStr=new byte[byteBuffer.limit()];
    
            //5.rewind():可重复读
            byteBuffer.rewind();
    
            //6.clear清空缓冲区,缓冲区数据依然存在只是 位置被重新置0
            byteBuffer.clear();
    
            //7.标记 指针当前记录位置
            byteBuffer.mark();
    
            //8.回到标记位置
            byteBuffer.reset();
    
            /**
             * byteBuffer的4个概念
             * position,mark,limit,capacity
             * position <= mark <= limit <= capacity
             */
            byteBuffer.limit();
            byteBuffer.position();
            byteBuffer.capacity();
    
            //9.是否有剩余数据
            byteBuffer.hasRemaining();
    
        }
    }
    

    需要注意的是读取get方法通过传入的参数不同分别代表了不同的方式

    get()读取一个字节

    get(byte [] dst)读取字节到字节数组中

    get(int index)从那个位置开始读

    get(byte [] dst ,int offset,int length)读取字节到dst数组中,从offset开始读取length个字节

    同理:getChar()

    类似

     

     

     

     

     

    展开全文
  • Stencil buffer

    千次阅读 2015-06-24 20:40:46
    模版缓冲(stencil buffer)或印模缓冲,是在OpenGL三维绘图等计算机图像硬件中常见的除颜色缓冲、像素缓冲、深度缓冲之外另一种数据缓冲。词源模版(stencil)是指一种印刷技术,通常以蜡纸或者钢板印刷文字或图形...

    Stencil buffer 

    模版缓冲(stencil buffer)或印模缓冲,是在OpenGL三维绘图等计算机图像硬件中常见的除颜色缓冲、像素缓冲、深度缓冲之外另一种数据缓冲。词源模版(stencil)是指一种印刷技术,通常以蜡纸或者钢板印刷文字或图形;区别于模板(template),用木板为外形修剪的依据来复制形状;模版(stencil)是指印模,而模板(template)主要是指形模。模版缓冲是以像素为单位的,整数数值的缓冲,通常给每个像素分配一个字节长度的数值。深度缓冲与模版缓冲经常在图形硬件的随机存取内存(RAM)中分享相同的区域。

    模板缓冲所在的是整个流水线的最后一个阶段,这个阶段的流水线如下





    最简单的情况,模版缓冲被用于限制渲染的区域。更多高级应用会利用深度缓冲与模版缓冲的在图形渲染流水线中的强关联关系。例如,模版的数值可以按每个像素是否通过深度测试来自动增加或减少。

    简单组合使用深度测试与模版修饰符可以使得大量的本来需要多次渲染过程的效果(例如阴影、外形的绘制或复合几何图元(Geometric primitive)的交叉部分的高光处理)可以简单实现,因此减轻了图形硬件的负担。

    最典型的应用是给三维图像加阴影。也用于平面反射。

    其它渲染的技术,例如,视口渲染(portal rendering),利用模版缓冲作其它用途。例如,它可以被用于查找被视口遮蔽的屏幕区域然后重新正确渲染这些像素点。

    模版缓冲与其修饰符可以通过OpenGL或Direct3D的应用程序编程接口(API)来访问。





    常用的比较操作


     
    GreaterOnly render pixels whose reference value is greater than the value in the buffer.
    GEqualOnly render pixels whose reference value is greater than or equal to the value in the buffer.
    LessOnly render pixels whose reference value is less than the value in the buffer.
    LEqualOnly render pixels whose reference value is less than or equal to the value in the buffer.
    EqualOnly render pixels whose reference value equals the value in the buffer.
    NotEqualOnly render pixels whose reference value differs from the value in the buffer.
    AlwaysMake the stencil test always pass.
    NeverMake the stencil test always fail.

    模版像素操作


     
    KeepKeep the current contents of the buffer.
    ZeroWrite 0 into the buffer.
    ReplaceWrite the reference value into the buffer.
    IncrSatIncrement the current value in the buffer. If the value is 255 already, it stays at 255.
    DecrSatDecrement the current value in the buffer. If the value is 0 already, it stays at 0.
    InvertNegate all the bits.
    IncrWrapIncrement the current value in the buffer. If the value is 255 already, it becomes 0.
    DecrWrapDecrement the current value in the buffer. If the value is 0 already, it becomes 255.

    Zfail
    What to do with the contents of the buffer if the stencil test passes, but the depth test fails. Default: keep.

    例子


    下面是Unity文档里的例子,文档有点错误,按照文档的代码是写不出对应的结果的。

    首先在场景里放一个红球,Shader如下
    Shader "Custom/RedStencil" {
    
    	SubShader {
    		  Tags { "RenderType"="Opaque" "Queue"="Geometry"}
            Pass {
                Stencil {
                    Ref 2
                    Comp always
                    Pass replace
                    ZFail decrWrap
                }
            
                CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag
                struct appdata {
                    float4 vertex : POSITION;
                };
                struct v2f {
                    float4 pos : SV_POSITION;
                };
                v2f vert(appdata v) {
                    v2f o;
                    o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
                    return o;
                }
                half4 frag(v2f i) : SV_Target {
                    return half4(1,0,0,1);
                }
                ENDCG
            }
    		}
    }
    

    结果如下




    stencil的值在球体绘制的地方被赋为2,没有绘制的地方为0.

    接下来画绿色的球
    Shader "Custom/GreenStencil" {
    	SubShader {
     Tags { "RenderType"="Opaque" "Queue"="Geometry+1"}
            Pass {
                Stencil {
                    Ref 2
                    Comp equal
                    Pass keep 
                    Fail decrWrap 
                    ZFail IncrSat
                }
            
                CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag
                struct appdata {
                    float4 vertex : POSITION;
                };
                struct v2f {
                    float4 pos : SV_POSITION;
                };
                v2f vert(appdata v) {
                    v2f o;
                    o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
                    return o;
                }
                half4 frag(v2f i) : SV_Target {
                    return half4(0,1,0,1);
                }
                ENDCG
            }
    	} 
    	FallBack "Diffuse"
    }
    



    绘制结果如下,绿色的部分是stencil pass的,绿球没有被绘制出来的地方stecil值会减一,变为255.有一部分通过的stencil test,但是没有通过ztest的,stencil值+1,变成3



    最后画蓝色的球,shader如下
    Shader "Custom/BlueStencil" {
    	SubShader {
    	  Tags { "RenderType"="Opaque" "Queue"="Overlay"}
            Pass {
                Stencil {
                    Ref 3
                    Comp Equal
                }
            
                CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag
                struct appdata {
                    float4 vertex : POSITION;
                };
                struct v2f {
                    float4 pos : SV_POSITION;
                };
                v2f vert(appdata v) {
                    v2f o;
                    o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
                    return o;
                }
                half4 frag(v2f i) : SV_Target {
                    return half4(0,0,1,1);
                }
                ENDCG
            }
    	}
    }
    




    蓝色球只在stencil buffer 值为3的地方绘制出来了。

    参考

    ShaderLab: Stencil - http://docs.unity3d.com/Manual/SL-Stencil.html
    Extra buffers - https://open.gl/depthstencils
    OpenGL Programming/Stencil buffer - https://en.wikibooks.org/wiki/OpenGL_Programming/Stencil_buffer

    展开全文
  • bounce buffer

    千次阅读 2012-07-07 01:05:18
    在 IA-32 系统中,物理内存最开始的1GB 被称为“低端内存”,1GB 以上的部分称为“高端内存”。先前的Linux 核心版本要求通往存储设备的数据缓存必须放在物理RAM 的低端内存区域,即使是应用程序可以同时使用高端...
  • 通道(Channel)与缓冲区(Buffer

    万次阅读 2019-12-13 01:06:47
    Channel负责传输、Buffer负责存储 Java NIO系统的核心在于: 通道(Channel)和缓冲区(Buffer)。通道表示打开到 IO 设备(例如:文件、套接字)的连接。若需要使用NIO 系统,需要获取用于连接 IO 设备的通道以及用于...
  • var imgData = new Buffer(body,'binary'); resolve(imgData); console.log(imgData); }else{ reject(error); } }); }); } url打开后就是一个图片(微信头像) console.log(imgData) <Buffer fd fd fd...
  • Z buffer 和 W buffer 簡介

    千次阅读 2007-11-02 17:38:00
    不過,還是常常可以看到有人對 Z buffer 和 W buffer 有一些基本的問題,像是 Z buffer 的用途、Z buffer 和 W buffer 的差別、或是一些精確度上的問題等等。這篇文章的目的就是要簡單介紹一下 Z buffer 和 W bu
  • 详细介绍Z-Buffer与W-Buffer

    千次阅读 2010-04-26 08:57:00
    详细介绍Z-Buffer与W-Buffer Depth-Buffer(深度缓存)有两种:Z-Buffer 和 W-Buffer,这里讨论这两种深度缓存的区别,以及如何在两者之间转换。 w 的含义 3D空间点的坐标是(x,y,z),为了使...
  • glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); glBindBuffer(GL_ARRAY_BUFFER, BufferName[0]); //glBufferData(GL_ARRAY_BUFFER, sizeof(vertexData), vertexData, GL_STATIC...
  • 最近服务器存在掉包的现象,在网上是修改ring buffer的大小就可以避免丢包的现象 修改命令:ethtool -g eth0 rx 2047 Ring parameters for eth0: Pre-set maximums: RX: 2047 RX Mini: 0 RX Jumbo: 0 TX: 511 ...
  • stream buffer原理

    千次阅读 2014-11-26 16:00:25
    Stream buffer是一个用于在cache和memory或者L1cache和L2cache之间的预取器,相应地,其目的是用于替代L2cache或者减少L1cache的缺失率 最原始的stream buffer由Jouppi(Improving direct-mapped cache performance ...
  • Vertex Buffer Objects

    千次阅读 2009-11-18 06:34:00
    Vertex Buffer Objects (VBOs) are Buffer Objects that are used for vertex data. Since the storage for buffer objects is allocated by OpenGL, vertex buffer objects are a mechanism for sto
  • Java NIO Buffer

    千次阅读 2014-11-20 08:48:44
    Java NIO Buffer
  • 设置buffer cache

    千次阅读 2012-07-23 21:59:33
    buffer cache的设置随着Oracle版本的升级而不断变化。Oracle 8i下使用db_block_buffers来设置,该参数表示buffer cache中所能够包含的内存数据块的个数;Oracle 9i以后使用db_cache_size来设置,该参数表示buffer ...
  • iOS stencil buffer

    千次阅读 2011-06-07 10:32:00
    iOS stencil buffer Both ES1.1 and ES2.0 support stencil operations.However the availability of a stencil buffer is renderer-dependent. On iPho
  • 我在decoder中解析数据并处理粘包的问题,模拟到了一种情况就是收到的是断包,且这段断包为一段完整数据包的后半段(实际上就是无用的了),想去除这段数据,也就是清空IoBuffer。看了一下api貌似没有彻底清空的...
  • buffer,双buffer和三buffer的区别

    千次阅读 2015-08-04 15:26:38
  • Z buffer 和 W buffer

    千次阅读 2009-12-03 00:21:00
    不过,还是常常可以看到有人对 Z buffer 和W buffer 有一些基本的问题,像是 Z buffer 的用途、Z buffer 和 W buffer的差别、或是一些精确度上的问题等等。这篇文章的目的就是要简单介绍一下 Z buffer 和 W buffer。...
  • 1、问题背景 将不同的Buffer对象重新结合为一个新的Buffer对象2、实现源码> A=new Buffer('AA'); > B=new Buffer('BB'); > C=new Buffer('CC'); > D=new Buffer('DD'); > E=new Buffer('EE'); > F=new Buffer...
  • 文章目录前言Heap-buffer-overflowHeap-use-after-freeStack-buffer-overflowGlobal-buffer-overflow 前言 在做LeetCode题时发现一个有趣的事情。 对于C语言来说,如果直接访问超出Index的数组,会报错: int main...
  • //开辟缓冲区buffer byte[] buffer = new byte[1024]; int k=1; int num=0; public void run(){ try { while(count==0) { Log.e(TAG, "等待"); count =is1.available(); } ...
  • ``` import requests import re #这是用requests进行的数据爬取 url = 'https://car.autohome.com.cn/photo/series/26709/1/3793691.html' ...TypeError: expected string or buffer ```
  • 求助代码 import urllib2 import re import os headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64;...TypeError: expected string or buffer Process finished with exit code 1
  • Android MediaPlayer buffer大小

    千次阅读 2018-07-18 16:24:36
    Android MediaPlayer buffer 前几天用VideoView (MediaPlayer+SurfaceView) 做一个类似于抖音APP的短视频Demo(测试机型 Android8.0 小米6),发现MediaPlayer onPrepared的时间非常长,好像把一个不到10M的视频全部...
  • 代码如下: ``` JsonObject jsonObject = new JsonParser...是不是和这个方法的两个重载方法有关 buffer(distance, quadrantSegments)和buffer(distance, quadrantSegments, endCapStyle) 网上实在找不到相关api
  • byte[] buffer = new byte[1024 * 1024]; int readCount = inputStream.Read(buffer, 0, toReadCount); 其中inputStream是Stream类型 其中toReadCount一般等于buffer.Length 为什么每次Read方法的返回值readCount...
  • Buffer size of router

    千次阅读 2012-08-15 11:06:13
    Data buffer   Buffers are typically used when there is a difference between the rate at which data is received and the rate at which it can be processed, or in the case that these rates are ...

空空如也

1 2 3 4 5 ... 20
收藏数 82,926
精华内容 33,170
关键字:

buffer