【oa工作流源码】【html查看源码网页】【2020spring源码】buffer 源码注释

时间:2024-12-22 19:15:23 分类:分块查找源码 来源:abp vnext 源码结构

1.stringbuffer与stringbuilder的区别?源码
2.FFplay源码分析-nobuffer
3.Protocol Buffer详解(一)
4.深入理解DirectBuffer
5.String,StringBuffer和StringBuilder的区别

buffer 源码注释

stringbuffer与stringbuilder的区别?

       äºŒè€…的区别主要是在运行速度和线程安全这两方面。

       1、StringBuffer 与 StringBuilder 中的方法和功能完全是等价的

       2、只是StringBuffer 中的方法大都采用了 synchronized å…³é”®å­—进行修饰,因此是线程安全的,而 StringBuilder 没有这个修饰,可以被认为是线程不安全的。

       3、在单线程程序下,StringBuilder效率更快,因为它不需要加锁,不具备多线程安全而StringBuffer则每次都需要判断锁,效率相对更低。

FFplay源码分析-nobuffer

       在使用 FFplay 播放 RTMP 流时,不开启 nobuffer 选项会导致画面延迟高达7秒左右,注释而开启此选项后,源码局域网延迟可降低到毫秒左右。注释因此,源码本文将深入探讨nobuffer的注释oa工作流源码实现细节,以及播放端缓存7秒数据的源码作用。

       fflags 的注释定义在 libavformat/options_table.h 文件中,这是源码一个通用选项,所有解复用器均包含此选项。注释在调用 avformat_open_input() 函数时,源码会将该命令行参数传入,注释其位置与所有格式参数相同,源码如在之前的注释文章《FFplay源码分析》中所述。记得在调试参数中添加-fflags nobuffer。源码

       在 avformat_open_input() 函数内部,fflags 这个 AVOption 会被传递给 AVClass,该类存储了多个 AVOption,而fflags 的索引为5。在 av_opt_set_dict() 函数中,fflags 的值会被应用并清除其他选项。在 avformat_open_input() 执行完毕后,AVFormatContext::flags 的第7位应被置为1,即二进制的 。通过下图可以清晰地看到这个过程。html查看源码网页

       在 avformat_find_stream_info() 函数内部,如果没有设置nobuffer标记,探测的数据包将被丢入队列。avformat_find_stream_info() 首先读取一段数据包以分析输入流的编码器等信息,为了重用这些数据包,它们会被放入队列中。然而,整个探测过程长达5秒,这意味着 FFplay 大概会读取5秒的数据来分析输入流。若开启nobuffer,则不会重复使用这些探测数据,FFplay 探测完输入流后,会读取新的数据包进行播放。无需缓存,从而降低了延迟。

       通过在 ffpaly.c 文件中的 avformat_find_stream_info() 函数前后输出时间,可以发现两者相差5秒,直观展示了nobuffer对于降低延迟的作用。在实时场景下,缓存功能变得多余,它原本是为了分析本地文件,避免重复读取,但在实时场景中反而影响了性能。因此,2020spring源码在实时场景中,关闭缓存更为合适。

       补充说明:若在本地虚拟机环境下,不启用缓存也能实现流畅播放。然而,如果 SRS 部署在局域网的另一台机器上,不开启缓存可能导致视频卡顿,原因可能是解码前未能及时读取视频帧,FFplay 不断丢弃视频帧,尤其是当视频比音频慢时,这种情况下缓存功能反而成为瓶颈。

