内部简单二进制编码(SBE)

SBE是用于金融行业的非常快速的序列化库,在本博客中,我将介绍一些使其快速发展的设计选择。

序列化的全部目的是对消息进行编码和解码,并且有很多可用的选项,从XML,JSON,Protobufer,Thrift,Avro等开始。

XML / JSON是基于文本的编码/解码,在大多数情况下都很好,但是当延迟很重要时,这些基于文本的编码/解码就会成为瓶颈。

Protobuffer / Thrift / Avro是二进制选项,使用非常广泛。

SBE也是二进制的,是基于机械同情而构建的,以利用基础硬件(CPU缓存,预取程序,访问模式,管线指令等)的优势。

CPU和内存革命的小历史。

我们的行业看到了功能强大的8位,16位,32位,64位处理器,现在普通的台式机CPU可以执行近数十亿条指令,只要程序员能够编写程序来生成这种类型的负载即可。 内存也变得便宜,获得512 GB服务器非常容易。

我们必须改变编程方式以利用所有这些东西,数据结构和算法也必须改变。

让我们潜入sbe。

全栈方法

大多数系统依赖于运行时优化,但是SBE已采用全栈方法,并且第一级优化由编译器完成。

预算局

模式 –用于定义消息的布局和数据类型的XML文件。

编译器 –将模式作为输入并生成IR。 在这一层中发生了很多魔术,例如使用最终/常量,优化代码。

消息 –实际消息被缓冲区包装。

全栈方法允许在各个级别进行优化。

无垃圾或少垃圾

这对于低延迟系统非常重要,如果不注意它,则应用程序将无法正确使用CPU缓存,并且可能进入GC暂停状态。

SBE是围绕flyweight模式构建的,它全部与重用对象有关,以减轻JVM上的内存压力。

它具有缓冲区的概念,并且可以重复使用,编码器/解码器可以将缓冲区作为输入并对其进行处理。 编码器/解码器不分配或分配很少(即在使用String的情况下)。

SBE建议使用直接/分出缓冲区使GC完全脱离图像,这些缓冲区可以在线程级别分配,并且可以用于消息的解码和编码。

缓冲区使用情况的代码段。

final ByteBuffer byteBuffer = ByteBuffer.allocateDirect(4096);final UnsafeBuffer directBuffer = new UnsafeBuffer(byteBuffer);
tradeEncoder        .tradeId(1).customerId(999).qty(100).symbol("GOOG").tradeType(TradeType.Buy);

缓存预取

CPU已内置基于硬件的预取器。 缓存预取是计算机处理器使用的一种技术,可通过在实际需要之前将指令或数据从较慢内存中的原始存储中提取到较快的本地内存中,从而提高执行性能。

从快速CPU缓存访问数据比从主存储器访问数据快许多个数量级。

等待时间,您应该知道的博客文章详细介绍了CPU高速缓存的速度。

如果算法正在流式传输并且所使用的基础数据像数组一样连续,则预取效果很好。 数组访问非常快,因为它是连续且可预测的

SBE使用数组作为基础存储,并将字段打包在其中。

预算局

数据以小批量的高速缓存行(通常为8个字节)移动,因此,如果应用程序要求1个字节,它将获得8个字节的数据。 由于数据打包在数组中,因此可以提前访问单字节预取数组内容,这将加快处理速度。

将预取器视为数据库表中的索引。 如果读取基于这些索引,则应用程序将受益。

流媒体访问

SBE支持所有原始类型,并且还允许定义大小可变的自定义类型,这使编码器和解码器可以流式传输和顺序传输。 从高速缓存行中读取数据具有很好的好处,并且解码器几乎不需要了解有关消息的元数据(即偏移量和大小)。

附带权衡的读取顺序必须基于布局顺序,尤其是在对可变类型的数据进行编码的情况下。

例如写正在使用以下顺序

tradeEncoder        .tradeId(1).customerId(999).tradeType(TradeType.Buy).qty(100).symbol("GOOG").exchange("NYSE");

对于String属性(符号和交换),读取顺序必须是第一个符号 ,然后是exchange ,如果应用程序交换顺序,则它将读取错误的字段,对于可变长度属性,另一项读取应仅为一次,因为它是流访问模式。

好东西是有代价的!

不安全的API

数组绑定检查可能会增加开销,但是SBE使用的是不安全的API,并且没有额外的绑定检查开销。

在生成的代码上使用常量

编译器生成代码时,它会预先计算内容并使用常量。 一个示例是在生成的代码中存在字段偏移,但不进行计算。

程式码片段

public static int qtyId(){return 2;}public static int qtySinceVersion(){return 0;}public static int qtyEncodingOffset(){return 16;}public static int qtyEncodingLength(){return 8;}

这需要权衡,这对性能有利,但对灵活性不利。 您无法更改字段顺序,必须在末尾添加新字段。

关于常量的另一个好处是,它们仅在生成的代码中存在,而在消息中却没有,这是非常有效的。

