Repository navigation
Video segment pairing fix - #177
felipemontoya wants to merge 4 commits into
Conversation
|
Thanks for the pull request, @felipemontoya! This repository is currently maintained by Once you've gone through the following steps feel free to tag them in a comment and let them know that your changes are ready for engineering review. 🔘 Get product approvalIf you haven't already, check this list to see if your contribution needs to go through the product review process.
🔘 Provide contextTo help your reviewers and other members of the community understand the purpose and larger context of your changes, feel free to add as much of the following information to the PR description as you can:
🔘 Get a green buildIf one or more checks are failing, continue working on your changes until this is no longer the case and your build turns green. DetailsWhere can I find more information?If you'd like to get more details on all aspects of the review process for open source pull requests (OSPRs), check out the following resources: When can I expect my changes to be merged?Our goal is to get community contributions seen and reviewed as efficiently as possible. However, the amount of time that it takes to review and merge a PR can vary significantly based on factors such as:
💡 As a result it may take up to several weeks or months to complete a review and merge your PR. |
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…h the intervals scan Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
32bdaa8 to
efb9e5c
Compare
|
@saraburns1 rebased the PR. I also included all your suggestions and took it a step further trimming comments to mostly one line at the top of the file or comments that are necessary to understand the intent of confusing lines. |
|
This is great overall! Because this is a bit of a new direction, and if it works well is probably something we would want to carry over to pages and problems, I have a couple of questions:
|
|
I've been benchmarking the engagement models against a dataset with known expected results (~14.8M xAPI events, 25k learners, realistic play/pause/seek journeys) on ClickHouse 25.8 limited to 4 CPU / 16 GB. I added a round for this PR before starting on other performance improvements, and here's what I found. I rendered the actual Superset chart SQL from tutor-contrib-aspects for the Course Dashboard and Individual Learner video tabs, then ran it directly. Good findings:
Issues found:
The cast(ifNull(end_video_position, 0) as int) + 1,
Largest course (~1,050 learners), warm runs:
Peak memory is about 7 GiB per chart on both. Loading the whole Videos tab at once still runs out of memory on 16 GB with either version. Since
On our dataset, v8.0.0's watched seconds come out only +0.4% above expected, not +13%. The "last end before the next play" defect only shows up on interleaved event sequences, which the random load generator produces much more often than real journeys do. The fix is still right, but real-world drift is probably less than 13%. I've been using this |
|
Fantastic review. I am a bit behind on my side, but I expect to get back on track on Tuesday. |
|
A correction and two more findings, now that we've profiled further. Correction: the view isn't what makes the video charts slow In my last comment I put the 2–3× slowdown of the video_watches charts down to
v8.0.0 looked faster mostly because it stored fewer rows. So there's no need to materialize What does fix it is a per-learner, per-video summary: distinct seconds watched, plus the most views of any second. That's all the Finding: In select type from system.columns
where table = 'video_playback_events' and name = 'emission_time_long'
-- DateTimeThe pairing window here orders by Finding: the off-by-one is easy to fix here The off-by-one you noted is range(
cast(start_video_position as int) + 1,
cast(ifNull(end_video_position, 0) as int) + 1,
1
)With both fixes, watched seconds match a known-answer dataset exactly (14.8M events, 25k learners). |
|
Last thing, then I'll stop spamming this ticket. In trying to figure out the tutor-contrib-aspects bug 1335 I built on top of this PR to get to #180 and openedx/tutor-contrib-aspects#1355 I think they fix the items I brought up above and get us to a much better overall place with both data loading and engagement chart performance, but would really appreciate your input and review. |
This PR contains the fix to issue #176. It has three commits: the fix, the tests and the performance changes.
The problem it fixes
fact_video_segments used to be a plain ClickHouse materialized view (MV) over video_playback_events. A plain MV only sees the rows in each insert batch. If a learner's played event and its closing paused event arrive in different inserts, which is normal for live traffic, they are never paired. That watched time is silently lost. fact_video_engagement was an MV built on top of it, so it lost the same data.
The new design
1. New model: models/video/fact_video_watch_intervals.sql
2. The pairing logic: macros/video_watch_intervals.sql
3. fact_video_segments is now a view
4. fact_video_engagement is now a view
5. Cleaning up the old objects
How it is tested
1. dbt unit tests (models/video/unit_tests.yaml)
2. CI integration check (.github/workflows/coverage.yml)
3. Performance:
In a local tutor environment. The host: 12 CPUs, 30 GiB RAM, of which ~11 GiB were free when testing started (the rest
held by the desktop and other projects), NVMe disk. ClickHouse 25.8.33.6 in
tutor_dev-clickhouse-1, no container limits,max_server_memory_usage27.9 GiB (0.9 × RAM),max_threads12, no per-querymax_memory_usage. The host has less free memory thanClickHouse thinks it may use, so host memory pressure can be the real limit.
Incremental: the refresh keeps up far beyond realistic traffic; memory is the limit, not time.
One refresh re-pairs the last day of video events:
At 31M video events per day (~70M xAPI events per day at the generator's 44% video share) a refresh
takes 37 s against a 5-minute interval. The next doubling would need more memory than this host has
free. Ingestion itself tops out at ~13k xAPI events/s (~1.1B/day) through the full Aspects MV chain,
far above both.
Full refresh: 10–28× faster than v8.0.0 and 4–10× less memory, but it does not stay small.
Like-for-like on the same course subsets (runs 25–27):
dbt run --full-refreshv8.0.0's extra 13% of watched seconds is its pairing defect (the last end before the next play).
Both still carry the inherited off-by-one at interval starts.
This performance review raised 5 findings, fixed in the last commit.
A more complete depiction of all the tests run was created using claude artifacts and its available here: https://claude.ai/artifact/Gctp5pViYWeFCh2cV2CtWn