Protocol Buffer详解(一)

       Protocol Buffer是一种支持多平台、多语言、可扩展的数据序列化机制,与XML相比,protobuf体积更小、速度更快、使用更简单,支持自定义数据结构。通过protobu编译器,可以生成特定语言的源代码,如C++、Java、Python,绿豆影视源码5.1.3protoBuf对主流编程语言都提供了支持,使得序列化和反序列化变得非常方便。

       一、Message定义

       这里给出一个简单的例子,是一个搜索请求的message格式。

       上述例子中fields的种类都是数值型的(string和int),当然也可以指定更加复杂的fields,比如枚举类型enum,或者是嵌套的message类型。

       1、分配field编号

       上述例子中每个field都被分配了一个编号,这个编号是该field的唯一标识。需要注意的是,标识1-在编码时只占用一个字节,-占用两个字节,因此为了进一步优化程序,对于经常出现的element,建议使用1-作为其唯一标识;对于不经常使用的element,建议使用-。编号的范围是1-2^(-是系统预留的,不要使用)。

       2、field类型

       message中的field类型包含以下两种(proto3):

       (1)singular

       (2)repeated:该类型的field可以在message中重复使用(类似于数组),它们的仿东郊到家源码顺序会被保存,通过索引进行检索,数值类型的repeated默认使用packed编码方式。

       3、多message结构

       在一个proto文件中可以定义多个protobuf。

       4、reserved field类型

       在开发过程中可能会涉及到对proto文件中message各个fields的修改,可能是更新、删除某个field及其表示,这样可能会导致调用的服务失败。其中一个防止这种问题的方式是,确保你要删除的field的标识(或是名字)是reserved,具体protobuf的编译器会决定未来这个field表示能否被使用。

       5、编译结果

       对于C++开发者来说,使用protoc编译一个proto文件之后,会生成pb.h和pb.cc两个文件。

       二、数值类型

       具体proto类型对应生成类中的类型可以参考官方文档。

       三、默认值

       对于string和byte类型,默认值为空;对于bool类型,默认值是false;对于数值类型,默认值是0;对于枚举类型,默认值是第一个枚举值,默认为0;对于message类型,默认值由编程语言决定;对于repeated field,默认值为空。

       四、枚举类型

       当采用枚举类型的之后,枚举中的值都是预先定义好的,对于上述例子,我们可以再额外增加一个枚举类型corpus,具体如下。

       通常枚举类型的第一个值初始化为0,而且在message中使用枚举类型,必须要给定一个为0的值,而且这个为0的值应该为第一个元素。

       也可以给不同的元素以相同的alias,但是需要指定option allow_alias = true;具体如下。

       除此之外枚举类型不仅可以定义在message内部,也可以定义在message外部,而且在不同message中可以重用enum。

       在更改枚举类型field时,为保证系统运行正常,同样可以指定reserved数字标识和命名。

       五、使用其他message类型

       1、同文件引用

       具体如下:

       2、不同文件引用

       引用其他proto文件中定义好的message类型,具体如下。

       有时我们会对引用的proto文件进行更改,比如将其内容移动到另外一个地方,这样我们就需要对调用方import路径进行更改,当调用方非常多的时候,这种方法是非常低效的,protobuf提供一种机制,我们可以在原有位置提供一个新位置proto文件的“副本”,通过使用import public表示来实现,具体可以参考如下例子。

       这时编译器就会在某些固定目录下查询import的proto文件(具体在命令行编译的时候,由-I/—proto_path指定),如果上述路径找不到,编译器会在调用路径进行查找。通常将—proto_path设置为项目的根目录,然后import的时候使用完整的路径名。

       3、使用proto2中的message类型

       proto2中的枚举类型无法直接使用。

       六、嵌套类型

       具体如下。

       在parent message之外调用嵌套的message可以用如下方式:SearchResponse.Result,嵌套结构可以更加复杂,具体如下:

       七、更新message类型

       当现有的message已经无法满足现有业务需要,你需要更新你的message类型以支持更复杂的业务,这就涉及到向后兼容的问题了,为保证已有服务不受影响,需要遵守以下的一些规定:

       1、不要更改已经存在的fields的数字标识

       2、如果添加新的field,利用旧代码序列化得到的message可以使用新的代码进行解析,你需要记住各个元素的默认值。新代码创建的field同样可以由旧代码进行加解析

       3、field可以被删除,但是需要保证其对应的数字标识不再被使用,你可以通过加前缀的方式来重新使用这个field name,或者指定数字标识为reserved来避免这种情况

       4、int、int、uint、uint、bool这些类型都是互相兼容的,并不会影响前向、后向兼容性

       5、sint和sint之间是互相兼容的,但是和其他数字类型是不兼容的

       6、string和bytes是互相兼容的,只要使用的是UTF-8编码

       7、如果byte包含message的编码版本,则嵌套的message和bytes兼容

       8、flexed兼容sfixed,fixed,sfixed

       9、enum兼容 int, uint, int, and uint。对于这个值在转化时,不同语言的客户端处理方式会有所不同

       感兴趣的小伙伴可以关注公众号:独立团丶