分支免费代码

每个内核都有多个并行运行的端口,几乎没有指令会像分支,mod,除法那样阻塞。 SBE编译器生成的代码无需使用这些昂贵的指令,并且具有基本的指针碰撞数学功能。

没有昂贵指令的代码非常快,它将利用内核的所有端口。

Java序列化的示例代码

public void writeFloat(float v) throws IOException {if (pos + 4 <= MAX_BLOCK_SIZE) {Bits.putFloat(buf, pos, v);        pos += 4;    } else {dout.writeFloat(v);    }
}public void writeLong(long v) throws IOException {if (pos + 8 <= MAX_BLOCK_SIZE) {Bits.putLong(buf, pos, v);        pos += 8;    } else {dout.writeLong(v);    }
}public void writeDouble(double v) throws IOException {if (pos + 8 <= MAX_BLOCK_SIZE) {Bits.putDouble(buf, pos, v);        pos += 8;    } else {dout.writeDouble(v);    }
}

SBE的示例代码

public TradeEncoder customerId(final long value)
{buffer.putLong(offset + 8, value, java.nio.ByteOrder.LITTLE_ENDIAN);    return this;}
public TradeEncoder tradeId(final long value)
{buffer.putLong(offset + 0, value, java.nio.ByteOrder.LITTLE_ENDIAN);    return this;}

邮件大小上的一些数字。

类型级元帅.SerializableMarshal-> 267号

输入class marshal.ExternalizableMarshal-> size 75

输入类元帅SBEMarshall->大小49

SBE最紧凑且速度最快,SBE的作者声称它比Google proto缓冲区快20到50倍。

可提供SBE代码@ simple-binary-encoding

博客中使用的示例代码可在@ sbeplayground获得

翻译自: https://www.javacodegeeks.com/2018/06/inside-simple-binary-encoding-sbe.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/346083.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mingw64 下 java_在 Windows 10 64 位下安装 Mingw-w64

1、MinGW 的全称是&#xff1a;Minimalist GNU on Windows 。打开网址&#xff1a;http://www.mingw-w64.org/doku.php/download &#xff0c;选择 MingW-W64-builds。如图1图12、下载包名&#xff1a;mingw-w64-install.exe。安装时报错&#xff1a;Cannot download repositor…

java实现layui分页_layui如何实现数据分页功能

我们先来看下官网的演示画面。具体代码&#xff1a;页面引入layui.css、 layui.js前台jsvar limitcount 10;var curnum 1;//列表查询方法function productsearch(productGroupId,start,limitsize) {layui.use([table,laypage,laydate], function(){var table layui.table,la…

java 正则表达式使用_如何用正则表达式杀死Java

java 正则表达式使用我们最近偶然发现了一个我们绝对不了解的现象&#xff1a;您可以使用简单的正则表达式杀死任何Java IDE以及任何Java进程… 回到大学后&#xff0c;我被告知正则表达式&#xff08;称为正则语法或3型语法&#xff09;总是以有限状态的自动机结束&#xff0…

java 合并到一行_mysql中将多行数据合并成一行数据

一个字段可能对应多条数据&#xff0c;用mysql实现将多行数据合并成一行数据例如&#xff1a;一个活动id(activeId)对应多个模块名(modelName),按照一般的sql语句&#xff1a;1 SELECT am.activeId,m.modelName2 FROM activemodel am3 JOIN model m4 ON am.modelId m.modelId5…

容器化Spring Data Cassandra应用程序

我正在继续学习Docker的旅程。 在这一点上&#xff0c;我仍然保持简单。 这次&#xff0c;我将解决将Spring和Cassandra应用程序转换为使用容器而不是在主机上本地运行的问题。 更准确地说&#xff0c;使用Spring Data Cassandra整理应用程序。 我希望我前几天看过进行此更改。…

最快的 java 图像_ImageJ 1.53 世界上最快的Java图像处理程序

ImageJ 1.53 世界上最快的Java图像处理程序 已通过小编安装运行测试 100%可以使用。ImageJ 1.53 是世界上最快的纯Java图像处理程序。它可以在0.1秒内过滤2048x2048图像。每秒可以处理4000万像素的图片。ImageJ支持处理8位灰度或索引颜色&#xff0c;16位无符号整数&#xff0c…

java字节码提取if语句_终于找到了!有了它你就可以读懂字节码了!

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼0x80 ior 将栈顶两int型数值作“按位或”并将结果压入栈顶0x81 lor 将栈顶两long型数值作“按位或”并将结果压入栈顶0x82 ixor 将栈顶两int型数值作“按位异或”并将结果压入栈顶0x83 lxor 将栈顶两long型数值作“按位异或”并将结…

maven设置代理服务器_使用Maven设置您的应用服务器

maven设置代理服务器在许多情况下&#xff0c;无需事先设置应用程序就无法部署应用程序。 在JBoss AS 7.x中&#xff0c;您可能需要配置例如数据库连接。 或者&#xff0c;您必须配置一个安全领域。 也许您还想调整SLSB池…在任何情况下&#xff0c;团队中的所有开发人员都必须…

