ManimCommunity / ManimCommunity/manim
Caching performance Issues
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 40.9k
- Forks
- 3.1k
- Avg merge
- 3d 12h
- Merged PRs (30d)
- 25
Description
Description of bug / unexpected behavior
The performance with caching enabled is a lot slower than with caching disabled.
Time Table dry_run
| Type | OpenGL | Cairo |
|---|---|---|
| Cached 1st | 417 s | 113 s |
| Cached 2nd | 418 s | 79 s |
| Uncached | 45 s | 54 s |
Time Table normal run (without dry_run)
| Type | OpenGL | Cairo |
|---|---|---|
| Cached 1st | 596 s | 174 s |
| Cached 2nd | 569 s | 142 s |
| Uncached | 236 s | 179 s |
Output for first cached OpenGL dry run which does not appear in second run!
[05/06/22 08:44:23] INFO Writing Fixpoint Iteration : Diverging to media/Tex/162bb2b1a28541de.tex tex_file_writing.py:87
[05/06/22 08:44:24] INFO Writing x to media/Tex/0928cfcc759228a6.tex tex_file_writing.py:87
[05/06/22 08:44:25] INFO Writing f(x) to media/Tex/befe5547f2e66150.tex tex_file_writing.py:87
[05/06/22 08:44:30] INFO Writing x_0 = 0.2 to media/Tex/490a8d4dc52f2b9f.tex tex_file_writing.py:87
INFO Writing x_0 to media/Tex/92af03d5e2840ce9.tex
.
.
.
[05/06/22 08:50:21] INFO Writing x_5 to media/Tex/059b6f1ae9f59ac7.tex tex_file_writing.py:87
[05/06/22 08:51:19] INFO Rendered Converging scene.py:240
Played 52 animations
Expected behavior
The cached run should obviously be faster than the uncached run. The file reading and writing seems to be pretty slow. The media folder was on average 1.4MB in file size.
(I am using an nvme ssd with 2.5GB read and write speed, so that shouldn't be a bottle neck)
I suggest reworking the cache system on both ends or just removing in completely.
How to reproduce the issue
Code for reproducing the problem
import time
from manim import *
def get_t_label(
c: CoordinateSystem,
isX: bool,
hasLine: bool,
val: float,
graph: ParametricFunction,
label: float | str | Mobject | None = None,
label_color = None,
triangle_size: float = MED_SMALL_BUFF,
triangle_color = WHITE,
line_func: Line = Line,
line_color = YELLOW,
) -> VGroup:
T_label_group = VGroup()
angle = 0
direction = LEFT
axis = c.y_axis
if(isX) :
angle = np.pi / 2
direction = DOWN
axis = c.x_axis
triangle = RegularPolygon(n=3, start_angle=angle, stroke_width=0).set_fill(
color=triangle_color,
opacity=1,
)
triangle.height = triangle_size
if(isX) : triangle.move_to(c.coords_to_point(val, 0), UP)
else : triangle.next_to(c.coords_to_point(0, val), LEFT, buff = 0)
if label is not None:
t_label = MathTex(label, color = label_color, arg_separator=" ", substrings_to_isolate=[" ","="])#axis._create_label_tex(label, color=label_color)
t_label.next_to(triangle, direction)
T_label_group.add(t_label)
T_label_group.add(triangle)
if(hasLine):
line = c.get_horizontal_line( #TODO fix the line
c.i2gp(val, graph),
color=line_color,
line_func=line_func,
)
if(isX):
line = c.get_vertical_line(
c.i2gp(val, graph),
color=line_color,
line_func=line_func,
)
T_label_group.add(line)
return T_label_group
class Converging(Scene):
def construct(self):
# constants
function_color = BLUE
dashed_color = ORANGE
# computation of the graph
f = lambda x: 0.3*(x-1)*(x-3)+1
x_0 = 0.2
# fixpoint pairs
iterations = 5
x = x_0
fixpoint_pairs = []
for _ in range(iterations):
f_x = f(x)
fixpoint_pairs.append([x, f_x])
x = f_x
# create the axes and the curve
ax = Axes(
x_range=[0, 2.5], x_length=7,
y_range=[0, 2.1], y_length=5,
axis_config={'include_tip': True, 'include_ticks': False}
)
function_tex = MathTex("f(x) = 0.3(x-1)(x-3)+1").scale(0.5).to_corner(DR)
title = Tex("Fixpoint Iteration : Diverging").to_corner(UL,buff=0.2)
graph = ax.plot(f, color=function_color)
diagonal_line = DashedLine(ax.coords_to_point(0, 0), ax.coords_to_point(2.0, 2.0), color=DARK_GRAY)
x_label = ax.get_x_axis_label("x")
y_label = ax.get_y_axis_label("f(x)")
x_tracker = ValueTracker(x_0)
red_dot_tracked = Dot(ax.coords_to_point(x_tracker.get_value(), f(x_tracker.get_value())), color="#FF0000", stroke_width=2, stroke_color=WHITE).set_z_index(100)
always_redraw(lambda: red_dot_tracked.move_to(ax.coords_to_point(x_tracker.get_value(), f(x_tracker.get_value()))))
graph_group = VGroup(ax, graph, diagonal_line, x_label, y_label, red_dot_tracked).to_edge(LEFT,buff=3)
# meowwwwwwwnimation
self.play(Write(title), Write(function_tex), Create(graph_group), run_time=2)
x_n_list = VGroup().next_to(graph_group, RIGHT, buff=0.5)
for i,(x,f_x) in enumerate(fixpoint_pairs):
# Create components
dot = Dot(ax.coords_to_point(x, f_x), color=GREEN_C)
dash_length = 0.15
line_x = DashedLine(ax.coords_to_point(x, 0), ax.coords_to_point(x, f_x), color=dashed_color,dash_length=dash_length)
line_x_inside = DashedLine(ax.coords_to_point(x, x), ax.coords_to_point(x, f_x), color=dashed_color,dash_length=dash_length)
line_y = DashedLine(ax.coords_to_point(0, f_x), ax.coords_to_point(x, f_x), color=dashed_color,dash_length=dash_length)
line_y_inside = DashedLine(ax.coords_to_point(x, f_x), ax.coords_to_point(f_x, f_x), color=dashed_color,dash_length=dash_length)
line_x_down = DashedLine(ax.coords_to_point(f_x, f_x), ax.coords_to_point(f_x, f(f_x)), color=dashed_color,dash_length=dash_length)
x_n_label_group = get_t_label(ax, True, False, x, graph,f"x_{i}={round(x,2)}")
y_n_label_group = get_t_label(ax, False, False, f_x, graph,f"f(x_{i})={round(f_x,2)}")
# Show x label
if i == 0:
self.play(
Create(x_n_label_group),
run_time=1
)
else:
self.play(
TransformMatchingShapes(x_n_list[i-1][2].copy(), x_n_label_group),
)
# Transform x label to function call
tmp = x_n_label_group[0].copy()
tmp2 = MathTex(f"f(x_{i})").next_to(dot, UP)
self.play(TransformMatchingShapes(tmp, tmp2), Create(line_x), run_time=1)
self.wait(0.75)
# Transform into y label
self.play(TransformMatchingShapes(tmp2, y_n_label_group),Transform(line_x,line_x_inside), Create(line_y), run_time=1)
self.wait(0.75)
# Transform lines and hide x_label
self.play(Transform(line_y,line_y_inside),
FadeOut(x_n_label_group), run_time=0.5)
# Move dot
self.play(Create(dot), Circumscribe(y_n_label_group[0][2]),Create(line_x_down),x_tracker.animate.set_value(f_x))
# Move y label in to list
x_n_list += MathTex(f"f(x_{i})={round(f_x,2)}=x_{i+1}",substrings_to_isolate=["="]).scale(0.7).move_to(y_n_label_group[0])
# transform into xi+1 label
self.play(TransformMatchingShapes(y_n_label_group, x_n_list[i]), run_time=0.5)
self.play(x_n_list.animate.arrange(DOWN, buff=0.1).next_to(graph_group, RIGHT), run_time=0.8)
self.wait(0.5)
self.wait(3)
with tempconfig({"dry_run":False, "output_file":"gl_test", "renderer": "cairo", "quality": "production_quality", "force_window": False, "disable_caching": False, "window_location":"0,0", "window_monitor":1}):
start = time.time()
scene = Converging()
scene.render(preview=True)
print(time.time() - start)
FFMPEG
Output of ffmpeg -version:
ffmpeg version n5.0 Copyright (c) 2000-2022 the FFmpeg developers
built with gcc 11.2.0 (GCC)
Related Issues
- #1957
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by running the supplied Converging scene with caching enabled and disabled, comparing the reported timings for Cairo and OpenGL. Trace the file-writing and rendering activity referenced in tex_file_writing.py and scene.py. Done means identifying and correcting the caching slowdown, with benchmarks showing cached runs are faster than uncached runs.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- performance
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100