feat: JFR events for open, HTTP range, segment decode/encode, chunk filtering and writer back-pressure

未关闭
#601 0 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

维护者通常 1 天内回复

还没有人认领这个 Issue。

评估

难度
4/5
预计耗时
3-5 天
新手友好度
55/100
Issue 类型
功能
描述清晰度
描述清楚
活跃度
活跃
技术栈
java

调研方向

Start by reading the reader and writer entry points named in the issue: VortexReader.open, VortexHttpReader.open, SerializedArrayDecoder.decode, ScanIterator, and VortexWriter. Add the JFR event classes and wire them into those paths as specified, then use the named tests to check event fields, filtering counts, and back-pressure duration. Done when the event tests pass and the reference guide, how-to guide, changelog, and module map are updated.

由索引模型根据 Issue 内容生成。

描述

enhancement

Goal

Emit JDK Flight Recorder events from the reader and writer, so a JFR recording shows where a read or write spends its time (file open/mapping, HTTP range fetches, per-segment decode/encode, chunk pruning, writer back-pressure) with no extra dependency and near-zero cost when recording is off.

Events

New package core/src/main/java/io/github/dfa1/vortex/core/jfr/ (with package-info.java). Each event is a public class extending jdk.jfr.Event, annotated @Name("io.github.dfa1.vortex.X"), @Label, @Category({"Vortex", …}), @Description and @StackTrace(false). Public fields get /// docs (doclint is all); byte sizes get @DataAmount.

Class Category Fields
FileOpenedEvent I/O source, fileSize, formatVersion, segmentCount
FileMappingEvent I/O file, size
HttpRangeEvent I/O source, offset (-1 = tail), length, status (0 = no response)
SegmentDecodedEvent Decode encoding, rowCount, segmentSize
ChunkFilterEvent Filter totalChunks, chunksPruned, chunksWithoutMatch, chunksReturned, rowsReturned
SegmentEncodedEvent Encode encoding, bufferCount, encodedSize
SegmentWaitEvent Pipeline segmentsInFlight

Reader wiring

Pattern: event.begin(), set fields, commit().

  • VortexReader.open(path, registry, layoutRegistry): FileOpened spans the whole open and is committed after parse; FileMapping wraps channel.map. A failed open emits no FileOpened.
  • VortexHttpReader.open(uri, registry, layoutRegistry, client): FileOpened begins before fetchTail and is committed after the reader is built.
    • New private sendRange(req, client, uri, offset, length) wraps client.send in try/finally and always commits HttpRange, with status = 0 on failure. fetchTail calls it with offset -1 and TAIL_SIZE.bytes(); fetchRange with from and to - from + 1.
    • New package-private static String describe(URI) returning scheme://host[:port] + raw path. It drops user info, query and fragment, because presigned URLs carry credentials. Used for every source field.
  • SerializedArrayDecoder.decode: begin at the top; after registry.decode(ctx) set encoding = node.encodingId().id(), rowCount, segmentSize = segLen, then commit. Covers both readers.
  • ScanIterator:
    • New counters chunksPruned, chunksWithoutMatch, chunksReturned.
    • In hasNext(), split canPruneChunk(...) || !selectMatchingRows(...) into two branches that each count, chunkIndex++; continue.
    • Increment chunksReturned in next().
    • close() calls emitChunkFilterEvent(), a no-op when filter == null || chunks == null.

Writer wiring (VortexWriter)

  • encodeSegment: begin at the top; before returning, if (event.shouldCommit()) fill encoding from result.rootNode().encodingId().id(), bufferCount, encodedSize, then commit. Failures emit nothing.
  • drainSegments: replace pending.poll().join() with a static awaitHead(head, pending.size() + 1). It joins directly if head.isDone(); otherwise begins a SegmentWaitEvent, joins in a try, commits in the finally.
  • No change to the writer's default behavior. (The default executor runs tasks on the caller, so SegmentWait never appears there.)

Tests

Given/When/Then throughout. For events committed on other threads, assert presence and field values, never exact counts.

  • core/src/test/.../core/testing/JfrRecorderTest.java: abstract base; a RecordingStream with setReuse(false) starts in @BeforeEach; offers awaitEvents() and events(name).
  • reader VortexReaderJfrTest (fixture primitives.vortex): FileOpened and FileMapping fields; a too-small file emits no FileOpened.
  • reader VortexHttpReaderJfrTest (mocked HttpClient): tail HttpRange (offset -1, status 206); source has no credentials or query; status 0 when send throws IOException.
  • writer JfrEventsTest (uses LegacyZoneMaps.OPTIONS, same package):
    • SegmentEncoded present with non-negative sizes (a vortex.sequence segment has 0 buffers).
    • Default executor: no SegmentWait.
    • Executor sleeping 200 ms before each task: SegmentWait duration > 50 ms and segmentsInFlight > 0.
    • Chunks 1..50, 51..100, 101..150 with eq(id, 75) → totals 3/2/0/1 and 1 row.
    • Single chunk {1, 100} with eq(id, 50) → 1/0/1/0 and 0 rows.
    • Unfiltered scan emits no ChunkFilter.

Docs (same commit)

  • docs/reference.md: "JFR events" section (event table) + TOC entry.
  • docs/how-to.md: "Find where a read or write spends its time (JFR)".
  • CHANGELOG.md: ## [Unreleased] → Added.
  • AGENTS.md: core.jfr line in the module map.

Verify

  • ./mvnw test -pl core,reader,writer -am
  • ./mvnw verify -DskipTests (Javadoc lint + checkstyle)
主要语言
Java
星标
3
派生
2
平均合并
14 小时 59 分钟
30 天内合并 PR
137

环境准备

  • 没有 Dockerfile 或 Docker Compose 文件
  • 没有 Pull Request 模板
  • 阅读贡献指南

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

dfa1/vortex-java 的其他 Issue

查看 dfa1/vortex-java 的全部 Issue

相似的 Issue

更多 Java Issue

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。