Poison


  • 首页

  • 归档

  • 标签

  • 搜索
close
Poison

ContextClassLoader

发表于 2021-10-07

关于上下文类加载器,之前一直只是了解,在开发过程中并未使用过,直到开发 Java Agent 时,才真正明白其作用,本文作简要记录。在 Java SPI 机制的核心类 ServiceLoader 中,有以下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/**
* Creates a new service loader for the given service type, using the
* current thread's {@linkplain java.lang.Thread#getContextClassLoader
* context class loader}.
*
* <p> An invocation of this convenience method of the form
*
* <blockquote><pre>
* ServiceLoader.load(<i>service</i>)</pre></blockquote>
*
* is equivalent to
*
* <blockquote><pre>
* ServiceLoader.load(<i>service</i>,
* Thread.currentThread().getContextClassLoader())</pre></blockquote>
*
* @param <S> the class of the service type
*
* @param service
* The interface or abstract class representing the service
*
* @return A new service loader
*/
public static <S> ServiceLoader<S> load(Class<S> service) {
ClassLoader cl = Thread.currentThread().getContextClassLoader();
return ServiceLoader.load(service, cl);
}
阅读全文 »
Poison

ResultSet

发表于 2021-10-05

MySQL JDBC 驱动在未配置流式读取或游标相关参数的情况下,默认会使用静态结果集进行数据的接收,其中源码位于 MysqlIO.java at release/5.1:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
private RowData readSingleRowSet(long columnCount, int maxRows, int resultSetConcurrency, boolean isBinaryEncoded, Field[] fields) throws SQLException {
RowData rowData;
ArrayList<ResultSetRow> rows = new ArrayList<ResultSetRow>();

boolean useBufferRowExplicit = useBufferRowExplicit(fields);

// Now read the data
ResultSetRow row = nextRow(fields, (int) columnCount, isBinaryEncoded, resultSetConcurrency, false, useBufferRowExplicit, false, null);

int rowCount = 0;

if (row != null) {
rows.add(row);
rowCount = 1;
}

while (row != null) {
row = nextRow(fields, (int) columnCount, isBinaryEncoded, resultSetConcurrency, false, useBufferRowExplicit, false, null);

if (row != null) {
if ((maxRows == -1) || (rowCount < maxRows)) {
rows.add(row);
rowCount++;
}
}
}

rowData = new RowDataStatic(rows);

return rowData;
}
阅读全文 »
Poison

Redis 中 Bitmap 的存储实现

发表于 2021-10-04

在 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 亿用户的比特位信息。

阅读全文 »
Poison

RoaringBitmap 的底层数据结构

发表于 2021-10-04

我曾开发过基于 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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
* Add the value to the container (set the value to "true"), whether it already appears or not.
*
* Java lacks native unsigned integers but the x argument is considered to be unsigned.
* Within bitmaps, numbers are ordered according to {@link Integer#compareUnsigned}.
* We order the numbers like 0, 1, ..., 2147483647, -2147483648, -2147483647,..., -1.
*
* @param x integer value
*/
@Override
public void add(final int x) {
final char hb = Util.highbits(x);
final int i = highLowContainer.getIndex(hb);
if (i >= 0) {
highLowContainer.setContainerAtIndex(i,
highLowContainer.getContainerAtIndex(i).add(Util.lowbits(x)));
} else {
final ArrayContainer newac = new ArrayContainer();
highLowContainer.insertNewKeyValueAt(-i - 1, hb, newac.add(Util.lowbits(x)));
}
}
阅读全文 »
Poison

JVM Intrinsics

发表于 2021-10-04

Richard Startin 在文章 A Quick Look at RoaringBitmap 中介绍 BitmapContainer 提到 Long.bitCount 在处理器支持的情况下,会被内联为调用指令 popcnt 实现。本文做简单记录,我们编写如下的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package me.tianshuang;

public class IntrinsicTest {

public static void main(String[] args) {
int result = 0;
for (int i = 0; i < 1000000000; i++) {
result += Long.bitCount(i);
}

System.out.println(result);
}

}
阅读全文 »
1…141516…26

130 日志
119 标签
GitHub LeetCode
© 2025 Poison 蜀ICP备16000644号
由 Hexo 强力驱动
主题 - NexT.Mist