深入理解DirectBuffer

       DirectBuffer在高性能场景中,因其堆外内存的特性,相较于ByteBuffer,能有效提升数据处理效率。本文将从源码角度深入解析DirectBuffer的原理和使用方式。

       在Intel X架构下,用户态(Ring3)与内核态(Ring0)的划分保证了安全隔离。应用程序通过系统调用,将需要内核支持的任务委托给运行在Ring0的内核。创建DirectBuffer时,调用new DirectByteBuffer(int cap)的私有构造函数,它完成内存分配、大小记录和Cleaner对象的声明,以备后续内存清理。

       使用DirectBuffer时,主要有putXXX和getXXX方法。putXXX如putInt,根据内存对齐和字节序,调用unsafe或Bits方法将数据写入。getXXX则根据对齐情况,通过相应方法读取数据。

       内存回收有System.gc和Cleaner对象两种方式。System.gc会在内存不足且没有禁用显式GC时触发Full GC,尝试清理堆外内存。Cleaner对象则在DirectBuffer不再被引用时自动执行,释放堆外内存。

       正确运用DirectBuffer,能够优化程序性能,减少GC的频繁发生。在高性能中间件中,它是一个实用且重要的工具。深入了解DirectBuffer的使用,对提高开发效率至关重要。

String,StringBuffer和StringBuilder的区别

       java中String、StringBuffer、StringBuilder是编程中经常使用的字符串类,他们之间的区别也是经常在面试中会问到的问题。现在总结一下,看看他们的不同与相同。

       1.可变与不可变

       ã€€ã€€String类中使用字符数组保存字符串,如下就是,因为有“final”修饰符,所以可以知道string对象是不可变的。

       ã€€ã€€ã€€ã€€private final char value[];

       ã€€ã€€StringBuilder与StringBuffer都继承自AbstractStringBuilder类,在AbstractStringBuilder中也是使用字符数组保存字符串,如下就是,可知这两种对象都是可变的。

       ã€€ã€€ã€€ã€€char[] value;

       2.是否多线程安全

       ã€€ã€€String中的对象是不可变的,也就可以理解为常量,显然线程安全。

       ã€€ã€€AbstractStringBuilder是StringBuilder与StringBuffer的公共父类,定义了一些字符串的基本操作,如expandCapacity、append、insert、indexOf等公共方法。

       ã€€ã€€StringBuffer对方法加了同步锁或者对调用的方法加了同步锁,所以是线程安全的。看如下源码:

1 public synchronized StringBuffer reverse() {

       2     super.reverse();

       3     return this;

       4 }

       5 

       6 public int indexOf(String str) {

       7     return indexOf(str, 0);        //存在 public synchronized int indexOf(String str, int fromIndex) æ–¹æ³•

       8 }

       ã€€ã€€StringBuilder并没有对方法进行加同步锁,所以是非线程安全的。

        3.StringBuilder与StringBuffer共同点

       ã€€ã€€StringBuilder与StringBuffer有公共父类AbstractStringBuilder(抽象类)。

       ã€€ã€€æŠ½è±¡ç±»ä¸ŽæŽ¥å£çš„其中一个区别是:抽象类中可以定义一些子类的公共方法,子类只需要增加新的功能,不需要重复写已经存在的方法;而接口中只是对方法的申明和常量的定义。

       ã€€ã€€StringBuilder、StringBuffer的方法都会调用AbstractStringBuilder中的公共方法,如super.append(...)。只是StringBuffer会在方法上加synchronized关键字,进行同步。

       ã€€ã€€æœ€åŽï¼Œå¦‚果程序不是多线程的,那么使用StringBuilder效率高于StringBuffer。