-
Notifications
You must be signed in to change notification settings - Fork 5k
Description
在 macOS 上使用 TDengine JDBC(通过 AbstractConnection.write(...) 进行 schemaless 写入)时,进程的 Mach port 数量持续增长,增长的主要是 send rights,并且通过 lsmp diff 发现新增对象类型为 SEMAPHORE。
现象表现为:只要持续调用 schemaless 写入(每秒写19万个点),Mach port 的 send 权限数量会稳定上升(约每 2 秒增加 ~50 个),长期运行会导致端口空间不断膨胀,最终被系统 kill。
当不执行写入(不调用 taosCon.write(...))时,Mach port 不再增长,但是也不会减少。
另:最开始使用WS连接,但是没有长时间测试过,因为发现WS写入效率奇低,同样的数据写入需要2秒以上,改用 Native 写入只需要 40ms 左右。
补充:测试在Linux上没有出现此问题
To Reproduce
- 在 macOS 上运行一个 Java 服务/程序,使用 TDengine JDBC + Hikari 连接池,并在业务中持续进行 schemaless 写入(示例代码见下)。
- 获取进程 PID,例如
PID=61250。 - 使用
lsmp监控 Mach port 数量增长(每 2 秒打印一次):
while true; do
ts="$(date '+%F %T')"
sudo lsmp -p "$PID" | awk -v ts="$ts" '
$1 ~ /^0x/ {
total++
if ($3 == "recv") r++
if ($3 == "send") s++
if ($3 == "send-once") so++
if ($3 == "port-set") ps++
}
END { printf "%s total=%d recv=%d send=%d send-once=%d port-set=%d\n", ts, total, r, s, so, ps }'
sleep 2
done- 观察到
total/send持续增长,例如(节选):
2026-02-11 14:13:02 total=13003 recv=182 send=12798 send-once=0 port-set=1
2026-02-11 14:13:07 total=13056 recv=182 send=12851 send-once=0 port-set=1
...
2026-02-11 14:19:44 total=23351 recv=182 send=23146 send-once=0 port-set=1
- 对
send rights做快照 diff,找出新增的 send rights 类型:
sudo lsmp -p "$PID" 2>/dev/null > /tmp/lsmp.1
sleep 5
sudo lsmp -p "$PID" 2>/dev/null > /tmp/lsmp.2
awk '$3=="send"{print $1, $2, $NF}' /tmp/lsmp.1 | sort > /tmp/send.1
awk '$3=="send"{print $1, $2, $NF}' /tmp/lsmp.2 | sort > /tmp/send.2
echo "NEW send rights:"
comm -13 /tmp/send.1 /tmp/send.2 | head -50输出显示新增 send rights 的对象类型为 SEMAPHORE(节选):
NEW send rights:
0x0085e103 0x0d3c6389 SEMAPHORE
0x0085e203 0xca6f83b0 SEMAPHORE
0x0085e303 0x4dd6fc63 SEMAPHORE
...
- 使用
sample采样进程堆栈,能看到大量线程在 TDengine native 库中等待信号量(节选):
sudo sample $PID 5 -file /tmp/sample.txt
# 查看关键堆栈
nl -ba /tmp/sample.txt | sed -n '1460,1540p'
nl -ba /tmp/sample.txt | sed -n '4960,5060p'堆栈中可见 libtaosnative.3.4.0.2.dylib 的 tsem_wait/tsem_timewait 调用链进入 GCD semaphore wait:
taosProcessSchedQueue / monitorThreadFunc / ctgUpdateThreadFunc / ... (in libtaosnative.3.4.0.2.dylib)tsem_wait / tsem_timewait (in libtaosnative.3.4.0.2.dylib)_dispatch_semaphore_wait_slow (in libdispatch.dylib)semaphore_wait_trap / semaphore_timedwait_trap (in libsystem_kernel.dylib)
并且在 Java JNI 写入路径中看到:
Java_com_taosdata_jdbc_TSDBJNIConnector_schemalessInsertImp (in libtaos.3.4.0.2.dylib)schemalessInsert / taos_schemaless_insert* (in libtaosnative.3.4.0.2.dylib)tsem_wait -> _dispatch_semaphore_wait_slow -> semaphore_wait_trap
- 对照实验:不执行写入(不调用
taosCon.write(...))时,Mach port 数量不增长。
Environment
-
OS: macOS 26.2
-
Memory / CPU / Disk: M4pro 24G
-
JDK: JDK 1.8
-
TDengine Version: 3.4.0
-
进程采样中显示 native 库为:
libtaosnative.3.4.0.2.dylib、libtaos.3.4.0.2.dylib -
连接池:HikariCP
-
使用方式:Spring
JdbcTemplate.execute(ConnectionCallback)获取连接并unwrap(AbstractConnection.class)调用write
Additional Context
业务侧调用代码(节选)
public void writeSchemaless(String[] lines) {
if (lines == null || lines.length == 0) return;
tdengineJdbcTemplate.execute((ConnectionCallback<Object>) con -> {
try {
if (con.isWrapperFor(AbstractConnection.class)) {
AbstractConnection taosCon = con.unwrap(AbstractConnection.class);
taosCon.write(lines,
SchemalessProtocolType.LINE,
SchemalessTimestampType.MILLI_SECONDS);
} else {
throw new SQLException("Connection is not an instance of AbstractConnection");
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
return null;
});
}关键观察
lsmp监控显示sendrights 与total持续增长(增长速率稳定)。lsmpdiff 显示新增sendrights 的对象类型为SEMAPHORE。sample堆栈中大量线程在libtaosnative.3.4.0.2.dylib的tsem_wait/tsem_timewait→_dispatch_semaphore_wait_slow→semaphore_wait_trap。- A/B 对照:不调用写入则 Mach port 不涨。