Skip to content

Commit f806a41

Browse files
Merge pull request #707 from lukecotter/feat-optimised-timeline-sub-pixel-rendering
feat: optimised timeline - sub pixel / LOD rendering
2 parents 855ab85 + 657e3f7 commit f806a41

35 files changed

Lines changed: 5378 additions & 1068 deletions

CHANGELOG.md

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
99

1010
### Added
1111

12-
-**Timeline**: A brand new **experimental** timeline Flame Chart that is up to **7X faster**. ([#446] [#251] [#92] [#564])
13-
- Revert to the legacy timeline via **Settings -> Apex Log Analyzer -> Timeline -> Legacy**.
14-
- Generally Improved performance, especially for large logs.
15-
- Text labels on Timeline events.
16-
- Zoom and pan are now **7X faster**.
17-
- The Time axis scales more naturally when zooming, with larger gaps between the markers on longer logs.
18-
- Search + highlight will grey out non matches to find matches more easily.
19-
- Added 18 timeline color themes and improved the default theme for better contrast and readability.
20-
- Supply multiple custom themes via **Settings -> Apex Log Analyzer -> Timeline -> Custom Themes**.
21-
- Change the active theme via the new **Command Palette** command **Log: Timeline Theme** or via **Settings -> Apex Log Analyzer -> Timeline -> Active Theme**.
12+
-**Timeline**: A brand new **experimental** timeline Flame Chart built for massive logs and up to **7X faster**. ([#446] [#251] [#92] [#564])
13+
- Toggle the legacy timeline anytime via **Settings -> Apex Log Analyzer -> Timeline -> Legacy**.
14+
- Improved performance to handle huge Apex debug logs.
15+
- Dynamic labels on Timeline events for faster log scanning.
16+
- Zoom + pan are **7X faster** with smoother motion.
17+
- Time axis auto-spaces markers intelligently and more naturally as you zoom.
18+
- Search + highlight dims non-matches for fast scanning.
19+
- 18 curated timeline themes plus the default theme has been improved for better contrast and readability.
20+
- Add your own multiple custom themes via **Settings -> Apex Log Analyzer -> Timeline -> Custom Themes**.
21+
- Fast theme switching via **Command Palette**: **Log: Timeline Theme** or **Settings -> Apex Log Analyzer -> Timeline -> Active Theme**.
22+
- Adaptive level-of-detail bucketing reveals richer timeline detail as you zoom while keeping keeping the view clean and fast.
2223

2324
### Changed
2425

log-viewer/src/features/timeline/__tests__/batching.test.ts

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,8 @@ describe('EventBatchRenderer', () => {
7777
rectangleManager = new RectangleManager(events, categories);
7878
renderer = new EventBatchRenderer(container, batches);
7979

80-
const culledRects = rectangleManager.getCulledRectangles(viewport);
81-
renderer.render(culledRects);
80+
const { visibleRects, buckets } = rectangleManager.getCulledRectangles(viewport);
81+
renderer.render(visibleRects, buckets);
8282
}
8383

8484
beforeEach(() => {
@@ -122,18 +122,20 @@ describe('EventBatchRenderer', () => {
122122
});
123123

124124
describe('initialization', () => {
125-
it('should create Graphics objects for each batch', () => {
125+
it('should create a SpritePool container', () => {
126126
renderer = new EventBatchRenderer(container, batches);
127127

128-
expect(container.children).toHaveLength(3);
129-
expect(container.children.every((child) => child instanceof PIXI.Graphics)).toBe(true);
128+
// SpritePool creates a container for sprites
129+
expect(container.children).toHaveLength(1);
130+
expect(container.children[0] instanceof PIXI.Container).toBe(true);
130131
});
131132

132-
it('should handle empty batches', () => {
133+
it('should create SpritePool container with empty batches', () => {
133134
const emptyBatches = new Map<string, RenderBatch>();
134135
renderer = new EventBatchRenderer(container, emptyBatches);
135136

136-
expect(container.children).toHaveLength(0);
137+
// SpritePool container is still created
138+
expect(container.children).toHaveLength(1);
137139
});
138140
});
139141

@@ -322,7 +324,7 @@ describe('EventBatchRenderer', () => {
322324

323325
it('should render events that meet minimum size threshold', () => {
324326
const events = [
325-
createEvent(0, 1, 'Method'), // Width = 1px at zoom=1
327+
createEvent(0, 3, 'Method'), // Width = 3px at zoom=1 (> MIN_RECT_SIZE = 2px)
326328
];
327329

328330
const viewport = createViewport(1, 0, 0);
@@ -454,8 +456,9 @@ describe('EventBatchRenderer', () => {
454456

455457
// Second render with different viewport (should recalculate)
456458
const viewport2 = createViewport(1, 150, 0); // Pan to cull first event
457-
const culledRects2 = rectangleManager.getCulledRectangles(viewport2);
458-
renderer.render(culledRects2);
459+
const { visibleRects: visibleRects2, buckets: buckets2 } =
460+
rectangleManager.getCulledRectangles(viewport2);
461+
renderer.render(visibleRects2, buckets2);
459462
expect(batches.get('Method')?.rectangles).toHaveLength(1);
460463
});
461464
});
@@ -503,14 +506,14 @@ describe('EventBatchRenderer', () => {
503506
});
504507

505508
describe('cleanup', () => {
506-
it('should destroy all Graphics objects', () => {
509+
it('should destroy SpritePool and remove all children', () => {
507510
renderer = new EventBatchRenderer(container, batches);
508511

509512
const childrenCount = container.children.length;
510513
expect(childrenCount).toBeGreaterThan(0);
511514

512515
renderer.destroy();
513-
// After destruction, graphics are removed from their parent
516+
// After destruction, SpritePool container is removed
514517
// Container should have no children
515518
expect(container.children.length).toBe(0);
516519
});
@@ -541,9 +544,9 @@ describe('EventBatchRenderer', () => {
541544
});
542545

543546
it('should render events when they meet minimum size threshold after zoom', () => {
544-
const events = [createEvent(0, 100, 'Method')];
547+
const events = [createEvent(0, 300, 'Method')];
545548

546-
// Zoom in so screenWidth = 100 * 0.01 = 1px (> MIN_RECT_SIZE = 0.5px)
549+
// Zoom in so screenWidth = 300 * 0.01 = 3px (> MIN_RECT_SIZE = 2px)
547550
const viewport = createViewport(0.01, 0, 0);
548551
setupAndRender(events, viewport);
549552

0 commit comments

Comments
 (0)