java编程中的di是什么_java-在Spring IoC / DI中使用@Component注释对接口...

在Spring类中,通常使用Component注释接口,特别是对于某些Spring构造型注释&#xff1a;package org.springframework.stereotype;...Componentpublic interface Service {...}要么 &#xff1a;package org.springframework.boot.test.context;...Componentpublic interface Te…

使用React和Spring Boot构建一个简单的CRUD应用

“我喜欢编写身份验证和授权代码。” 〜从来没有Java开发人员。 厌倦了一次又一次地建立相同的登录屏幕&#xff1f; 尝试使用Okta API进行托管身份验证&#xff0c;授权和多因素身份验证。 React的设计使创建交互式UI变得轻松自如。 它的状态管理非常有效&#xff0c;并且仅在…

java初始化该字符串值_java字符串数组初始化和赋值

//一维数组String[] str new String[5]; //创建一个长度为5的String(字符串)型的一维数组String[] str new String[]{“”,””,””,””,””};String[] str {“”,””,””,””,””};String数组初始化区别首先应该明白java数组里面存的是对象的引用&#xff0c;所以必…

java 无法找到ant_Java-Ant需要tools.jar并且无法找到我

Java-Ant需要tools.jar并且无法找到我我将一个Java程序的开发环境放在一起&#xff0c;并且在第一次尝试使用Ant构建脚本后&#xff0c;出现了以下错误&#xff1a;Unable to locate tools.jar. Expected to find it in /usr/lib/jvm/java-6-openjdk/lib/tools.jar虽然通往jdk的…

js实现日历框上一日下一日_一日三项令人兴奋的Lucene功能

js实现日历框上一日下一日昨天是富有成效的一天&#xff1a;突然&#xff0c;Lucene有了三个令人兴奋的新功能。 表达式模块 昨天提交的第一个功能是新的expressions模块 。 这使您可以使用任意String表达式定义用于排序的动态字段。 内置了对JavaScript解析的支持&#xff0c…

使用CUBA进行开发–是Spring的重大转变吗?

阅读另一个供内部公司使用的Web项目的要求时&#xff0c;您&#xff08;至少是我自己&#xff09;通常会看到一个很普通的集合&#xff1a;定义明确的数据存储结构&#xff08;或有时是现有的旧式DB&#xff09;&#xff0c;大量的数据输入形式&#xff0c;非常复杂的业务逻辑&…

java 伴随矩阵_C#计算矩阵的逆矩阵方法实例分析

本文实例讲述了C#计算矩阵的逆矩阵方法。分享给大家供大家参考。具体如下&#xff1a;1.代码思路1)对矩阵进行合法性检查&#xff1a;矩阵必须为方阵2)计算矩阵行列式的值(Determinant函数)3)只有满秩矩阵才有逆矩阵&#xff0c;因此如果行列式的值为0(在代码中以绝对值小于1E-…

apache camel_探索Apache Camel Core –文件组件

apache camel文件轮询器是解决常见IT问题的非常有用的机制。 Camel的内置file组件非常灵活&#xff0c;并且有许多选项可用于配置。 让我们在这里介绍一些常用用法。 轮询目录以输入文件 这是一条典型的骆驼Route用于每秒轮询一次目录以查找输入文件。 import org.slf4j.*; i…

java list 遍历 remove_JAVA中LISt遍历时如何remove元素?

import java。util。*;  public class object {  public static void main(String[] args) {  String str1 new String("abcde");  String str2 new String("abcde");  String str3 new String("abcde");  String str4 new Stri…

Java使用者的延期执行

在前面的博客文章&#xff08;“ 延迟执行Java的供应商 “&#xff09;&#xff0c;我引用礁HORSTMANN的陈述书中‘ 的Java SE8为真的很急关于lambda表达式’&#xff0c;‘所有的lambda表达式的点被推迟执行 。’ Horstmann在最后一年为Dobb博士的杂志写了一篇名为“ Java 8中…

java 代码造假_老板居然让我在Java项目中“造假”

1. 前言老板说&#xff0c;明天甲方要来看产品&#xff0c;你得造点数据&#xff0c;而且数据必须是“真”的&#xff0c;演示效果要好看一些&#xff0c;这样他才会买我们的产品&#xff0c;我好明年给你换个嫂子。一般开发接到这种过分要求都不会很乐意去做&#xff0c;这完全…

nginx php环境搭建_php+nginx环境配置

本篇文章的内容是PHP和nginx环境的配置&#xff0c;在这里分享给大家&#xff0c;也给有需要的朋友一个参考phpnginx环境配置1、首先需要准备的应用程序包。nginx&#xff1a;nginx/Windows-1.0.4php&#xff1a;php-5.2.16-nts-Win32-VC6-x86.zip (nginx下php是以FastCGI的方式…