[PR #724] [MERGED] allow play to stream events #1215

Closed
opened 2026-03-15 11:24:42 +03:00 by kerem · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/asciinema/asciinema/pull/724
Author: @fopina
Created: 2/9/2026
Status: Merged
Merged: 2/10/2026
Merged by: @ku1ik

Base: developHead: feature/stream-play-events


📝 Commits (2)

  • 4544047 allow play to stream events
  • dcfbe1e Apply rustfmt formatting to v2.rs

📊 Changes

4 files changed (+13 additions, -12 deletions)

View changed files

📝 src/asciicast.rs (+6 -6)
📝 src/asciicast/v2.rs (+4 -1)
📝 src/asciicast/v3.rs (+1 -1)
📝 src/player.rs (+2 -4)

📄 Description

This change removes the memory bottleneck in the play command by streaming events from disk instead of loading them all into memory.

This is greatly assisted by Claude but after a long chat around the existing .collect and its motivation.

Changes:

  • Replace tokio::spawn with tokio::task::spawn_blocking in emit_session_events()
  • Remove .collect() that was loading all events into a Vec
  • Use blocking_send() instead of async send() for the channel

Benefits:

  • Memory usage reduced
  • Instant playback start (no pre-loading delay)
  • Support for arbitrarily large recordings
  • Foundation for stdin streaming support (cat file.cast | asciinema play -)

Technical details:
The original code used .collect() because tokio::spawn requires 'static lifetime. By using spawn_blocking instead, we can stream the iterator directly since blocking tasks don't have the same lifetime constraints. File I/O is blocking anyway, so this is the correct approach.

Testing:

  • Generated different large files and compared Max RSS between develop version and my branch
  •       Maximum resident set size (kbytes): 221712
          ./ gtime -v ./asciinema-new play --speed 10000 size_100.cast
          Maximum resident set size (kbytes): 111120
          ./ gtime -v ./asciinema-original play --speed 10000 size_500.cast
          Maximum resident set size (kbytes): 924512
          ./ gtime -v ./asciinema-new play --speed 10000 size_500.cast
          Maximum resident set size (kbytes): 508768
          ./ gtime -v ./asciinema-original play --speed 10000 size_2000.cast
          Maximum resident set size (kbytes): 2003312
          ./ gtime -v ./asciinema-new play --speed 10000 size_2000.cast
          Maximum resident set size (kbytes): 701328
    
  • As this is Max RSS it, the increased memory is likely from the OS and not the binary but it still shows a much friendlier scaling of memory usage for the input file 😄

🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/asciinema/asciinema/pull/724 **Author:** [@fopina](https://github.com/fopina) **Created:** 2/9/2026 **Status:** ✅ Merged **Merged:** 2/10/2026 **Merged by:** [@ku1ik](https://github.com/ku1ik) **Base:** `develop` ← **Head:** `feature/stream-play-events` --- ### 📝 Commits (2) - [`4544047`](https://github.com/asciinema/asciinema/commit/45440476181293a545195b3ed90fa8c743608093) allow `play` to stream events - [`dcfbe1e`](https://github.com/asciinema/asciinema/commit/dcfbe1edc4d93749a97f4a291e4b7b8377791990) Apply rustfmt formatting to v2.rs ### 📊 Changes **4 files changed** (+13 additions, -12 deletions) <details> <summary>View changed files</summary> 📝 `src/asciicast.rs` (+6 -6) 📝 `src/asciicast/v2.rs` (+4 -1) 📝 `src/asciicast/v3.rs` (+1 -1) 📝 `src/player.rs` (+2 -4) </details> ### 📄 Description This change removes the memory bottleneck in the play command by streaming events from disk instead of loading them all into memory. This is greatly assisted by Claude but after a long chat around the existing `.collect` and its motivation. Changes: - Replace tokio::spawn with tokio::task::spawn_blocking in emit_session_events() - Remove .collect() that was loading all events into a Vec - Use blocking_send() instead of async send() for the channel Benefits: - Memory usage reduced - Instant playback start (no pre-loading delay) - Support for arbitrarily large recordings - Foundation for stdin streaming support (cat file.cast | asciinema play -) Technical details: The original code used .collect() because tokio::spawn requires 'static lifetime. By using spawn_blocking instead, we can stream the iterator directly since blocking tasks don't have the same lifetime constraints. File I/O is blocking anyway, so this is the correct approach. Testing: - Generated different large files and compared Max RSS between develop version and my branch - ```./ gtime -v ./asciinema-original play --speed 10000 size_100.cast Maximum resident set size (kbytes): 221712 ./ gtime -v ./asciinema-new play --speed 10000 size_100.cast Maximum resident set size (kbytes): 111120 ./ gtime -v ./asciinema-original play --speed 10000 size_500.cast Maximum resident set size (kbytes): 924512 ./ gtime -v ./asciinema-new play --speed 10000 size_500.cast Maximum resident set size (kbytes): 508768 ./ gtime -v ./asciinema-original play --speed 10000 size_2000.cast Maximum resident set size (kbytes): 2003312 ./ gtime -v ./asciinema-new play --speed 10000 size_2000.cast Maximum resident set size (kbytes): 701328 ``` - As this is Max RSS it, the increased memory is likely from the OS and not the binary but it still shows a much friendlier scaling of memory usage for the input file :smile: --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
kerem 2026-03-15 11:24:42 +03:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/asciinema#1215
No description provided.