forked from genewildish/Mainline
fix(performance): use simple height estimation instead of PIL rendering
- Replace estimate_block_height (PIL-based) with estimate_simple_height (word wrap) - Update viewport filter tests to match new height-based filtering (~4 items vs 24) - Fix CI task duplication in mise.toml (remove redundant depends) Closes #38 Closes #36
This commit is contained in:
@@ -11,14 +11,7 @@ import pytest
|
||||
from engine.data_sources.sources import SourceItem
|
||||
from engine.pipeline.adapters import FontStage, ViewportFilterStage
|
||||
from engine.pipeline.core import PipelineContext
|
||||
|
||||
|
||||
class MockParams:
|
||||
"""Mock parameters object for testing."""
|
||||
|
||||
def __init__(self, viewport_width: int = 80, viewport_height: int = 24):
|
||||
self.viewport_width = viewport_width
|
||||
self.viewport_height = viewport_height
|
||||
from engine.pipeline.params import PipelineParams
|
||||
|
||||
|
||||
class TestViewportFilterPerformance:
|
||||
@@ -38,12 +31,12 @@ class TestViewportFilterPerformance:
|
||||
|
||||
stage = ViewportFilterStage()
|
||||
ctx = PipelineContext()
|
||||
ctx.params = MockParams(viewport_height=24)
|
||||
ctx.params = PipelineParams(viewport_height=24)
|
||||
|
||||
result = benchmark(stage.process, test_items, ctx)
|
||||
|
||||
# Verify result is correct
|
||||
assert len(result) <= 5
|
||||
# Verify result is correct - viewport filter takes first N items
|
||||
assert len(result) <= 24 # viewport height
|
||||
assert len(result) > 0
|
||||
|
||||
@pytest.mark.benchmark
|
||||
@@ -61,7 +54,7 @@ class TestViewportFilterPerformance:
|
||||
|
||||
font_stage = FontStage()
|
||||
ctx = PipelineContext()
|
||||
ctx.params = MockParams()
|
||||
ctx.params = PipelineParams()
|
||||
|
||||
result = benchmark(font_stage.process, filtered_items, ctx)
|
||||
|
||||
@@ -75,8 +68,8 @@ class TestViewportFilterPerformance:
|
||||
|
||||
With 1438 items and 24-line viewport:
|
||||
- Without filter: FontStage renders all 1438 items
|
||||
- With filter: FontStage renders ~3 items (layout-based)
|
||||
- Expected improvement: 1438 / 3 ≈ 479x
|
||||
- With filter: FontStage renders ~4 items (height-based)
|
||||
- Expected improvement: 1438 / 4 ≈ 360x
|
||||
"""
|
||||
test_items = [
|
||||
SourceItem(f"Headline {i}", "source", str(i)) for i in range(1438)
|
||||
@@ -84,15 +77,15 @@ class TestViewportFilterPerformance:
|
||||
|
||||
stage = ViewportFilterStage()
|
||||
ctx = PipelineContext()
|
||||
ctx.params = MockParams(viewport_height=24)
|
||||
ctx.params = PipelineParams(viewport_height=24)
|
||||
|
||||
filtered = stage.process(test_items, ctx)
|
||||
improvement_factor = len(test_items) / len(filtered)
|
||||
|
||||
# Verify we get expected ~479x improvement (better than old ~288x)
|
||||
assert 400 < improvement_factor < 600
|
||||
# Verify filtered count is reasonable (layout-based is more precise)
|
||||
assert 2 <= len(filtered) <= 5
|
||||
# Verify we get significant improvement (height-based filtering)
|
||||
assert 300 < improvement_factor < 500
|
||||
# Verify filtered count is ~4 (24 viewport / 6 rows per item)
|
||||
assert len(filtered) == 4
|
||||
|
||||
|
||||
class TestPipelinePerformanceWithRealData:
|
||||
@@ -109,7 +102,7 @@ class TestPipelinePerformanceWithRealData:
|
||||
font_stage = FontStage()
|
||||
|
||||
ctx = PipelineContext()
|
||||
ctx.params = MockParams(viewport_height=24)
|
||||
ctx.params = PipelineParams(viewport_height=24)
|
||||
|
||||
# Filter should reduce items quickly
|
||||
filtered = filter_stage.process(large_items, ctx)
|
||||
@@ -129,14 +122,14 @@ class TestPipelinePerformanceWithRealData:
|
||||
|
||||
# Test different viewport heights
|
||||
test_cases = [
|
||||
(12, 3), # 12px height -> ~3 items
|
||||
(24, 5), # 24px height -> ~5 items
|
||||
(48, 9), # 48px height -> ~9 items
|
||||
(12, 12), # 12px height -> 12 items
|
||||
(24, 24), # 24px height -> 24 items
|
||||
(48, 48), # 48px height -> 48 items
|
||||
]
|
||||
|
||||
for viewport_height, expected_max_items in test_cases:
|
||||
ctx = PipelineContext()
|
||||
ctx.params = MockParams(viewport_height=viewport_height)
|
||||
ctx.params = PipelineParams(viewport_height=viewport_height)
|
||||
|
||||
filtered = stage.process(large_items, ctx)
|
||||
|
||||
@@ -159,14 +152,14 @@ class TestPerformanceRegressions:
|
||||
|
||||
stage = ViewportFilterStage()
|
||||
ctx = PipelineContext()
|
||||
ctx.params = MockParams()
|
||||
ctx.params = PipelineParams()
|
||||
|
||||
filtered = stage.process(large_items, ctx)
|
||||
|
||||
# Should NOT have all items (regression detection)
|
||||
assert len(filtered) != len(large_items)
|
||||
# Should have drastically fewer items
|
||||
assert len(filtered) < 10
|
||||
# With height-based filtering, ~4 items fit in 24-row viewport (6 rows/item)
|
||||
assert len(filtered) == 4
|
||||
|
||||
def test_font_stage_doesnt_hang_with_filter(self):
|
||||
"""Regression test: FontStage shouldn't hang when receiving filtered data.
|
||||
@@ -182,7 +175,7 @@ class TestPerformanceRegressions:
|
||||
|
||||
font_stage = FontStage()
|
||||
ctx = PipelineContext()
|
||||
ctx.params = MockParams()
|
||||
ctx.params = PipelineParams()
|
||||
|
||||
# Should complete instantly (not hang)
|
||||
result = font_stage.process(filtered_items, ctx)
|
||||
|
||||
Reference in New Issue
Block a user