def test_chess(test_env): slide = test_env.slide board = slide.box(width=500, height=500) board.new_style("black", color="black", size=50) colors = ["#e0e0ff", "#A0A0ff"] tiles = {} for i in range(8): row = board.box(height="fill", width="100%", horizontal=True) for j in range(8): b = row.box(width="fill", height="100%") b.rect(bg_color=colors[(i + j) % 2]) tiles[(j, i)] = b.overlay(z_level=1) board.rect(color="black") points = [ tiles[(3, 4)].mid_point(), tiles[(3, 2)].mid_point(), tiles[(4, 2)].mid_point() ] arrow = Arrow(30) slide.box(show="1-3").line(points, color="green", stroke_width=15, end_arrow=arrow) tiles[(3, 4)].box(show="1").text("♞", "black") tiles[(3, 3)].box(show="2").text("♞", "black") tiles[(3, 2)].box(show="3").text("♞", "black") tiles[(4, 2)].box(show="4").text("♞", "black") test_env.check("chess", 4)
def intro_slide(slides: Slides): slide = slides.new_slide() slide.set_style("text", s(size=60, bold=True)) slide.set_style("orange", slide.get_style("text").compose(s(color="orange"))) safe = slide.box() safe.text("Fast & ~orange{Safe}", style="text") slide.box(height=100) line = slide.box(width="fill", horizontal=True) development = line.box(width="50%", y=0) development.overlay(show="2-3").text("Memory safety") development.overlay(show="4").text("Memory safety", style=s(color="orange")) performance = line.box(width="50%", y=0, show="3+") performance.text("Fearless concurrency") arrow = Arrow(20) slide.box(show="2+").line( [safe.p("80%", "100%"), development.p("50%", 0)], stroke_width=5, color="orange", end_arrow=arrow) slide.box(show="3+").line( [safe.p("80%", "100%"), performance.p("50%", 0)], stroke_width=5, color="orange", end_arrow=arrow)
def intro_slide(slides: Slides): slide = slides.new_slide() slide.set_style("text", s(size=60, bold=True)) slide.set_style("orange", slide.get_style("text"), s(color="orange")) fast = slide.box() fast.text("~orange{Fast} & Safe", style="text") slide.box(height=100) line = slide.box(width="fill", horizontal=True) development = line.box(width="50%", y=0) development.overlay().text("Quick development") performance = line.box(width="50%", y=0) performance.text("High performance", style=s(color="orange")) arrow = Arrow(20) slide.box().line( [fast.p("15%", "100%"), development.p("50%", 0)], stroke_width=5, color="orange", end_arrow=arrow) slide.box().line( [fast.p("15%", "100%"), performance.p("50%", 0)], stroke_width=5, color="orange", end_arrow=arrow)
def line(start, end, start_x, end_x, right_x, offset_x, color, show, y="65%"): line_start = code_box.line_box(start, width="fill") line_end = code_box.line_box(end, width="fill") arrow = Arrow(20) start = line_start.p(start_x, y) end = line_end.p(end_x, y) content.box(show=show).line([ start, line_start.p(right_x, y).add(offset_x, 0), line_end.p(right_x, y).add(offset_x, 0), end ], start_arrow=arrow, end_arrow=arrow, stroke_width=5, color=color)
def pointer_to_line(content, code_box, line, x, y, show, textbox_pos=("0", "0"), code_pos=("0", "0")): arrow = Arrow(20) line = code_box.line_box(line, show=show) text_box = content.box(x=x, y=y, show=show) content.box(show=show).line([ text_box.p(textbox_pos[0], textbox_pos[1]), line.p(code_pos[0], code_pos[1]) ], end_arrow=arrow, stroke_width=5, color="orange") return text_box
def llvm_iterator(slides: Slides): slide = slides.new_slide() content = slide_header(slide, "Compiles to LLVM") content.box(height=600, x=350).image("imgs/llvm-flow.svg") slide = slides.new_slide() content = slide_header(slide, "Compiles to LLVM") src = content.box(width=700, height=100) src.image("imgs/godbolt-dot-product.svg") content.box(height=60) assembly = content.box(width="fill", height=400, show="2+") assembly.image("imgs/godbolt-dot-product-assembly.svg") arrow = Arrow(20) content.box(show="2+").line( [src.p("50%", "100%"), assembly.p("50%", "0%").add(0, -10)], stroke_width=5, color="orange", end_arrow=arrow)
def test_line_highlight_no_fragments(test_env): slide = test_env.slide slide.box(100, 100, 200, 200).rect(color="green") slide.box(120, 120, 160, 160).rect(bg_color="green") slide.box(320, 100, 200, 200).rect(color="blue", rx=20, ry=20) slide.box(340, 120, 160, 160).rect(bg_color="blue", rx=20, ry=20) slide.polygon([(540, 300), (740, 300), (640, 100)], color="red") slide.polygon([(570, 280), (710, 280), (640, 140)], bg_color="red") slide.line([(760, 100), (940, 100), (760, 300), (960, 300)], color="orange", stroke_width=5) slide.line([(100, 500), (200, 500)], color="black", stroke_width=1) slide.line([(100, 550), (200, 550)], color="black", stroke_width=5) slide.line([(100, 600), (200, 600)], color="black", stroke_width=10) arrow1 = Arrow(10, stroke_width=1) slide.line([(300, 500), (400, 500)], color="black", stroke_width=1, start_arrow=arrow1, end_arrow=arrow1) arrow2 = Arrow(20, stroke_width=5) slide.line([(300, 550), (400, 550)], color="black", stroke_width=5, start_arrow=arrow2, end_arrow=arrow2) arrow3 = Arrow(30, stroke_width=10) slide.line([(300, 600), (400, 600)], color="black", stroke_width=10, start_arrow=arrow3, end_arrow=arrow3) arrow1 = Arrow(10) slide.line([(500, 500), (600, 500)], color="black", stroke_width=1, start_arrow=arrow1, end_arrow=arrow1) arrow2 = Arrow(20) slide.line([(500, 550), (600, 550)], color="black", stroke_width=5, start_arrow=arrow2, end_arrow=arrow2) arrow3 = Arrow(30) slide.line([(500, 600), (600, 600)], color="black", stroke_width=10, start_arrow=arrow3, end_arrow=arrow3) arrow1 = Arrow(10, inner=0.5) slide.line([(700, 500), (800, 500)], color="black", stroke_width=1, start_arrow=arrow1, end_arrow=arrow1) arrow2 = Arrow(20, inner=0.5) slide.line([(700, 550), (800, 550)], color="black", stroke_width=5, start_arrow=arrow2, end_arrow=arrow2) arrow3 = Arrow(30, inner=0.5) slide.line([(700, 600), (800, 600)], color="black", stroke_width=10, start_arrow=arrow3, end_arrow=arrow3) arrow1 = Arrow(10, inner=2.0) slide.line([(900, 500), (1000, 500)], color="black", stroke_width=1, start_arrow=arrow1, end_arrow=arrow1) arrow2 = Arrow(20, inner=2.0) slide.line([(900, 550), (1000, 550)], color="black", stroke_width=5, start_arrow=arrow2, end_arrow=arrow2) arrow3 = Arrow(30, inner=2.0) slide.line([(900, 600), (1000, 600)], color="black", stroke_width=10, start_arrow=arrow3, end_arrow=arrow3) test_env.check("shapes")
def test_shapes(test_env): slide = test_env.slide slide.box(x=650, y=350, width=50, height=50).ellipse(bg_color="green") slide.box(x=720, y=350, width=150, height=50).ellipse( bg_color="purple", color="yellow", stroke_width=10 ) slide.box(x=900, y=350, width=50, height=100).ellipse(bg_color="blue") slide.box(x=100, y=100, width=200, height=200).rect(color="green") slide.box(x=120, y=120, width=160, height=160).rect(bg_color="green") slide.box(x=320, y=100, width=200, height=200).rect(color="blue", rx=20, ry=20) slide.box(x=340, y=120, width=160, height=160).rect(bg_color="blue", rx=20, ry=20) slide.polygon([(540, 300), (740, 300), (640, 100)], color="red") slide.polygon([(570, 280), (710, 280), (640, 140)], bg_color="red") slide.line( [(760, 100), (940, 100), (760, 300), (960, 300)], color="orange", stroke_width=5 ) slide.line([(100, 500), (200, 500)], color="black", stroke_width=1) slide.line([(100, 550), (200, 550)], color="black", stroke_width=5) slide.line([(100, 600), (200, 600)], color="black", stroke_width=10) arrow1 = Arrow(10, stroke_width=1) slide.line( [(300, 500), (400, 500)], color="black", stroke_width=1, start_arrow=arrow1, end_arrow=arrow1, ) arrow2 = Arrow(20, stroke_width=5) slide.line( [(300, 550), (400, 550)], color="black", stroke_width=5, start_arrow=arrow2, end_arrow=arrow2, ) arrow3 = Arrow(30, stroke_width=10) slide.line( [(300, 600), (400, 600)], color="black", stroke_width=10, start_arrow=arrow3, end_arrow=arrow3, ) arrow1 = Arrow(10) slide.line( [(500, 500), (600, 500)], color="black", stroke_width=1, start_arrow=arrow1, end_arrow=arrow1, ) arrow2 = Arrow(20) slide.line( [(500, 550), (600, 550)], color="black", stroke_width=5, start_arrow=arrow2, end_arrow=arrow2, ) arrow3 = Arrow(30) slide.line( [(500, 600), (600, 600)], color="black", stroke_width=10, start_arrow=arrow3, end_arrow=arrow3, ) arrow1 = Arrow(10, inner=0.5) slide.line( [(700, 500), (800, 500)], color="black", stroke_width=1, start_arrow=arrow1, end_arrow=arrow1, ) arrow2 = Arrow(20, inner=0.5) slide.line( [(700, 550), (800, 550)], color="black", stroke_width=5, start_arrow=arrow2, end_arrow=arrow2, ) arrow3 = Arrow(30, inner=0.5) slide.line( [(700, 600), (800, 600)], color="black", stroke_width=10, start_arrow=arrow3, end_arrow=arrow3, ) arrow1 = Arrow(10, inner=2.0) slide.line( [(900, 500), (1000, 500)], color="black", stroke_width=1, start_arrow=arrow1, end_arrow=arrow1, ) arrow2 = Arrow(20, inner=2.0) slide.line( [(900, 550), (1000, 550)], color="black", stroke_width=5, start_arrow=arrow2, end_arrow=arrow2, ) arrow3 = Arrow(30, inner=2.0) slide.line( [(900, 600), (1000, 600)], color="black", stroke_width=10, start_arrow=arrow3, end_arrow=arrow3, ) # Dashes # dash(10) space(10) ... slide.line([(100, 350), (500, 350)], stroke_width=10, stroke_dasharray="10") # dash(10) space(20) ... slide.line([(100, 380), (500, 380)], stroke_width=10, stroke_dasharray="10 20") # dash(20) space(10) dash(2) space(10) ... slide.line([(100, 410), (500, 410)], stroke_width=10, stroke_dasharray="20 10 2 10") # dashed rectangle slide.box(x=550, y=350, width=50, height=50).rect( stroke_width=5, stroke_dasharray="2", color="black", rx=5, ry=5 )
def test_path(test_env): COLOR1 = "blue" slide = test_env.slide box = slide.box(height="80%", width="80%").rect(color="black") arrow1 = Arrow(10) box.path( [("M", box.p(0, 0)), ("L", (300, 400)), ("Q", (400, 400), (300, 500))], end_arrow=arrow1, ) box.path( [ ("M", box.p(0, 0)), ("C", box.p(0, -40), box.p("100%", -40), box.p("100%", 0)), ], color="red", stroke_width=4, bg_color="blue", ) root = ( slide.box(x=250, y="[50%]", width=100, height=50) .rect(color=COLOR1, bg_color="#EEE", rx=5, ry=5) .text("Root") ) child1 = ( slide.box(x=650, y="[20%]", width=100, height=50) .rect(color=COLOR1, bg_color="#EEE", rx=5, ry=5) .text("Child1") ) child2 = ( slide.box(x=650, y="[80%]", width=100, height=50) .rect(color=COLOR1, bg_color="#EEE", rx=5, ry=5) .text("Child2") ) arrow = Arrow(10) # Path root -> child1 r1 = root.p("100%", "50%") c1 = child1.p("0%", "50%") # See SVG <path> documentation for commands explanation # In short: M = move to, L = line to, C/S = bezier curve, Q/T = quadratic slide.path( [("M", r1), ("C", r1.add(300, 0), c1.add(-300, 0), c1)], end_arrow=arrow, stroke_width=2, color=COLOR1, ) # Path root -> child2 c2 = child2.p("0%", "50%") slide.path( [("M", r1), ("Q", c2.add(-100, 0), c2)], end_arrow=arrow, stroke_width=2, color=COLOR1, stroke_dasharray="10", ) # Path chiled1 -> child1 c1t = child1.p("50%", "0%") c1r = child1.p("100%", "50%") slide.path( [("M", c1t), ("C", c1t.add(0, -100), c1r.add(100, 0), c1r)], end_arrow=arrow, stroke_width=2, color=COLOR1, ) slide.path([("M", (650, 350)), ("L", (750, 350))], stroke_width=4, color="green") slide.path( [("M", (600, 450)), ("L", (700, 250)), ("L", (800, 450))], stroke_width=4, color="red", ) slide.path( [("M", (600, 450)), ("Q", (700, 250), (800, 450))], bg_color="blue", color=None )
label = slide.box(100, 400, 200, 130, show="5") label.update_style("default", color="white") label.rect(bg_color="green", rx=10, ry=10) label.text("Comment for\na line") # Here we creates the triangle heading to a line, # method 'p' returns a position relatively to the box label.polygon([ label.p("99%", "40%"), label.p("99%", "60%"), code_box.line_box(4).p(0, "50%") ], bg_color="green") # Now we are creating an arrow head for the orange line arrow = Arrow(10) p1 = code_box.line_box(0).p("100%", "50%") p2 = code_box.line_box(5).p("100%", "50%") slide.box(show="6").line( [p1, p1.add(40, 0), p2.add(40, 0), p2], stroke_width=3, color="orange", end_arrow=arrow) # Console demo ############################################ slide = slides.new_slide() slide.derive_style("code", "shell", color="white") slide.new_style("prompt", color="#aaaaff") slide.new_style("cmd", color="yellow")
def cache_conflicts(slides: SlideDeck, backup: bool): if backup: slide = new_slide(slides) content = slide_header(slide, "Code (backup)") code( content.box(), """// Addresses of N integers, each `offset` bytes apart std::vector<int*> data = ...; for (auto ptr: data) { *ptr += 1; } // Offsets: 4, 64, 4000, 4096, 4128""") slide = new_slide(slides) content = slide_header(slide, "Result (backup)") content.box(height=600).image("images/example1-time.png") slide = new_slide(slides) content = slide_header(slide, "Cache memory") content.box(height=600).image("images/haswell-diagram.png") content.box(width=230, height=40, x=816, y=530).rect(color=COLOR_BACKEND, stroke_width=3) slide = new_slide(slides) content = slide_header(slide, "How are (L1) caches implemented") list_wrapper = content.box() list_item(list_wrapper).text("N-way set associative table") list_item(list_wrapper, level=1, show="last+").text("Hardware hash table") list_item(list_wrapper, show="next+").text("Key = address (8B)") list_item(list_wrapper, show="next+").text("Entry = cache line (64B)") slide = new_slide(slides) content = slide_header(slide, "N-way set associative cache") hash_size = 8 hash_dimension = 60 def table(wrapper: Box, size, dimension, buckets=None, bucket_indices=True): htable = wrapper.box(horizontal=True) items = [] for i in range(size): cell = htable.box(width=dimension, height=dimension, horizontal=True).rect("black", stroke_width=2) items.append(cell) if buckets: bucket_width = int((size / buckets) * dimension) for i in range(buckets): pos = i * bucket_width htable.box(x=pos, y=0, width=bucket_width, height=dimension).rect("black", stroke_width=6) if bucket_indices: htable.box(x=pos, y=dimension - 5, width=bucket_width).text(str(i)) return (htable, items) content.box().text("Size = {} cache lines".format(hash_size), style="notice") (htable, hitems) = table(content.box(p_top=20), hash_size, hash_dimension) arrow_wrapper = content.box() arrow = Arrow(20) arrow_wrapper.box().line([ hitems[0].p("50%", 0).add(0, -20), hitems[-1].p("50%", 0).add(0, -20), ], start_arrow=arrow, end_arrow=arrow, stroke_width=5, color=COLOR_NOTE) content.box( p_top=20, show="next+").text("Associativity (N) - # of cache lines per bucket") content.box(p_top=10, show="next+").text("# of buckets = Size / N") row = content.box(horizontal=True, p_top=20) lcol = row.box(y=0) rcol = row.box(y=0, p_left=20) def htable_row(text, block_count): padding = 20 height = 110 lcol.box(show="next+", p_top=padding, height=height).text(text) return table(rcol.box(show="last+", p_top=padding, height=height), hash_size, hash_dimension, block_count) htable_row("N = 1 (direct mapped)", hash_size) htable_row("N = {} (fully associative)".format(hash_size), 1) htable_row("N = 2", hash_size // 2) slide = new_slide(slides) content = slide_header(slide, "How are addresses hashed?") content.box().text("64-bit address:") row = content.box(horizontal=True, width=800) widths = ["60%", "25%", "15%"] address_colors = ["#B22222", "#007944", "#0018AE"] labels = ["Tag", "Index", "Offset"] for i in range(3): wrapper = row.box(width=widths[i]).rect(color=address_colors[i], stroke_width=4) wrapper.box(padding=4).text(labels[i]) labelrow = content.box(horizontal=True, x=220) labelrow.box().text("63") labelrow.box(p_left=770).text("0") list_wrapper = content.box(p_top=20) list_item(list_wrapper, show="next+").text("Offset", "bold") list_item(list_wrapper, level=1, show="last+").text("Selects byte within a cache line") list_item(list_wrapper, level=1, show="last+").text("log2(cache line size) bits") list_item(list_wrapper, show="next+").text("Index", "bold") list_item(list_wrapper, level=1, show="last+").text("Selects bucket within the cache") list_item(list_wrapper, level=1, show="last+").text("log2(bucket count) bits") list_item(list_wrapper, show="next+").text("Tag", "bold") list_item(list_wrapper, level=1, show="last+").text("Used for matching") slide = new_slide(slides) content = slide_header(slide, "N-way set associative cache") queue = content.box(x="55%", y=40, horizontal=True) queue.box(p_right=40).text("Cache lines:") colors = ("#F0134D", "#FF6F5E", "#F0134D") cacheline_labels = ("A", "B", "C") for i in range(3): queue.box(width=hash_dimension, height=hash_dimension).rect(color="black", bg_color=colors[i], stroke_width=5).text( cacheline_labels[i], style=s(bold=True, color="white")) index = content.box(x="55%", y=90, horizontal=True) index.box(p_right=75).text("Index bits:") index_bits = (0, 1, 0) for i in range(3): index.box(width=hash_dimension, height=hash_dimension).text(str(index_bits[i])) def insert(slot, show, item): wrapper = slot.overlay(show=show) wrapper.rect(bg_color=colors[item]) wrapper.text(cacheline_labels[item], style=s(bold=True, color="white")) row = content.box(horizontal=True, p_top=20) lcol = row.box(y=0) rcol = row.box(y=0, p_left=20) def htable_row(text, block_count): padding = 20 height = 140 lcol.box(show="next+", p_top=padding, height=height).text(text) return table(rcol.box(show="last+", p_top=padding, height=height), hash_size, hash_dimension, block_count) (_, hitems) = htable_row("N = 1", hash_size) insert(hitems[0], "next+", 0) insert(hitems[1], "next+", 1) insert(hitems[0], "next+", 2) (_, hitems) = htable_row("N = {}".format(hash_size), 1) insert(hitems[0], "next+", 0) insert(hitems[1], "next+", 1) insert(hitems[2], "next+", 2) (_, hitems) = htable_row("N = 2", hash_size // 2) insert(hitems[0], "next+", 0) insert(hitems[2], "next+", 1) insert(hitems[1], "next+", 2) slide = new_slide(slides) slide.update_style("default", s(size=46)) slide.update_style("bold", s(size=46)) content = slide_header(slide, "Intel L1 cache") bash(content.box(), """$ getconf -a | grep LEVEL1_DCACHE LEVEL1_DCACHE_SIZE 32768 LEVEL1_DCACHE_ASSOC 8 LEVEL1_DCACHE_LINESIZE 64""", text_style=s(align="left")) list_wrapper = content.box(p_top=20) list_item( list_wrapper, show="next+").text("~bold{Cache line size} - 64 B (6 offset bits)") list_item(list_wrapper, show="next+").text("~bold{Associativity} (N) - 8") list_item(list_wrapper, show="next+").text("~bold{Size} - 32768 B") list_item(list_wrapper, show="next+").text("32768 / 64 => 512 cache lines") list_item(list_wrapper, show="next+").text("512 / 8 => 64 buckets (6 index bits)") slides.set_style("tag", s(color=address_colors[0])) tag = slides.get_style("tag") slides.set_style("index", tag.compose(s(color=address_colors[1]))) slides.set_style("offset", tag.compose(s(color=address_colors[2]))) styles = ["tag", "index", "offset"] colors = ["#F0134D", "#FF6F5E", "#1F6650", "#40BFC1"] def address(cols, content, next=True, use_style=True, row=0): for i, col in enumerate(cols): show = "1+" if next: show = "next+" if i == 0 else "last+" style = "default" if use_style: if i == 0: style = s(color=colors[row]) else: style = styles[i - 1] col.box(show=show).text(content[i], style=style) slide = new_slide(slides) content = slide_header(slide, "Offset = 4B") width = 700 columns = 4 row = content.box(horizontal=True) cols = [row.box(width=width // columns) for _ in range(columns)] address(cols, ("Number", "Tag", "Index", "Offset"), next=False, use_style=False) address(cols, ("A", "..100000", "000000", "000000"), next=False) address(cols, ("B", "..100000", "000000", "000100"), row=1) address(cols, ("C", "..100000", "000000", "001000"), row=2) address(cols, ("D", "..100000", "000000", "001100"), row=3) hash_dimension = 80 (htable, hitems) = table(content.box(p_top=20), hash_size, hash_dimension, hash_size // 2) for i in range(4): hitems[0].box(show="{}+".format(i + 1), width=hash_dimension // 4, height=hash_dimension).rect(bg_color=colors[i]) list_wrapper = content.box(p_top=40) list_item( list_wrapper, show="next+").text("Same bucket, same cache line for each number") list_item(list_wrapper, show="next+").text("Most efficient, no space is wasted") slide = new_slide(slides) content = slide_header(slide, "Offset = 64B") row = content.box(horizontal=True) cols = [row.box(width=width // columns) for _ in range(columns)] address(cols, ("Number", "Tag", "Index", "Offset"), next=False, use_style=False) address(cols, ("A", "..100000", "000000", "000000"), next=False) address(cols, ("B", "..100000", "000001", "000000"), row=1) address(cols, ("C", "..100000", "000010", "000000"), row=2) address(cols, ("D", "..100000", "000011", "000000"), row=3) (htable, hitems) = table(content.box(p_top=20), hash_size, hash_dimension, hash_size // 2) for i in range(4): hitems[i * 2].box(show="{}+".format(i + 1), width=hash_dimension // 4, height=hash_dimension, x=0).rect(bg_color=colors[i]) list_wrapper = content.box(p_top=40) list_item(list_wrapper, show="next+").text("Different bucket for each number") list_item(list_wrapper, show="next+").text("Wastes 60B in each cache line") list_item(list_wrapper, show="next+").text("Equally distributed among buckets") slide = new_slide(slides) content = slide_header(slide, "Offset = 4096B") row = content.box(horizontal=True) cols = [row.box(width=width // columns) for _ in range(columns)] address(cols, ("Number", "Tag", "Index", "Offset"), next=False, use_style=False) address(cols, ("A", "..100000", "000000", "000000"), next=False) address(cols, ("B", "..100001", "000000", "000000"), row=1) address(cols, ("C", "..100010", "000000", "000000"), row=2) address(cols, ("D", "..100011", "000000", "000000"), row=3) (htable, hitems) = table(content.box(p_top=20), hash_size, hash_dimension, hash_size // 2) for i in range(4): hitems[i % 2].box(show="{}+".format(i + 1), width=hash_dimension // 4, height=hash_dimension, x=0).rect(bg_color=colors[i]) list_wrapper = content.box(p_top=40) list_item(list_wrapper, show="next+").text( "Same bucket, but different cache lines for each number!") list_item(list_wrapper, show="next+").text("Bucket full => evictions necessary") slide = new_slide(slides) content = slide_header(slide, "How to measure?") content.box().text("~tt{l1d.replacement}", style=s(size=48)) content.box( p_top=20).text("How many times was a cache line loaded into L1?") if backup: bash(content.box(p_top=40, show="next+"), """$ perf stat -e l1d.replacement ./example1 4B offset -> 149 558 4096B offset -> 426 218 383""", text_style=s(align="left"))
def project(slides: Slides): slide = slides.new_slide() content = slide_header(slide, "Project management (Cargo)") content.box(height=400).image("imgs/cargo.png") slide = slides.new_slide() slide.update_style("code", s(size=30)) content = slide_header(slide, "Using libraries") line = content.box(width="fill", horizontal=True) cargo = line.box(width="50%", p_right=50) cargo.box().text("Cargo.toml") cargo_code = code( cargo.box(), """ [package] name = "hello_world" version = "0.1.0" [dependencies] ibverbs = "0.4" json = "1.0" protobuf = "2.0" """, "toml") main = line.box(width="50%", show="2+", y=0) main.box().text("main.rs") main_code = code( main.box(), """ use json::parse; fn main() { parse("data.json"); }""") arrow = Arrow(20) p1 = cargo_code.line_box(5).p("100%", "50%") p2 = main_code.line_box(0).p(0, "50%") slide.box(show="2+").line( [p1.add(-40, 0), p1, p2.add(-10, 0)], stroke_width=5, color="orange", end_arrow=arrow) content.box(height=10) content.box(show="3+").text("More than 26k libraries available") slide = slides.new_slide() content = slide_header(slide, "Unified documentation") content.box(width=900).image("imgs/rust-docs.png") slide = slides.new_slide() content = slide_header(slide, "Integrated tooling") def cargo_line(parent, text, code, show="1+", **text_args): wrapper = parent.box(width="fill", horizontal=True, show=show) textbox = wrapper.box(width="50%") textbox = textbox.text(text, **text_args) codebox = wrapper.box(width="40%") bash(codebox, code, x=0, width="fill") return textbox wrapper = content.box(width="fill") cargo_line(wrapper, "Build", "$ cargo build", "1+") cargo_line(wrapper, "Run", "$ cargo run", "2+") slide = slides.new_slide() slide.update_style("code", s(size=40)) content = slide_header(slide, "Integrated tooling (tests)") code(content.box(), """ #[test] fn test_add() { assert_eq!(add(1, 2), 3); } """) content.box(height=20) bash(content.box(show="2+"), "$ cargo test") slide = slides.new_slide() slide.update_style("code", s(size=40)) content = slide_header(slide, "Integrated tooling (benchmarks)") code( content.box(), """ #[bench] fn bench_add_two(b: &mut Bencher) { b.iter(|| add_two(2)); } """) content.box(height=20) bash(content.box(show="2+"), "$ cargo bench") slide = slides.new_slide() content = slide_header(slide, "Integrated tooling") wrapper = content.box(width="fill") cargo_line(wrapper, "Format", "$ cargo fmt") cargo_line(wrapper, "Lint", "$ cargo clippy", "next+") box = cargo_line(wrapper, "Publish to SC", "$ cargo publish", "next+") box = box.line_box(0) box.line([box.p("53%", "55%"), box.p("73%", "55%")], stroke_width=3) slide = slides.new_slide() slide.update_style("code", s(size=24)) content = slide_header(slide, "Build scripts") content.box().text("build.rs") code_width = 940 code_step(content.box(width=code_width, height=400), """ fn main() { // generate Protobuf objects protoc_rust::run("protobuf/message.proto", "src/protos"); // generate C headers cbindgen::Builder::new() .generate() .write_to_file("bindings.h"); } """, "1", ((0, 1, 2, 3, None, None, None, None, 8), (0, 1, 2, 3, 4, 5, 6, 7, 8)), width=code_width) slide = slides.new_slide() content = slide_header(slide, "(interlude)") content.box(height=600).image("imgs/meme-cargo.jpg")