关于上下文类加载器,之前一直只是了解,在开发过程中并未使用过,直到开发 Java Agent 时,才真正明白其作用,本文作简要记录。在 Java SPI 机制的核心类 ServiceLoader
中,有以下代码:
1 | /** |
关于上下文类加载器,之前一直只是了解,在开发过程中并未使用过,直到开发 Java Agent 时,才真正明白其作用,本文作简要记录。在 Java SPI 机制的核心类 ServiceLoader
中,有以下代码:
1 | /** |
MySQL JDBC 驱动在未配置流式读取或游标相关参数的情况下,默认会使用静态结果集进行数据的接收,其中源码位于 MysqlIO.java at release/5.1:
1 | private RowData readSingleRowSet(long columnCount, int maxRows, int resultSetConcurrency, boolean isBinaryEncoded, Field[] fields) throws SQLException { |
在 Redis 官网的数据类型介绍中对 Bitmap 部分有如下描述:
Bitmaps are not an actual data type, but a set of bit-oriented operations defined on the String type. Since strings are binary safe blobs and their maximum length is 512 MB, they are suitable to set up to 232 different bits.
可知,Redis 中的 Bitmap 由 String 实现,且因为 Redis 中的 String 是二进制安全的且最大长度为 512MB,所以支持存储 512 × 1024 × 1024 × 8 = 4294967296 = 232 个比特位。其中还提到仅需 512MiB 即可存储 40 亿用户的比特位信息。
我曾开发过基于 RoaringBitmap
的分布式去重服务,用于在线用户数去重统计及离线计算中的去重统计,本文基于 0.9.8
简要分析 RoaringBitmap
的底层数据结构。
Java 中基本类型 int
为有符号实现,可表示的范围为 [-2147483648, 2147483647]
,即整个范围段长达 42 亿之多,即使是仅使用正数部分也有 21 亿,对于大部分公司的用户维度的统计已经足够,所以我们选择基于 32 位 int
的 RoaringBitmap
进行分析。如果对基于 64 位 long
的 Roaring64Bitmap
实现感兴趣,可以自行查看源码:Roaring64Bitmap.java。
RoaringBitmap
的整体设计思想是把 32 位的 int
整数拆分为两个 16 位的部分进行存储,高 16 位的部分用于定位低 16 位的部分存储在哪一个 container
,然后在对应的 container
中存储低 16 位值。可能上面的说法有一点抽象,我们使用最常用的 add
方法进行分析,add
方法用于将一个 int
类型的整数添加至 RoaringBitmap
,其源码实现如下:
1 | /** |
Richard Startin 在文章 A Quick Look at RoaringBitmap 中介绍 BitmapContainer
提到 Long.bitCount
在处理器支持的情况下,会被内联为调用指令 popcnt
实现。本文做简单记录,我们编写如下的代码:
1 | package me.tianshuang; |