aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Anthony Knyszek <mknyszek@google.com>2025-10-02 01:16:42 +0000
committerMichael Knyszek <mknyszek@google.com>2025-10-29 09:40:14 -0700
commit32fdd4793acb7ac395a5ad92ccccf643554f265f (patch)
treeb16383b9b596a1042a03f68b66ab13e91aa46f5d
parent3989c3b2377d38ed58e49f666fa9182de5a35090 (diff)
downloadgo-x-website-32fdd4793acb7ac395a5ad92ccccf643554f265f.tar.xz
_content/blog/greenteagc: new blog post
Change-Id: I3600285a327351d7e02167c07ecea00bfd62ba07 Reviewed-on: https://go-review.googlesource.com/c/website/+/708757 LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Austin Clements <austin@google.com>
-rw-r--r--_content/blog/greenteagc.md1156
-rw-r--r--_content/blog/greenteagc/avx512.svg354
-rw-r--r--_content/blog/greenteagc/carousel.js37
-rw-r--r--_content/blog/greenteagc/graphflood-path.pngbin0 -> 98218 bytes
-rw-r--r--_content/blog/greenteagc/graphflood-path2.pngbin0 -> 89495 bytes
-rw-r--r--_content/blog/greenteagc/greentea-060.pngbin0 -> 141467 bytes
-rw-r--r--_content/blog/greenteagc/greentea-062.pngbin0 -> 126050 bytes
-rw-r--r--_content/blog/greenteagc/greentea-063.pngbin0 -> 133333 bytes
-rw-r--r--_content/blog/greenteagc/greentea-064.pngbin0 -> 148488 bytes
-rw-r--r--_content/blog/greenteagc/greentea-066.pngbin0 -> 162231 bytes
-rw-r--r--_content/blog/greenteagc/greentea-069.pngbin0 -> 166962 bytes
-rw-r--r--_content/blog/greenteagc/greentea-071.pngbin0 -> 157631 bytes
-rw-r--r--_content/blog/greenteagc/greentea-072.pngbin0 -> 157783 bytes
-rw-r--r--_content/blog/greenteagc/greentea-074.pngbin0 -> 186919 bytes
-rw-r--r--_content/blog/greenteagc/greentea-075.pngbin0 -> 166556 bytes
-rw-r--r--_content/blog/greenteagc/greentea-076.pngbin0 -> 166599 bytes
-rw-r--r--_content/blog/greenteagc/greentea-078.pngbin0 -> 169773 bytes
-rw-r--r--_content/blog/greenteagc/greentea-079.pngbin0 -> 147795 bytes
-rw-r--r--_content/blog/greenteagc/greentea-081.pngbin0 -> 156464 bytes
-rw-r--r--_content/blog/greenteagc/greentea-082.pngbin0 -> 157420 bytes
-rw-r--r--_content/blog/greenteagc/greentea-083.pngbin0 -> 161232 bytes
-rw-r--r--_content/blog/greenteagc/greentea-084.pngbin0 -> 180712 bytes
-rw-r--r--_content/blog/greenteagc/greentea-085.pngbin0 -> 174238 bytes
-rw-r--r--_content/blog/greenteagc/greentea-086.pngbin0 -> 167734 bytes
-rw-r--r--_content/blog/greenteagc/greentea-087.pngbin0 -> 169550 bytes
-rw-r--r--_content/blog/greenteagc/greentea-088.pngbin0 -> 171527 bytes
-rw-r--r--_content/blog/greenteagc/greentea-089.pngbin0 -> 172453 bytes
-rw-r--r--_content/blog/greenteagc/greentea-090.pngbin0 -> 172318 bytes
-rw-r--r--_content/blog/greenteagc/greentea-091.pngbin0 -> 172061 bytes
-rw-r--r--_content/blog/greenteagc/greentea-092.pngbin0 -> 170526 bytes
-rw-r--r--_content/blog/greenteagc/greentea-093.pngbin0 -> 143550 bytes
-rw-r--r--_content/blog/greenteagc/greentea-094.pngbin0 -> 147145 bytes
-rw-r--r--_content/blog/greenteagc/greentea-095.pngbin0 -> 148734 bytes
-rw-r--r--_content/blog/greenteagc/greentea-096.pngbin0 -> 149591 bytes
-rw-r--r--_content/blog/greenteagc/greentea-097.pngbin0 -> 148840 bytes
-rw-r--r--_content/blog/greenteagc/greentea-098.pngbin0 -> 149703 bytes
-rw-r--r--_content/blog/greenteagc/greentea-099.pngbin0 -> 143385 bytes
-rw-r--r--_content/blog/greenteagc/greentea-100.pngbin0 -> 144276 bytes
-rw-r--r--_content/blog/greenteagc/greentea-101.pngbin0 -> 124198 bytes
-rw-r--r--_content/blog/greenteagc/greentea-102.pngbin0 -> 105691 bytes
-rw-r--r--_content/blog/greenteagc/greentea-path.pngbin0 -> 89402 bytes
-rw-r--r--_content/blog/greenteagc/marksweep-007.pngbin0 -> 124903 bytes
-rw-r--r--_content/blog/greenteagc/marksweep-008.pngbin0 -> 133116 bytes
-rw-r--r--_content/blog/greenteagc/marksweep-009.pngbin0 -> 140167 bytes
-rw-r--r--_content/blog/greenteagc/marksweep-010.pngbin0 -> 132584 bytes
-rw-r--r--_content/blog/greenteagc/marksweep-011.pngbin0 -> 135268 bytes
-rw-r--r--_content/blog/greenteagc/marksweep-012.pngbin0 -> 130784 bytes
-rw-r--r--_content/blog/greenteagc/marksweep-013.pngbin0 -> 133392 bytes
-rw-r--r--_content/blog/greenteagc/marksweep-014.pngbin0 -> 134043 bytes
-rw-r--r--_content/blog/greenteagc/marksweep-015.pngbin0 -> 138840 bytes
-rw-r--r--_content/blog/greenteagc/marksweep-016.pngbin0 -> 134186 bytes
-rw-r--r--_content/blog/greenteagc/marksweep-017.pngbin0 -> 124903 bytes
-rw-r--r--_content/blog/greenteagc/marksweep-018.pngbin0 -> 132158 bytes
-rw-r--r--_content/blog/greenteagc/marksweep-019.pngbin0 -> 137685 bytes
-rw-r--r--_content/blog/greenteagc/marksweep-020.pngbin0 -> 137041 bytes
-rw-r--r--_content/blog/greenteagc/marksweep-021.pngbin0 -> 141682 bytes
-rw-r--r--_content/blog/greenteagc/marksweep-022.pngbin0 -> 130170 bytes
-rw-r--r--_content/blog/greenteagc/marksweep-023.pngbin0 -> 136066 bytes
-rw-r--r--_content/blog/greenteagc/marksweep-024.pngbin0 -> 145526 bytes
-rw-r--r--_content/blog/greenteagc/marksweep-025.pngbin0 -> 137286 bytes
-rw-r--r--_content/blog/greenteagc/marksweep-026.pngbin0 -> 139041 bytes
-rw-r--r--_content/blog/greenteagc/marksweep-027.pngbin0 -> 141857 bytes
-rw-r--r--_content/blog/greenteagc/marksweep-028.pngbin0 -> 142726 bytes
-rw-r--r--_content/blog/greenteagc/marksweep-029.pngbin0 -> 142979 bytes
-rw-r--r--_content/blog/greenteagc/marksweep-030.pngbin0 -> 143322 bytes
-rw-r--r--_content/blog/greenteagc/marksweep-031.pngbin0 -> 141243 bytes
-rw-r--r--_content/blog/greenteagc/marksweep-032.pngbin0 -> 135785 bytes
-rw-r--r--_content/blog/greenteagc/marksweep-033.pngbin0 -> 136611 bytes
-rw-r--r--_content/blog/greenteagc/marksweep-034.pngbin0 -> 135915 bytes
-rw-r--r--_content/blog/greenteagc/marksweep-035.pngbin0 -> 136741 bytes
-rw-r--r--_content/blog/greenteagc/marksweep-036.pngbin0 -> 130699 bytes
-rw-r--r--_content/blog/greenteagc/marksweep-037.pngbin0 -> 137829 bytes
-rw-r--r--_content/blog/greenteagc/marksweep-038.pngbin0 -> 144245 bytes
-rw-r--r--_content/blog/greenteagc/marksweep-039.pngbin0 -> 133051 bytes
-rw-r--r--_content/blog/greenteagc/marksweep-040.pngbin0 -> 134904 bytes
-rw-r--r--_content/blog/greenteagc/marksweep-041.pngbin0 -> 135839 bytes
-rw-r--r--_content/blog/greenteagc/marksweep-042.pngbin0 -> 140316 bytes
-rw-r--r--_content/blog/greenteagc/marksweep-043.pngbin0 -> 144636 bytes
-rw-r--r--_content/blog/greenteagc/marksweep-044.pngbin0 -> 140365 bytes
-rw-r--r--_content/blog/greenteagc/marksweep-045.pngbin0 -> 128739 bytes
-rw-r--r--_content/blog/greenteagc/marksweep-046.pngbin0 -> 129492 bytes
-rw-r--r--_content/blog/greenteagc/marksweep-047.pngbin0 -> 122706 bytes
-rw-r--r--_content/blog/greenteagc/marksweep-048.pngbin0 -> 103983 bytes
-rw-r--r--_content/blog/greenteagc/timeline.pngbin0 -> 556351 bytes
84 files changed, 1547 insertions, 0 deletions
diff --git a/_content/blog/greenteagc.md b/_content/blog/greenteagc.md
new file mode 100644
index 00000000..46ce043e
--- /dev/null
+++ b/_content/blog/greenteagc.md
@@ -0,0 +1,1156 @@
+---
+title: The Green Tea Garbage Collector
+date: 2025-10-29
+by:
+- Michael Knyszek
+- Austin Clements
+tags:
+- garbage collection
+- performance
+summary: Go 1.25 includes a new experimental garbage collector, Green Tea.
+---
+
+<style type="text/css" scoped>
+ .centered {
+ position: relative;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ }
+ div.carousel {
+ display: flex;
+ width: 100%;
+ height: auto;
+ overflow-x: auto;
+ scroll-snap-type: x mandatory;
+ -webkit-overflow-scrolling: touch;
+ padding-bottom: 1.1em;
+ }
+ .hide-overflow {
+ overflow-x: hidden !important;
+ }
+ button.scroll-button-left {
+ left: 0;
+ bottom: 0;
+ }
+ button.scroll-button-right {
+ right: 0;
+ bottom: 0;
+ }
+ button.scroll-button {
+ position: absolute;
+ font-size: 1em;
+ font-family: inherit;
+ font-style: oblique;
+ }
+ figure.carouselitem {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ margin: 0;
+ padding: 0;
+ width: 100%;
+ flex-shrink: 0;
+ scroll-snap-align: start;
+ }
+ figure.carouselitem figcaption {
+ display: table-caption;
+ caption-side: top;
+ text-align: left;
+ width: 80%;
+ height: auto;
+ padding: 8px;
+ }
+ figure.captioned {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ margin: 0 auto;
+ padding: 0;
+ width: 95%;
+ }
+ figure.captioned figcaption {
+ display: table-caption;
+ caption-side: top;
+ text-align: center;
+ font-style: oblique;
+ height: auto;
+ padding: 8px;
+ }
+ div.row {
+ display: flex;
+ flex-direction: row;
+ justify-content: center;
+ align-items: center;
+ width: 100%;
+ }
+</style>
+
+Go 1.25 includes a new experimental garbage collector called Green Tea,
+available by setting `GOEXPERIMENT=greenteagc` at build time.
+Many workloads spend around 10% less time in the garbage collector, but some
+workloads see a reduction of up to 40%!
+
+It's production-ready and already in use at Google, so we encourage you to
+try it out.
+We know some workloads don't benefit as much, or even at all, so your feedback
+is crucial to helping us move forward.
+Based on the data we have now, we plan to make it the default in Go 1.26.
+
+To report back with any problems, [file a new issue](/issue/new).
+
+To report back with any successes, reply to [the existing Green Tea issue](
+/issue/73581).
+
+What follows is a blog post based on Michael Knyszek's GopherCon 2025 talk.
+We'll update this blog post with a link to the talk once it's available online.
+
+## Tracing garbage collection
+
+Before we discuss Green Tea let's get us all on the same page about garbage
+collection.
+
+### Objects and pointers
+
+The purpose of garbage collection is to automatically reclaim and reuse memory
+no longer used by the program.
+
+To this end, the Go garbage collector concerns itself with *objects* and
+*pointers*.
+
+In the context of the Go runtime, *objects* are Go values whose underlying
+memory is allocated from the heap.
+Heap objects are created when the Go compiler can't figure out how else to allocate
+memory for a value.
+For example, the following code snippet allocates a single heap object: the backing
+store for a slice of pointers.
+
+```
+var x = make([]*int, 10) // global
+```
+
+
+The Go compiler can't allocate the slice backing store anywhere except the heap,
+since it's very hard, and maybe even impossible, for it to know how long `x` will
+refer to the object for.
+
+*Pointers* are just numbers that indicate the location of a Go value in memory,
+and they're how a Go program references objects.
+For example, to get the pointer to the beginning of the object allocated in the
+last code snippet, we can write:
+
+```
+&x[0] // 0xc000104000
+```
+
+### The mark-sweep algorithm
+
+Go's garbage collector follows a strategy broadly referred to as *tracing garbage
+collection*, which just means that the garbage collector follows, or traces, the
+pointers in the program to identify which objects the program is still using.
+
+More specifically, the Go garbage collector implements the mark-sweep algorithm.
+This is much simpler than it sounds.
+Imagine objects and pointers as a sort of graph, in the computer science sense.
+Objects are nodes, pointers are edges.
+
+The mark-sweep algorithm operates on this graph, and as the name might suggest,
+proceeds in two phases.
+
+In the first phase, the mark phase, it walks the object graph from well-defined
+source edges called *roots*.
+Think global and local variables.
+Then, it *marks* everything it finds along the way as *visited*, to avoid going in
+circles.
+This is analogous to your typical graph flood algorithm, like a depth-first or
+breadth-first search.
+
+Next is the sweep phase.
+Whatever objects were not visited in our graph walk are unused, or *unreachable*,
+by the program.
+We call this state unreachable because it is impossible with normal safe Go code
+to access that memory anymore, simply through the semantics of the language.
+To complete the sweep phase, the algorithm simply iterates through all the
+unvisited nodes and marks their memory as free, so the memory allocator can reuse
+it.
+
+### That's it?
+
+You may think I'm oversimplifying a bit here.
+Garbage collectors are frequently referred to as *magic*, and *black boxes*.
+And you'd be partially right, there are more complexities.
+
+For example, this algorithm is, in practice, executed concurrently with your
+regular Go code.
+Walking a graph that's mutating underneath you brings challenges.
+We also parallelize this algorithm, which is a detail that'll come up again
+later.
+
+But trust me when I tell you that these details are mostly separate from the
+core algorithm.
+It really is just a simple graph flood at the center.
+
+### Graph flood example
+
+Let's walk through an example.
+Navigate through the slideshow below to follow along.
+
+<noscript>
+<i>Scroll horizontally through the slideshow!</i>
+<br />
+<br />
+Consider viewing with JavaScript enabled, which will add "Previous" and "Next"
+buttons.
+This will let you click through the slideshow without the scrolling motion,
+which will better highlight differences between the diagrams.
+<br />
+<br />
+</noscript>
+
+<div class="centered">
+<button type="button" id="marksweep-prev" class="scroll-button scroll-button-left" hidden disabled>← Prev</button>
+<button type="button" id="marksweep-next" class="scroll-button scroll-button-right" hidden>Next →</button>
+<div id="marksweep" class="carousel">
+ <figure class="carouselitem">
+ <img src="greenteagc/marksweep-007.png" />
+ <figcaption>
+ Here we have a diagram of some global variables and Go heap.
+ Let's break it down, piece by piece.
+ </figcaption>
+ </figure>
+ <figure class="carouselitem">
+ <img src="greenteagc/marksweep-008.png" />
+ <figcaption>
+ On the left here we have our roots.
+ These are global variables x and y.
+ They will be the starting point of our graph walk.
+ Since they're marked blue, according to our handy legend in the bottom left, they're currently on our work list.
+ </figcaption>
+ </figure>
+ <figure class="carouselitem">
+ <img src="greenteagc/marksweep-009.png" />
+ <figcaption>
+ On the right side, we have our heap.
+ Currently, everything in our heap is grayed out because we haven't visited any of it yet.
+ </figcaption>
+ </figure>
+ <figure class="carouselitem">
+ <img src="greenteagc/marksweep-010.png" />
+ <figcaption>
+ Each one of these rectangles represents an object.
+ Each object is labeled with its type.
+ This object in particular is an object of type T, whose type definition is on the top left.
+ It's got a pointer to an array of children, and some value.
+ We can surmise that this is some kind of recursive tree data structure.
+ </figcaption>
+ </figure>
+ <figure class="carouselitem">
+ <img src="greenteagc/marksweep-011.png" />
+ <figcaption>
+ In addition to the objects of type T, you'll also notice that we have array objects containing star-Ts.
+ These are pointed to by the "children" field of objects of type T.
+ </figcaption>
+ </figure>
+ <figure class="carouselitem">
+ <img src="greenteagc/marksweep-012.png" />
+ <figcaption>
+ Each square inside of the rectangle represents 8 bytes of memory.
+ A square with a dot is a pointer.
+ If it has an arrow, it is a non-nil pointer pointing to some other object.
+ </figcaption>
+ </figure>
+ <figure class="carouselitem">
+ <img src="greenteagc/marksweep-013.png" />
+ <figcaption>
+ And if it doesn't have a corresponding arrow, then it's a nil pointer.
+ </figcaption>
+ </figure>
+ <figure class="carouselitem">
+ <img src="greenteagc/marksweep-014.png" />
+ <figcaption>
+ Next, these dotted rectangles represents free space, what I'll call a free "slot." We could put an object there, but there currently isn't one.
+ </figcaption>
+ </figure>
+ <figure class="carouselitem">
+ <img src="greenteagc/marksweep-015.png" />
+ <figcaption>
+ You'll also notice that objects are grouped together by these labeled, dotted rounded rectangles.
+ Each of these represents a page: a contiguous block of memory.
+ These pages are labeled A, B, C, and D, and I'll refer to them that way.
+ </figcaption>
+ </figure>
+ <figure class="carouselitem">
+ <img src="greenteagc/marksweep-015.png" />
+ <figcaption>
+ In this diagram, each object is allocated as part of some page.
+ Like in the real implementation, each page here only contains objects of a certain size.
+ This is just how the Go heap is organized.
+ </figcaption>
+ </figure>
+ <figure class="carouselitem">
+ <img src="greenteagc/marksweep-016.png" />
+ <figcaption>
+ Pages are also how we organize per-object metadata.
+ Here you can see seven boxes, each corresponding to one of the seven object slots in page A.
+ </figcaption>
+ </figure>
+ <figure class="carouselitem">
+ <img src="greenteagc/marksweep-016.png" />
+ <figcaption>
+ Each box represents one bit of information: whether or not we have seen the object before.
+ This is actually how the real runtime manages whether an object has been visited, and it'll be an important detail later.
+ </figcaption>
+ </figure>
+ <figure class="carouselitem">
+ <img src="greenteagc/marksweep-017.png" />
+ <figcaption>
+ That was a lot of detail, so thanks for reading along.
+ This will all come into play later.
+ For now, let's just see how our graph flood applies to this picture.
+ </figcaption>
+ </figure>
+ <figure class="carouselitem">
+ <img src="greenteagc/marksweep-018.png" />
+ <figcaption>
+ We start by taking a root off of the work list.
+ We mark it red to indicate that it's now active.
+ </figcaption>
+ </figure>
+ <figure class="carouselitem">
+ <img src="greenteagc/marksweep-019.png" />
+ <figcaption>
+ Following that root's pointer, we find an object of type T, which we add to our work list.
+ Following our legend, we draw the object in blue to indicate that it's on our work list.
+ Note also that we set the seen bit corresponding to this object in our metadata.
+ </figcaption>
+ </figure>
+ <figure class="carouselitem">
+ <img src="greenteagc/marksweep-020.png" />
+ <figcaption>
+ Same goes for the next root.
+ </figcaption>
+ </figure>
+ <figure class="carouselitem">
+ <img src="greenteagc/marksweep-021.png" />
+ <figcaption>
+ Now that we've taken care of all the roots, we're left with two objects on our work list.
+ Let's take an object off the work list.
+ </figcaption>
+ </figure>
+ <figure class="carouselitem">
+ <img src="greenteagc/marksweep-022.png" />
+ <figcaption>
+ What we're going to do now is walk the pointers of the objects, to find more objects.
+ By the way, we call walking the pointers of an object "scanning" the object.
+ </figcaption>
+ </figure>
+ <figure class="carouselitem">
+ <img src="greenteagc/marksweep-023.png" />
+ <figcaption>
+ We find this valid array object…
+ </figcaption>
+ </figure>
+ <figure class="carouselitem">
+ <img src="greenteagc/marksweep-024.png" />
+ <figcaption>
+ … and add it to our work list.
+ </figcaption>
+ </figure>
+ <figure class="carouselitem">
+ <img src="greenteagc/marksweep-025.png" />
+ <figcaption>
+ From here, we proceed recursively.
+ </figcaption>
+ </figure>
+ <figure class="carouselitem">
+ <img src="greenteagc/marksweep-026.png" />
+ <figcaption>
+ We walk the array's pointers.
+ </figcaption>
+ </figure>
+ <figure class="carouselitem">
+ <img src="greenteagc/marksweep-027.png" />
+ <figcaption>
+ </figcaption>
+ </figure>
+ <figure class="carouselitem">
+ <img src="greenteagc/marksweep-028.png" />
+ <figcaption>
+ </figcaption>
+ </figure>
+ <figure class="carouselitem">
+ <img src="greenteagc/marksweep-029.png" />
+ <figcaption>
+ Find some more objects…
+ </figcaption>
+ </figure>
+ <figure class="carouselitem">
+ <img src="greenteagc/marksweep-030.png" />
+ <figcaption>
+ </figcaption>
+ </figure>
+ <figure class="carouselitem">
+ <img src="greenteagc/marksweep-031.png" />
+ <figcaption>
+ </figcaption>
+ </figure>
+ <figure class="carouselitem">
+ <img src="greenteagc/marksweep-032.png" />
+ <figcaption>
+ Then we walk the objects that the array object referred to!
+ </figcaption>
+ </figure>
+ <figure class="carouselitem">
+ <img src="greenteagc/marksweep-033.png" />
+ <figcaption>
+ And note that we still have to walk over all pointers, even if they're nil.
+ We don't know ahead of time if they will be.
+ </figcaption>
+ </figure>
+ <figure class="carouselitem">
+ <img src="greenteagc/marksweep-034.png" />
+ <figcaption>
+ One more object down this branch…
+ </figcaption>
+ </figure>
+ <figure class="carouselitem">
+ <img src="greenteagc/marksweep-035.png" />
+ <figcaption>
+ </figcaption>
+ </figure>
+ <figure class="carouselitem">
+ <img src="greenteagc/marksweep-036.png" />
+ <figcaption>
+ And now we've reached the other branch, starting from that object in page A we found much earlier from one of the roots.
+ </figcaption>
+ </figure>
+ <figure class="carouselitem">
+ <img src="greenteagc/marksweep-036.png" />
+ <figcaption>
+ You may be noticing a last-in-first-out discipline for our work list here, indicating that our work list is a stack, and hence our graph flood is approximately depth-first.
+ This is intentional, and reflects the actual graph flood algorithm in the Go runtime.
+ </figcaption>
+ </figure>
+ <figure class="carouselitem">
+ <img src="greenteagc/marksweep-037.png" />
+ <figcaption>
+ Let's keep going…
+ </figcaption>
+ </figure>
+ <figure class="carouselitem">
+ <img src="greenteagc/marksweep-038.png" />
+ <figcaption>
+ Next we find another array object…
+ </figcaption>
+ </figure>
+ <figure class="carouselitem">
+ <img src="greenteagc/marksweep-039.png" />
+ <figcaption>
+ And walk it…
+ </figcaption>
+ </figure>
+ <figure class="carouselitem">
+ <img src="greenteagc/marksweep-040.png" />
+ <figcaption>
+ </figcaption>
+ </figure>
+ <figure class="carouselitem">
+ <img src="greenteagc/marksweep-041.png" />
+ <figcaption>
+ </figcaption>
+ </figure>
+ <figure class="carouselitem">
+ <img src="greenteagc/marksweep-042.png" />
+ <figcaption>
+ </figcaption>
+ </figure>
+ <figure class="carouselitem">
+ <img src="greenteagc/marksweep-043.png" />
+ <figcaption>
+ </figcaption>
+ </figure>
+ <figure class="carouselitem">
+ <img src="greenteagc/marksweep-044.png" />
+ <figcaption>
+ Just one more object left on our work list…
+ </figcaption>
+ </figure>
+ <figure class="carouselitem">
+ <img src="greenteagc/marksweep-045.png" />
+ <figcaption>
+ Let's scan it…
+ </figcaption>
+ </figure>
+ <figure class="carouselitem">
+ <img src="greenteagc/marksweep-046.png" />
+ <figcaption>
+ </figcaption>
+ </figure>
+ <figure class="carouselitem">
+ <img src="greenteagc/marksweep-047.png" />
+ <figcaption>
+ And we're done with the mark phase! There's nothing we're actively working on and there's nothing left on our work list.
+ Every object drawn in black is reachable, and every object drawn in gray is unreachable.
+ Let's sweep the unreachable objects, all in one go.
+ </figcaption>
+ </figure>
+ <figure class="carouselitem">
+ <img src="greenteagc/marksweep-048.png" />
+ <figcaption>
+ We've converted those objects into free slots, ready to hold new objects.
+ </figcaption>
+ </figure>
+</div>
+</div>
+
+## The problem
+
+After all that, I think we have a handle on what the Go garbage collector is actually doing.
+This process seems to work well enough today, so what's the problem?
+
+Well, it turns out we can spend *a lot* of time executing this particular algorithm in some
+programs, and it adds substantial overhead to nearly every Go program.
+It's not that uncommon to see Go programs spending 20% or more of their CPU time in the
+garbage collector.
+
+Let's break down where that time is being spent.
+
+### Garbage collection costs
+
+At a high level, there are two parts to the cost of the garbage collector.
+The first is how often it runs, and the second is how much work it does each time it runs.
+Multiply those two together, and you get the total cost of the garbage collector.
+
+<figure class="captioned">
+ <figcaption>
+ Total GC cost = Number of GC cycles &times; Average cost per GC cycle
+ </figcaption>
+</figure>
+
+Over the years we've tackled both terms in this equation, and for more on _how often_ the garbage
+collector runs, see [Michael's GopherCon EU talk from 2022](https://www.youtube.com/watch?v=07wduWyWx8M)
+about memory limits.
+[The guide to the Go garbage collector](/doc/gc-guide) also has a lot to say about this topic,
+and is worth a look if you want to dive deeper.
+
+But for now let's focus only on the second part, the cost per cycle.
+
+From years of poring over CPU profiles to try and improve performance, we know two big things
+about Go's garbage collector.
+
+The first is that about 90% of the cost of the garbage collector is spent marking,
+and only about 10% is sweeping.
+Sweeping turns out to be much easier to optimize than marking,
+and Go has had a very efficient sweeper for many years.
+
+The second is that, of that time spent marking, a substantial portion, usually at least 35%, is
+simply spent _stalled_ on accessing heap memory.
+This is bad enough on its own, but it completely gums up the works on what makes modern CPUs
+actually fast.
+
+### "A microarchitectural disaster"
+
+What does "gum up the works" mean in this context?
+The specifics of modern CPUs can get pretty complicated, so let's use an analogy.
+
+Imagine the CPU driving down a road, where that road is your program.
+The CPU wants to ramp up to a high speed, and to do that it needs to be able to see far ahead of it,
+and the way needs to be clear.
+But the graph flood algorithm is like driving through city streets for the CPU.
+The CPU can't see around corners and it can't predict what's going to happen next.
+To make progress, it constantly has to slow down to make turns, stop at traffic lights, and avoid
+pedestrians.
+It hardly matters how fast your engine is because you never get a chance to get going.
+
+Let's make that more concrete by looking at our example again.
+I've overlaid the heap here with the path that we took.
+Each left-to-right arrow represents a piece of scanning work that we did
+and the dashed arrows show how we jumped around between bits of scanning work.
+
+<figure class="captioned">
+ <img src="greenteagc/graphflood-path.png" />
+ <figcaption>
+ The path through the heap the garbage collector took in our graph flood example.
+ </figcaption>
+</figure>
+
+Notice that we were jumping all over memory doing tiny bits of work in each place.
+In particular, we're frequently jumping between pages, and between different parts of pages.
+
+Modern CPUs do a lot of caching.
+Going to main memory can be up to 100x slower than accessing memory that's in our cache.
+CPU caches are populated with memory that's been recently accessed, and memory that's nearby to
+recently accessed memory.
+But there's no guarantee that any two objects that point to each other will *also* be close to each
+other in memory.
+The graph flood doesn't take this into account.
+
+Quick side note: if we were just stalling fetches to main memory, it might not be so bad.
+CPUs issue memory requests asynchronously, so even slow ones could overlap if the CPU could see
+far enough ahead.
+But in the graph flood, every bit of work is small, unpredictable, and highly dependent on the
+last, so the CPU is forced to wait on nearly every individual memory fetch.
+
+And unfortunately for us, this problem is only getting worse.
+There's an adage in the industry of "wait two years and your code will get faster."
+
+But Go, as a garbage collected language that relies on the mark-sweep algorithm, risks the opposite.
+"Wait two years and your code will get slower."
+The trends in modern CPU hardware are creating new challenges for garbage collector performance:
+
+**Non-uniform memory access.**
+For one, memory now tends to be associated with subsets of CPU cores.
+Accesses by *other* CPU cores to that memory are slower than before.
+In other words, the cost of a main memory access [depends on which CPU core is accessing
+it](https://jprahman.substack.com/p/sapphire-rapids-core-to-core-latency).
+It's non-uniform, so we call this non-uniform memory access, or NUMA for short.
+
+**Reduced memory bandwidth.**
+Available memory bandwidth per CPU is trending downward over time.
+This just means that while we have more CPU cores, each core can submit relatively fewer
+requests to main memory, forcing non-cached requests to wait longer than before.
+
+**Ever more CPU cores.**
+Above, we looked at a sequential marking algorithm, but the real garbage collector performs this
+algorithm in parallel.
+This scales well to a limited number of CPU cores, but the shared queue of objects to scan becomes
+a bottleneck, even with careful design.
+
+**Modern hardware features.**
+New hardware has fancy features like vector instructions, which let us operate on a lot of data at once.
+While this has the potential for big speedups, it's not immediately clear how to make that work for
+marking because marking does so much irregular and often small pieces of work.
+
+## Green Tea
+
+Finally, this brings us to Green Tea, our new approach to the mark-sweep algorithm.
+The key idea behind Green Tea is astonishingly simple:
+
+_Work with pages, not objects._
+
+Sounds trivial, right?
+And yet, it took a lot of work to figure out how to order the object graph walk and what we needed to
+track to make this work well in practice.
+
+More concretely, this means:
+* Instead of scanning objects we scan whole pages.
+* Instead of tracking objects on our work list, we track whole pages.
+* We still need to mark objects at the end of the day, but we'll track marked objects locally to each
+ page, rather than across the whole heap.
+
+### Green Tea example
+
+Let's see what this means in practice by looking at our example heap again, but this time
+running Green Tea instead of the straightforward graph flood.
+
+As above, navigate through the annotated slideshow to follow along.
+
+<noscript>
+<i>Scroll horizontally through the slideshow!</i>
+<br />
+<br />
+Consider viewing with JavaScript enabled, which will add "Previous" and "Next"
+buttons.
+This will let you click through the slideshow without the scrolling motion,
+which will better highlight differences between the diagrams.
+<br />
+<br />
+</noscript>
+
+<div class="centered">
+<button type="button" id="greentea-prev" class="scroll-button scroll-button-left" hidden disabled>← Prev</button>
+<button type="button" id="greentea-next" class="scroll-button scroll-button-right" hidden>Next →</button>
+<div id="greentea" class="carousel">
+ <figure class="carouselitem">
+ <img src="greenteagc/greentea-060.png" />
+ <figcaption>
+ This is the same heap as before, but now with two bits of metadata per object rather than one.
+ Again, each bit, or box, corresponds to one of the object slots in the page.
+ In total, we now have fourteen bits that correspond to the seven slots in page A.
+ </figcaption>
+ </figure>
+ <figure class="carouselitem">
+ <img src="greenteagc/greentea-060.png" />
+ <figcaption>
+ The top bits represent the same thing as before: whether or not we've seen a pointer to the object.
+ I'll call these the "seen" bits.
+ The bottom set of bits are new.
+ These "scanned" bits track whether or not we've <i>scanned</i> the object.
+ </figcaption>
+ </figure>
+ <figure class="carouselitem">
+ <img src="greenteagc/greentea-060.png" />
+ <figcaption>
+ This new piece of metadata is necessary because, in Green tea, <b>the work list tracks pages,
+ not objects</b>.
+ We still need to track objects at some level, and that's the purpose of these bits.
+ </figcaption>
+ </figure>
+ <figure class="carouselitem">
+ <img src="greenteagc/greentea-062.png" />
+ <figcaption>
+ We start off the same as before, walking objects from the roots.
+ </figcaption>
+ </figure>
+ <figure class="carouselitem">
+ <img src="greenteagc/greentea-063.png" />
+ <figcaption>
+ </figcaption>
+ </figure>
+ <figure class="carouselitem">
+ <img src="greenteagc/greentea-064.png" />
+ <figcaption>
+ But this time, instead of putting an object on the work list,
+ we put a whole page–in this case page A–on the work list,
+ indicated by shading the whole page blue.
+ </figcaption>
+ </figure>
+ <figure class="carouselitem">
+ <img src="greenteagc/greentea-066.png" />
+ <figcaption>
+ The object we found is also blue to indicate that when we do take this page off of the work list, we will need to look at that object.
+ Note that the object's blue hue directly reflects the metadata in page A.
+ Its corresponding seen bit is set, but its scanned bit is not.
+ </figcaption>
+ </figure>
+ <figure class="carouselitem">
+ <img src="greenteagc/greentea-069.png" />
+ <figcaption>
+ We follow the next root, find another object, and again put the whole page–page C–on the work list and set the object's seen bit.
+ </figcaption>
+ </figure>
+ <figure class="carouselitem">
+ <img src="greenteagc/greentea-071.png" />
+ <figcaption>
+ We're done following roots, so we turn to the work list and take page A off the work list.
+ </figcaption>
+ </figure>
+ <figure class="carouselitem">
+ <img src="greenteagc/greentea-072.png" />
+ <figcaption>
+ Using the seen and scanned bits, we can tell there's one object to scan on page A.
+ </figcaption>
+ </figure>
+ <figure class="carouselitem">
+ <img src="greenteagc/greentea-074.png" />
+ <figcaption>
+ We scan that object, following its pointers.
+ And as a result, we add page B to the work list, since the first object in page A points to an object in page B.
+ </figcaption>
+ </figure>
+ <figure class="carouselitem">
+ <img src="greenteagc/greentea-075.png" />
+ <figcaption>
+ We're done with page A.
+ Next we take page C off the work list.
+ </figcaption>
+ </figure>
+ <figure class="carouselitem">
+ <img src="greenteagc/greentea-076.png" />
+ <figcaption>
+ Similar to page A, there's a single object on page C to scan.
+ </figcaption>
+ </figure>
+ <figure class="carouselitem">
+ <img src="greenteagc/greentea-078.png" />
+ <figcaption>
+ We found a pointer to another object in page B.
+ Page B is already on the work list, so we don't need to add anything to the work list.
+ We simply have to set the seen bit for the target object.
+ </figcaption>
+ </figure>
+ <figure class="carouselitem">
+ <img src="greenteagc/greentea-079.png" />
+ <figcaption>
+ Now it's page B's turn.
+ We've accumulated two objects to scan on page B,
+ and we can process both of these objects in a row, in memory order!
+ </figcaption>
+ </figure>
+ <figure class="carouselitem">
+ <img src="greenteagc/greentea-081.png" />
+ <figcaption>
+ We walk the pointers of the first object…
+ </figcaption>
+ </figure>
+ <figure class="carouselitem">
+ <img src="greenteagc/greentea-082.png" />
+ <figcaption>
+ </figcaption>
+ </figure>
+ <figure class="carouselitem">
+ <img src="greenteagc/greentea-083.png" />
+ <figcaption>
+ </figcaption>
+ </figure>
+ <figure class="carouselitem">
+ <img src="greenteagc/greentea-084.png" />
+ <figcaption>
+ We find a pointer to an object in page A.
+ Page A was previously on the work list, but isn't at this point, so we put it back on the work list.
+ Unlike the original mark-sweep algorithm, where any given object is only added to the work list at
+ most once per whole mark phase, in Green Tea, a given page can reappear on the work list several times
+ during a mark phase.
+ </figcaption>
+ </figure>
+ <figure class="carouselitem">
+ <img src="greenteagc/greentea-085.png" />
+ <figcaption>
+ </figcaption>
+ </figure>
+ <figure class="carouselitem">
+ <img src="greenteagc/greentea-086.png" />
+ <figcaption>
+ We scan the second seen object in the page immediately after the first.
+ </figcaption>
+ </figure>
+ <figure class="carouselitem">
+ <img src="greenteagc/greentea-087.png" />
+ <figcaption>
+ </figcaption>
+ </figure>
+ <figure class="carouselitem">
+ <img src="greenteagc/greentea-088.png" />
+ <figcaption>
+ </figcaption>
+ </figure>
+ <figure class="carouselitem">
+ <img src="greenteagc/greentea-089.png" />
+ <figcaption>
+ We find a few more objects in page A…
+ </figcaption>
+ </figure>
+ <figure class="carouselitem">
+ <img src="greenteagc/greentea-090.png" />
+ <figcaption>
+ </figcaption>
+ </figure>
+ <figure class="carouselitem">
+ <img src="greenteagc/greentea-091.png" />
+ <figcaption>
+ </figcaption>
+ </figure>
+ <figure class="carouselitem">
+ <img src="greenteagc/greentea-092.png" />
+ <figcaption>
+ </figcaption>
+ </figure>
+ <figure class="carouselitem">
+ <img src="greenteagc/greentea-093.png" />
+ <figcaption>
+ We're done scanning page B, so we pull page A off the work list.
+ </figcaption>
+ </figure>
+ <figure class="carouselitem">
+ <img src="greenteagc/greentea-094.png" />
+ <figcaption>
+ This time we only need to scan three objects, not four,
+ since we already scanned the first object.
+ We know which objects to scan by looking at the difference between the "seen" and "scanned" bits.
+ </figcaption>
+ </figure>
+ <figure class="carouselitem">
+ <img src="greenteagc/greentea-095.png" />
+ <figcaption>
+ We'll scan these objects in sequence.
+ </figcaption>
+ </figure>
+ <figure class="carouselitem">
+ <img src="greenteagc/greentea-096.png" />
+ <figcaption>
+ </figcaption>
+ </figure>
+ <figure class="carouselitem">
+ <img src="greenteagc/greentea-097.png" />
+ <figcaption>
+ </figcaption>
+ </figure>
+ <figure class="carouselitem">
+ <img src="greenteagc/greentea-098.png" />
+ <figcaption>
+ </figcaption>
+ </figure>
+ <figure class="carouselitem">
+ <img src="greenteagc/greentea-099.png" />
+ <figcaption>
+ </figcaption>
+ </figure>
+ <figure class="carouselitem">
+ <img src="greenteagc/greentea-100.png" />
+ <figcaption>
+ </figcaption>
+ </figure>
+ <figure class="carouselitem">
+ <img src="greenteagc/greentea-101.png" />
+ <figcaption>
+ We're done! There are no more pages on the work list and there's nothing we're actively looking at.
+ Notice that the metadata now all lines up nicely, since all reachable objects were both seen and scanned.
+ </figcaption>
+ </figure>
+ <figure class="carouselitem">
+ <img src="greenteagc/greentea-101.png" />
+ <figcaption>
+ You may have also noticed during our traversal that the work list order is a little different from the graph flood.
+ Where the graph flood had a last-in-first-out, or stack-like, order, here we're using a first-in-first-out, or queue-like, order for the pages on our work list.
+ </figcaption>
+ </figure>
+ <figure class="carouselitem">
+ <img src="greenteagc/greentea-101.png" />
+ <figcaption>
+ This is intentional.
+ We let seen objects accumulate on each page while the page sits on the queue, so we can process as many as we can at once.
+ That's how we were able to hit so many objects on page A at once.
+ Sometimes laziness is a virtue.
+ </figcaption>
+ </figure>
+ <figure class="carouselitem">
+ <img src="greenteagc/greentea-102.png" />
+ <figcaption>
+ And finally we can sweep away the unvisited objects, as before.
+ </figcaption>
+ </figure>
+</div>
+</div>
+
+### Getting on the highway
+
+Let's come back around to our driving analogy.
+Are we finally getting on the highway?
+
+Let's recall our graph flood picture before.
+
+<figure class="captioned">
+ <img src="greenteagc/graphflood-path2.png" />
+ <figcaption>
+ The path the original graph flood took through the heap required 7 separate scans.
+ </figcaption>
+</figure>
+
+We jumped around a whole lot, doing little bits of work in different places.
+The path taken by Green Tea looks very different.
+
+<figure class="captioned">
+ <img src="greenteagc/greentea-path.png" />
+ <figcaption>
+ The path taken by Green Tea requires only 4 scans.
+ </figcaption>
+</figure>
+
+Green Tea, in contrast, makes fewer, longer left-to-right passes over pages A and B.
+The longer these arrows, the better, and with bigger heaps, this effect can be much stronger.
+*That's* the magic of Green Tea.
+
+It's also our opportunity to ride the highway.
+
+This all adds up to a better fit with the microarchitecture.
+We can now scan objects closer together with much higher probability, so
+there's a better chance we can make use of our caches and avoid main memory.
+Likewise, per-page metadata is more likely to be in cache.
+Tracking pages instead of objects means work lists are smaller,
+and less pressure on work lists means less contention and fewer CPU stalls.
+
+And speaking of the highway, we can take our metaphorical engine into gears we've never been able to
+before, since now we can use vector hardware!
+
+### Vector acceleration
+
+If you're only vaguely familiar with vector hardware, you might be confused as to how we can use it here.
+But besides the usual arithmetic and trigonometric operations,
+recent vector hardware supports two things that are valuable for Green Tea:
+very wide registers, and sophisticated bit-wise operations.
+
+Most modern x86 CPUs support AVX-512, which has 512-bit wide vector registers.
+This is wide enough to hold all of the metadata for an entire page in just two registers,
+right on the CPU, enabling Green Tea to work on an entire page in just a few straight-line
+instructions.
+Vector hardware has long supported basic bit-wise operations on whole vector registers, but starting
+with AMD Zen 4 and Intel Ice Lake, it also supports a new bit vector "Swiss army knife" instruction
+that enables a key step of the Green Tea scanning process to be done in just a few CPU cycles.
+Together, these allow us to turbo-charge the Green Tea scan loop.
+
+This wasn't even an option for the graph flood, where we'd be jumping between scanning objects that
+are all sorts of different sizes.
+Sometimes you needed two bits of metadata and sometimes you needed ten thousand.
+There simply wasn't enough predictability or regularity to use vector hardware.
+
+If you want to nerd out on some of the details, read along!
+Otherwise, feel free to skip ahead to the [evaluation](#evaluation).
+
+#### AVX-512 scanning kernel
+
+To get a sense of what AVX-512 GC scanning looks like, take a look at the diagram below.
+
+<figure class="captioned">
+ <img src="greenteagc/avx512.svg" />
+ <figcaption>
+ The AVX-512 vector kernel for scanning.
+ </figcaption>
+</figure>
+
+There's a lot going on here and we could probably fill an entire blog post just on how this works.
+For now, let's just break it down at a high level:
+
+1. First we fetch the "seen" and "scanned" bits for a page.
+ Recall, these are one bit per object in the page, and all objects in a page have the same size.
+
+2. Next, we compare the two bit sets.
+ Their union becomes the new "scanned" bits, while their difference is the "active objects" bitmap,
+ which tells us which objects we need to scan in this pass over the page (versus previous passes).
+
+3. We take the difference of the bitmaps and "expand" it, so that instead of one bit per object,
+ we have one bit per word (8 bytes) of the page.
+ We call this the "active words" bitmap.
+ For example, if the page stores 6-word (48-byte) objects, each bit in the active objects bitmap
+ will be copied to 6 bits in the active words bitmap.
+ Like so:
+
+<figure class="captioned">
+ <div class="row"><pre>0 0 1 1 ...</pre> &rarr; <pre>000000 000000 111111 111111 ...</pre></div>
+</figure>
+
+4. Next we fetch the pointer/scalar bitmap for the page.
+ Here, too, each bit corresponds to a word (8 bytes) of the page, and it tells us whether that word
+ stores a pointer.
+ This data is managed by the memory allocator.
+
+5. Now, we take the intersection of the pointer/scalar bitmap and the active words bitmap.
+ The result is the "active pointer bitmap": a bitmap that tells us the location of every
+ pointer in the entire page contained in any live object we haven't scanned yet.
+
+6. Finally, we can iterate over the memory of the page and collect all the pointers.
+ Logically, we iterate over each set bit in the active pointer bitmap,
+ load the pointer value at that word, and write it back to a buffer that
+ will later be used to mark objects seen and add pages to the work list.
+ Using vector instructions, we're able to do this 64 bytes at a time,
+ in just a couple instructions.
+
+Part of what makes this fast is the `VGF2P8AFFINEQB` instruction,
+part of the "Galios Field New Instructions" x86 extension,
+and the bit manipulation Swiss army knife we referred to above.
+It's the real star of the show, since it lets us do step (3) in the scanning kernel very, very
+efficiently.
+It performs a bit-wise [affine
+transformations](https://en.wikipedia.org/wiki/Affine_transformation),
+treating each byte in a vector as itself a mathematical vector of 8 bits
+and multiplying it by an 8x8 bit matrix.
+This is all done over the [Galois field](https://en.wikipedia.org/wiki/Finite_field) `GF(2)`,
+which just means multiplication is AND and addition is XOR.
+The upshot of this is that we can define a few 8x8 bit matrices for each
+object size that perform exactly the 1:n bit expansion we need.
+
+For the full assembly code, see [this
+file](https://cs.opensource.google/go/go/+/master:src/internal/runtime/gc/scan/scan_amd64.s;l=23;drc=889ab74169db2c8758f51c1a199a90266b16669b).
+The "expanders" use different matrices and different permutations for each size class,
+so they're in a [separate file](https://cs.opensource.google/go/go/+/master:src/internal/runtime/gc/scan/expand_amd64.s;drc=889ab74169db2c8758f51c1a199a90266b16669b)
+that's written by a [code generator](https://cs.opensource.google/go/go/+/master:src/internal/runtime/gc/scan/mkasm.go;drc=889ab74169db2c8758f51c1a199a90266b16669b).
+Aside from the expansion functions, it's really not a lot of code.
+Most of it is dramatically simplified by the fact that we can perform most of the above
+operations on data that sits purely in registers.
+And, hopefully soon this assembly code [will be replaced with Go code](/issue/73787)!
+
+Credit to Austin Clements for devising this process.
+It's incredibly cool, and incredibly fast!
+
+### Evaluation
+
+So that's it for how it works.
+How much does it actually help?
+
+It can be quite a lot.
+Even without the vector enhancements, we see reductions in garbage collection CPU costs
+between 10% and 40% in our benchmark suite.
+For example, if an application spends 10% of its time in the garbage collector, then that
+would translate to between a 1% and 4% overall CPU reduction, depending on the specifics of
+the workload.
+A 10% reduction in garbage collection CPU time is roughly the modal improvement.
+(See the [GitHub issue](/issue/73581) for some of these details.)
+
+We've rolled Green Tea out inside Google, and we see similar results at scale.
+
+We're still rolling out the vector enhancements,
+but benchmarks and early results suggest this will net an additional 10% GC CPU reduction.
+
+While most workloads benefit to some degree, there are some that don't.
+
+Green Tea is based on the hypothesis that we can accumulate enough objects to scan on a
+single page in one pass to counteract the costs of the accumulation process.
+This is clearly the case if the heap has a very regular structure: objects of the same size at a
+similar depth in the object graph.
+But there are some workloads that often require us to scan only a single object per page at a time.
+This is potentially worse than the graph flood because we might be doing more work than before while
+trying to accumulate objects on pages and failing.
+
+The implementation of Green Tea has a special case for pages that have only a single object to scan.
+This helps reduce regressions, but doesn't completely eliminate them.
+
+However, it takes a lot less per-page accumulation to outperform the graph flood
+than you might expect.
+One surprise result of this work was that scanning a mere 2% of a page at a time
+can yield improvements over the graph flood.
+
+### Availability
+
+Green Tea is already available as an experiment in the recent Go 1.25 release and can be enabled
+by setting the environment variable `GOEXPERIMENT` to `greenteagc` at build time.
+This doesn't include the aforementioned vector acceleration.
+
+We expect to make it the default garbage collector in Go 1.26, but you'll still be able to opt-out
+with `GOEXPERIMENT=nogreenteagc` at build time.
+Go 1.26 will also add vector acceleration on newer x86 hardware, and include a whole bunch of
+tweaks and improvements based on feedback we've collected so far.
+
+If you can, we encourage you to try at Go tip-of-tree!
+If you prefer to use Go 1.25, we'd still love your feedback.
+See [this GitHub
+comment](/issue/73581#issuecomment-2847696497) with some details on
+what diagnostics we'd be interested in seeing, if you can share, and the preferred channels for
+reporting feedback.
+
+## The journey
+
+Before we wrap up this blog post, let's take a moment to talk about the journey that got us here.
+The human element of the technology.
+
+The core of Green Tea may seem like a single, simple idea.
+Like the spark of inspiration that just one single person had.
+
+But that's not true at all.
+Green Tea is the result of work and ideas from many people over several years.
+Several people on the Go team contributed to the ideas, including Michael Pratt, Cherry Mui, David
+Chase, and Keith Randall.
+Microarchitectural insights from Yves Vandriessche, who was at Intel at the time, also really helped
+direct the design exploration.
+There were a lot of ideas that didn't work, and there were a lot of details that needed figuring out.
+Just to make this single, simple idea viable.
+
+<figure class="captioned">
+ <img src="greenteagc/timeline.png" />
+ <figcaption>
+ A timeline depicting a subset of the ideas we tried in this vein before getting to
+ where we are today.
+ </figcaption>
+</figure>
+
+The seeds of this idea go all the way back to 2018.
+What's funny is that everyone on the team thinks someone else thought of this initial idea.
+
+Green Tea got its name in 2024 when Austin worked out a prototype of an earlier version while cafe
+crawling in Japan and drinking LOTS of matcha!
+This prototype showed that the core idea of Green Tea was viable.
+And from there we were off to the races.
+
+Throughout 2025, as Michael implemented and productionized Green Tea, the ideas evolved and changed even
+further.
+
+This took so much collaborative exploration because Green Tea is not just an algorithm, but an entire
+design space.
+One that we don't think any of us could've navigated alone.
+It's not enough to just have the idea, but you need to figure out the details and prove it.
+And now that we've done it, we can finally iterate.
+
+The future of Green Tea is bright.
+
+Once again, please try it out by setting `GOEXPERIMENT=greenteagc` and let us know how it goes!
+We're really excited about this work and want to hear from you!
+
+<script src="greenteagc/carousel.js"></script>
diff --git a/_content/blog/greenteagc/avx512.svg b/_content/blog/greenteagc/avx512.svg
new file mode 100644
index 00000000..c02fcf37
--- /dev/null
+++ b/_content/blog/greenteagc/avx512.svg
@@ -0,0 +1,354 @@
+<svg version="1.1" width="660" height="600" xmlns="http://www.w3.org/2000/svg">
+ <defs>
+ <linearGradient id="zoom" x1="0" y1="0" x2="0" y2="1">
+ <stop offset="0%" stop-color="#444" />
+ <stop offset="100%" stop-color="#bbb" />
+ </linearGradient>
+ </defs>
+ <path d="M 254.125,43.75 L 260.375,43.75 L 260.375,50.0 L 254.125,50.0 Z" fill="#000" stroke="#888" />
+ <path d="M 247.875,43.75 L 254.125,43.75 L 254.125,50.0 L 247.875,50.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 241.625,43.75 L 247.875,43.75 L 247.875,50.0 L 241.625,50.0 Z" fill="#000" stroke="#888" />
+ <path d="M 231.375,43.75 L 237.625,43.75 L 237.625,50.0 L 231.375,50.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 225.125,43.75 L 231.375,43.75 L 231.375,50.0 L 225.125,50.0 Z" fill="#000" stroke="#888" />
+ <path d="M 218.875,43.75 L 225.125,43.75 L 225.125,50.0 L 218.875,50.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 212.625,43.75 L 218.875,43.75 L 218.875,50.0 L 212.625,50.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 206.375,43.75 L 212.625,43.75 L 212.625,50.0 L 206.375,50.0 Z" fill="#000" stroke="#888" />
+ <path d="M 200.125,43.75 L 206.375,43.75 L 206.375,50.0 L 200.125,50.0 Z" fill="#000" stroke="#888" />
+ <path d="M 193.875,43.75 L 200.125,43.75 L 200.125,50.0 L 193.875,50.0 Z" fill="#000" stroke="#888" />
+ <path d="M 187.625,43.75 L 193.875,43.75 L 193.875,50.0 L 187.625,50.0 Z" fill="#000" stroke="#888" />
+ <path d="M 187.625,40.75 L 260.375,40.75" fill="none" stroke="#729fcf" stroke-width="1.5" />
+ <path d="M 224.0,20.0 L 224.0,20.0 L 224.0,20.0 L 224.0,40.75" fill="none" stroke="#729fcf" stroke-width="1.5" />
+ <rect x="189.0" y="12.0" width="70.0" height="16.0" rx="8" fill="#fff" stroke="#000" />
+ <text font-family="'Segoe UI', Helvetica, Arial, sans-serif" font-size="12" transform="translate(224.0,20.0)" text-anchor="middle" dominant-baseline="central">load</text>
+ <text font-family="'Segoe UI', Helvetica, Arial, sans-serif" font-size="12" transform="translate(174.0,46.0)" text-anchor="end" dominant-baseline="central" paint-order="stroke" stroke-width="4" stroke-linejoin="round" stroke="white">"seen" bits</text>
+ <path d="M 431.75,43.75 L 438.0,43.75 L 438.0,50.0 L 431.75,50.0 Z" fill="#000" stroke="#888" />
+ <path d="M 425.5,43.75 L 431.75,43.75 L 431.75,50.0 L 425.5,50.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 419.25,43.75 L 425.5,43.75 L 425.5,50.0 L 419.25,50.0 Z" fill="#000" stroke="#888" />
+ <path d="M 409.0,43.75 L 415.25,43.75 L 415.25,50.0 L 409.0,50.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 402.75,43.75 L 409.0,43.75 L 409.0,50.0 L 402.75,50.0 Z" fill="#000" stroke="#888" />
+ <path d="M 396.5,43.75 L 402.75,43.75 L 402.75,50.0 L 396.5,50.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 390.25,43.75 L 396.5,43.75 L 396.5,50.0 L 390.25,50.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 384.0,43.75 L 390.25,43.75 L 390.25,50.0 L 384.0,50.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 377.75,43.75 L 384.0,43.75 L 384.0,50.0 L 377.75,50.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 371.5,43.75 L 377.75,43.75 L 377.75,50.0 L 371.5,50.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 365.25,43.75 L 371.5,43.75 L 371.5,50.0 L 365.25,50.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 365.25,40.75 L 438.0,40.75" fill="none" stroke="#e9b96e" stroke-width="1.5" />
+ <path d="M 401.625,20.0 L 401.625,20.0 L 401.625,20.0 L 401.625,40.75" fill="none" stroke="#e9b96e" stroke-width="1.5" />
+ <rect x="366.625" y="12.0" width="70.0" height="16.0" rx="8" fill="#fff" stroke="#000" />
+ <text font-family="'Segoe UI', Helvetica, Arial, sans-serif" font-size="12" transform="translate(401.625,20.0)" text-anchor="middle" dominant-baseline="central">load</text>
+ <text font-family="'Segoe UI', Helvetica, Arial, sans-serif" font-size="12" transform="translate(448.0,46.0)" text-anchor="start" dominant-baseline="central" paint-order="stroke" stroke-width="4" stroke-linejoin="round" stroke="white">"scanned" bits</text>
+ <path d="M 254.125,103.75 L 260.375,103.75 L 260.375,110.0 L 254.125,110.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 247.875,103.75 L 254.125,103.75 L 254.125,110.0 L 247.875,110.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 241.625,103.75 L 247.875,103.75 L 247.875,110.0 L 241.625,110.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 231.375,103.75 L 237.625,103.75 L 237.625,110.0 L 231.375,110.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 225.125,103.75 L 231.375,103.75 L 231.375,110.0 L 225.125,110.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 218.875,103.75 L 225.125,103.75 L 225.125,110.0 L 218.875,110.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 212.625,103.75 L 218.875,103.75 L 218.875,110.0 L 212.625,110.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 206.375,103.75 L 212.625,103.75 L 212.625,110.0 L 206.375,110.0 Z" fill="#000" stroke="#888" />
+ <path d="M 200.125,103.75 L 206.375,103.75 L 206.375,110.0 L 200.125,110.0 Z" fill="#000" stroke="#888" />
+ <path d="M 193.875,103.75 L 200.125,103.75 L 200.125,110.0 L 193.875,110.0 Z" fill="#000" stroke="#888" />
+ <path d="M 187.625,103.75 L 193.875,103.75 L 193.875,110.0 L 187.625,110.0 Z" fill="#000" stroke="#888" />
+ <path d="M 187.625,53.0 L 260.375,53.0" fill="none" stroke="#729fcf" stroke-width="1.5" />
+ <path d="M 187.625,100.75 L 260.375,100.75" fill="none" stroke="#729fcf" stroke-width="1.5" />
+ <path d="M 224.0,53.0 L 224.0,53.0 Q 224.0 58.0,224.0 63.0 L 224.0,76.875 L 224.0,100.75" fill="none" stroke="#729fcf" stroke-width="1.5" />
+ <path d="M 365.25,53.0 L 438.0,53.0" fill="none" stroke="#e9b96e" stroke-width="1.5" />
+ <path d="M 401.625,53.0 L 401.625,53.0 Q 401.625 58.0,396.6529928199303 58.52834136818475 L 224.0,76.875" fill="none" stroke="#e9b96e" stroke-width="1.5" />
+ <circle cx="224.0" cy="76.875" r="10.0" fill="#fff" stroke="#000" />
+ <text font-family="'Segoe UI', Helvetica, Arial, sans-serif" font-size="12" transform="translate(224.0,76.875) skewY(0.0)" text-anchor="middle" dominant-baseline="central">&amp;^</text>
+ <text font-family="'Segoe UI', Helvetica, Arial, sans-serif" font-size="12" transform="translate(174.0,106.0)" text-anchor="end" dominant-baseline="central" paint-order="stroke" stroke-width="4" stroke-linejoin="round" stroke="white">active objects bits</text>
+ <path d="M 431.75,103.75 L 438.0,103.75 L 438.0,110.0 L 431.75,110.0 Z" fill="#000" stroke="#888" />
+ <path d="M 425.5,103.75 L 431.75,103.75 L 431.75,110.0 L 425.5,110.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 419.25,103.75 L 425.5,103.75 L 425.5,110.0 L 419.25,110.0 Z" fill="#000" stroke="#888" />
+ <path d="M 409.0,103.75 L 415.25,103.75 L 415.25,110.0 L 409.0,110.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 402.75,103.75 L 409.0,103.75 L 409.0,110.0 L 402.75,110.0 Z" fill="#000" stroke="#888" />
+ <path d="M 396.5,103.75 L 402.75,103.75 L 402.75,110.0 L 396.5,110.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 390.25,103.75 L 396.5,103.75 L 396.5,110.0 L 390.25,110.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 384.0,103.75 L 390.25,103.75 L 390.25,110.0 L 384.0,110.0 Z" fill="#000" stroke="#888" />
+ <path d="M 377.75,103.75 L 384.0,103.75 L 384.0,110.0 L 377.75,110.0 Z" fill="#000" stroke="#888" />
+ <path d="M 371.5,103.75 L 377.75,103.75 L 377.75,110.0 L 371.5,110.0 Z" fill="#000" stroke="#888" />
+ <path d="M 365.25,103.75 L 371.5,103.75 L 371.5,110.0 L 365.25,110.0 Z" fill="#000" stroke="#888" />
+ <path d="M 187.625,53.0 L 260.375,53.0" fill="none" stroke="#729fcf" stroke-width="1.5" />
+ <path d="M 365.25,100.75 L 438.0,100.75" fill="none" stroke="#729fcf" stroke-width="1.5" />
+ <path d="M 224.0,53.0 L 224.0,53.0 Q 224.0 58.0,228.9720071800697 58.52834136818475 L 401.625,76.875 L 401.625,100.75" fill="none" stroke="#729fcf" stroke-width="1.5" />
+ <path d="M 365.25,53.0 L 438.0,53.0" fill="none" stroke="#e9b96e" stroke-width="1.5" />
+ <path d="M 401.625,53.0 L 401.625,53.0 Q 401.625 58.0,401.625 63.0 L 401.625,76.875" fill="none" stroke="#e9b96e" stroke-width="1.5" />
+ <circle cx="401.625" cy="76.875" r="10.0" fill="#fff" stroke="#000" />
+ <text font-family="'Segoe UI', Helvetica, Arial, sans-serif" font-size="12" transform="translate(401.625,76.875) skewY(0.0)" text-anchor="middle" dominant-baseline="central">|</text>
+ <path d="M 365.25,113.0 L 438.0,113.0" fill="none" stroke="#729fcf" stroke-width="1.5" />
+ <path d="M 401.625,113.0 L 401.625,140.0 L 401.625,140.0 L 401.625,140.0" fill="none" stroke="#729fcf" stroke-width="1.5" />
+ <rect x="366.625" y="132.0" width="70.0" height="16.0" rx="8" fill="#fff" stroke="#000" />
+ <text font-family="'Segoe UI', Helvetica, Arial, sans-serif" font-size="12" transform="translate(401.625,140.0)" text-anchor="middle" dominant-baseline="central">store</text>
+ <text font-family="'Segoe UI', Helvetica, Arial, sans-serif" font-size="12" transform="translate(448.0,106.0)" text-anchor="start" dominant-baseline="central" paint-order="stroke" stroke-width="4" stroke-linejoin="round" stroke="white">new "scanned" bits</text>
+ <path d="M 431.75,213.75 L 438.0,213.75 L 438.0,220.0 L 431.75,220.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 425.5,213.75 L 431.75,213.75 L 431.75,220.0 L 425.5,220.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 419.25,213.75 L 425.5,213.75 L 425.5,220.0 L 419.25,220.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 413.0,213.75 L 419.25,213.75 L 419.25,220.0 L 413.0,220.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 406.75,213.75 L 413.0,213.75 L 413.0,220.0 L 406.75,220.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 400.5,213.75 L 406.75,213.75 L 406.75,220.0 L 400.5,220.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 394.25,213.75 L 400.5,213.75 L 400.5,220.0 L 394.25,220.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 388.0,213.75 L 394.25,213.75 L 394.25,220.0 L 388.0,220.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 377.75,213.75 L 384.0,213.75 L 384.0,220.0 L 377.75,220.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 371.5,213.75 L 377.75,213.75 L 377.75,220.0 L 371.5,220.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 365.25,213.75 L 371.5,213.75 L 371.5,220.0 L 365.25,220.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 359.0,213.75 L 365.25,213.75 L 365.25,220.0 L 359.0,220.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 352.75,213.75 L 359.0,213.75 L 359.0,220.0 L 352.75,220.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 346.5,213.75 L 352.75,213.75 L 352.75,220.0 L 346.5,220.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 340.25,213.75 L 346.5,213.75 L 346.5,220.0 L 340.25,220.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 334.0,213.75 L 340.25,213.75 L 340.25,220.0 L 334.0,220.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 323.75,213.75 L 330.0,213.75 L 330.0,220.0 L 323.75,220.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 317.5,213.75 L 323.75,213.75 L 323.75,220.0 L 317.5,220.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 311.25,213.75 L 317.5,213.75 L 317.5,220.0 L 311.25,220.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 305.0,213.75 L 311.25,213.75 L 311.25,220.0 L 305.0,220.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 298.75,213.75 L 305.0,213.75 L 305.0,220.0 L 298.75,220.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 292.5,213.75 L 298.75,213.75 L 298.75,220.0 L 292.5,220.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 286.25,213.75 L 292.5,213.75 L 292.5,220.0 L 286.25,220.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 280.0,213.75 L 286.25,213.75 L 286.25,220.0 L 280.0,220.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 269.75,213.75 L 276.0,213.75 L 276.0,220.0 L 269.75,220.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 263.5,213.75 L 269.75,213.75 L 269.75,220.0 L 263.5,220.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 257.25,213.75 L 263.5,213.75 L 263.5,220.0 L 257.25,220.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 251.0,213.75 L 257.25,213.75 L 257.25,220.0 L 251.0,220.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 244.75,213.75 L 251.0,213.75 L 251.0,220.0 L 244.75,220.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 238.5,213.75 L 244.75,213.75 L 244.75,220.0 L 238.5,220.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 232.25,213.75 L 238.5,213.75 L 238.5,220.0 L 232.25,220.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 226.0,213.75 L 232.25,213.75 L 232.25,220.0 L 226.0,220.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 215.75,213.75 L 222.0,213.75 L 222.0,220.0 L 215.75,220.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 209.5,213.75 L 215.75,213.75 L 215.75,220.0 L 209.5,220.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 203.25,213.75 L 209.5,213.75 L 209.5,220.0 L 203.25,220.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 197.0,213.75 L 203.25,213.75 L 203.25,220.0 L 197.0,220.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 190.75,213.75 L 197.0,213.75 L 197.0,220.0 L 190.75,220.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 184.5,213.75 L 190.75,213.75 L 190.75,220.0 L 184.5,220.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 178.25,213.75 L 184.5,213.75 L 184.5,220.0 L 178.25,220.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 172.0,213.75 L 178.25,213.75 L 178.25,220.0 L 172.0,220.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 161.75,213.75 L 168.0,213.75 L 168.0,220.0 L 161.75,220.0 Z" fill="#000" stroke="#888" />
+ <path d="M 155.5,213.75 L 161.75,213.75 L 161.75,220.0 L 155.5,220.0 Z" fill="#000" stroke="#888" />
+ <path d="M 149.25,213.75 L 155.5,213.75 L 155.5,220.0 L 149.25,220.0 Z" fill="#000" stroke="#888" />
+ <path d="M 143.0,213.75 L 149.25,213.75 L 149.25,220.0 L 143.0,220.0 Z" fill="#000" stroke="#888" />
+ <path d="M 136.75,213.75 L 143.0,213.75 L 143.0,220.0 L 136.75,220.0 Z" fill="#000" stroke="#888" />
+ <path d="M 130.5,213.75 L 136.75,213.75 L 136.75,220.0 L 130.5,220.0 Z" fill="#000" stroke="#888" />
+ <path d="M 124.25,213.75 L 130.5,213.75 L 130.5,220.0 L 124.25,220.0 Z" fill="#000" stroke="#888" />
+ <path d="M 118.0,213.75 L 124.25,213.75 L 124.25,220.0 L 118.0,220.0 Z" fill="#000" stroke="#888" />
+ <path d="M 107.75,213.75 L 114.0,213.75 L 114.0,220.0 L 107.75,220.0 Z" fill="#000" stroke="#888" />
+ <path d="M 101.5,213.75 L 107.75,213.75 L 107.75,220.0 L 101.5,220.0 Z" fill="#000" stroke="#888" />
+ <path d="M 95.25,213.75 L 101.5,213.75 L 101.5,220.0 L 95.25,220.0 Z" fill="#000" stroke="#888" />
+ <path d="M 89.0,213.75 L 95.25,213.75 L 95.25,220.0 L 89.0,220.0 Z" fill="#000" stroke="#888" />
+ <path d="M 82.75,213.75 L 89.0,213.75 L 89.0,220.0 L 82.75,220.0 Z" fill="#000" stroke="#888" />
+ <path d="M 76.5,213.75 L 82.75,213.75 L 82.75,220.0 L 76.5,220.0 Z" fill="#000" stroke="#888" />
+ <path d="M 70.25,213.75 L 76.5,213.75 L 76.5,220.0 L 70.25,220.0 Z" fill="#000" stroke="#888" />
+ <path d="M 64.0,213.75 L 70.25,213.75 L 70.25,220.0 L 64.0,220.0 Z" fill="#000" stroke="#888" />
+ <path d="M 53.75,213.75 L 60.0,213.75 L 60.0,220.0 L 53.75,220.0 Z" fill="#000" stroke="#888" />
+ <path d="M 47.5,213.75 L 53.75,213.75 L 53.75,220.0 L 47.5,220.0 Z" fill="#000" stroke="#888" />
+ <path d="M 41.25,213.75 L 47.5,213.75 L 47.5,220.0 L 41.25,220.0 Z" fill="#000" stroke="#888" />
+ <path d="M 35.0,213.75 L 41.25,213.75 L 41.25,220.0 L 35.0,220.0 Z" fill="#000" stroke="#888" />
+ <path d="M 28.75,213.75 L 35.0,213.75 L 35.0,220.0 L 28.75,220.0 Z" fill="#000" stroke="#888" />
+ <path d="M 22.5,213.75 L 28.75,213.75 L 28.75,220.0 L 22.5,220.0 Z" fill="#000" stroke="#888" />
+ <path d="M 16.25,213.75 L 22.5,213.75 L 22.5,220.0 L 16.25,220.0 Z" fill="#000" stroke="#888" />
+ <path d="M 10.0,213.75 L 16.25,213.75 L 16.25,220.0 L 10.0,220.0 Z" fill="#000" stroke="#888" />
+ <text font-family="'Segoe UI', Helvetica, Arial, sans-serif" font-size="12" transform="translate(448.0,216.0)" text-anchor="start" dominant-baseline="central" paint-order="stroke" stroke-width="4" stroke-linejoin="round" stroke="white">active words bits</text>
+ <path d="M 187.625,110.0 L 193.875,110.0 L 193.875,115.0 L 47.5,208.75 L 47.5,213.75 L 10.0,213.75 L 10.0,208.75 L 187.625,115.0 Z" fill="#729fcf" stroke="none" />
+ <path d="M 193.875,110.0 L 200.125,110.0 L 200.125,115.0 L 89.0,208.75 L 89.0,213.75 L 47.5,213.75 L 47.5,208.75 L 193.875,115.0 Z" fill="#e9b96e" stroke="none" />
+ <path d="M 200.125,110.0 L 206.375,110.0 L 206.375,115.0 L 130.5,208.75 L 130.5,213.75 L 89.0,213.75 L 89.0,208.75 L 200.125,115.0 Z" fill="#729fcf" stroke="none" />
+ <path d="M 206.375,110.0 L 212.625,110.0 L 212.625,115.0 L 168.0,208.75 L 168.0,213.75 L 130.5,213.75 L 130.5,208.75 L 206.375,115.0 Z" fill="#e9b96e" stroke="none" />
+ <path d="M 212.625,110.0 L 218.875,110.0 L 218.875,115.0 L 209.5,208.75 L 209.5,213.75 L 172.0,213.75 L 172.0,208.75 L 212.625,115.0 Z" fill="#729fcf" stroke="none" />
+ <path d="M 218.875,110.0 L 225.125,110.0 L 225.125,115.0 L 251.0,208.75 L 251.0,213.75 L 209.5,213.75 L 209.5,208.75 L 218.875,115.0 Z" fill="#e9b96e" stroke="none" />
+ <path d="M 225.125,110.0 L 231.375,110.0 L 231.375,115.0 L 292.5,208.75 L 292.5,213.75 L 251.0,213.75 L 251.0,208.75 L 225.125,115.0 Z" fill="#729fcf" stroke="none" />
+ <path d="M 231.375,110.0 L 237.625,110.0 L 237.625,115.0 L 330.0,208.75 L 330.0,213.75 L 292.5,213.75 L 292.5,208.75 L 231.375,115.0 Z" fill="#e9b96e" stroke="none" />
+ <path d="M 241.625,110.0 L 247.875,110.0 L 247.875,115.0 L 371.5,208.75 L 371.5,213.75 L 334.0,213.75 L 334.0,208.75 L 241.625,115.0 Z" fill="#729fcf" stroke="none" />
+ <path d="M 247.875,110.0 L 254.125,110.0 L 254.125,115.0 L 413.0,208.75 L 413.0,213.75 L 371.5,213.75 L 371.5,208.75 L 247.875,115.0 Z" fill="#e9b96e" stroke="none" />
+ <path d="M 254.125,110.0 L 260.375,110.0 L 260.375,115.0 L 438.0,208.75 L 438.0,213.75 L 413.0,213.75 L 413.0,208.75 L 254.125,115.0 Z" fill="#729fcf" stroke="none" />
+ <rect x="181.2" y="172.0" width="85.60000000000002" height="16.0" rx="8" fill="#fff" stroke="#000" />
+ <text font-family="'Segoe UI', Helvetica, Arial, sans-serif" font-size="12" transform="translate(224.0,180.0)" text-anchor="middle" dominant-baseline="central">A*x in GF(2)⁸</text>
+ <path d="M 431.75,273.75 L 438.0,273.75 L 438.0,280.0 L 431.75,280.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 425.5,273.75 L 431.75,273.75 L 431.75,280.0 L 425.5,280.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 419.25,273.75 L 425.5,273.75 L 425.5,280.0 L 419.25,280.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 413.0,273.75 L 419.25,273.75 L 419.25,280.0 L 413.0,280.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 406.75,273.75 L 413.0,273.75 L 413.0,280.0 L 406.75,280.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 400.5,273.75 L 406.75,273.75 L 406.75,280.0 L 400.5,280.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 394.25,273.75 L 400.5,273.75 L 400.5,280.0 L 394.25,280.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 388.0,273.75 L 394.25,273.75 L 394.25,280.0 L 388.0,280.0 Z" fill="#000" stroke="#888" />
+ <path d="M 377.75,273.75 L 384.0,273.75 L 384.0,280.0 L 377.75,280.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 371.5,273.75 L 377.75,273.75 L 377.75,280.0 L 371.5,280.0 Z" fill="#000" stroke="#888" />
+ <path d="M 365.25,273.75 L 371.5,273.75 L 371.5,280.0 L 365.25,280.0 Z" fill="#000" stroke="#888" />
+ <path d="M 359.0,273.75 L 365.25,273.75 L 365.25,280.0 L 359.0,280.0 Z" fill="#000" stroke="#888" />
+ <path d="M 352.75,273.75 L 359.0,273.75 L 359.0,280.0 L 352.75,280.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 346.5,273.75 L 352.75,273.75 L 352.75,280.0 L 346.5,280.0 Z" fill="#000" stroke="#888" />
+ <path d="M 340.25,273.75 L 346.5,273.75 L 346.5,280.0 L 340.25,280.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 334.0,273.75 L 340.25,273.75 L 340.25,280.0 L 334.0,280.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 323.75,273.75 L 330.0,273.75 L 330.0,280.0 L 323.75,280.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 317.5,273.75 L 323.75,273.75 L 323.75,280.0 L 317.5,280.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 311.25,273.75 L 317.5,273.75 L 317.5,280.0 L 311.25,280.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 305.0,273.75 L 311.25,273.75 L 311.25,280.0 L 305.0,280.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 298.75,273.75 L 305.0,273.75 L 305.0,280.0 L 298.75,280.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 292.5,273.75 L 298.75,273.75 L 298.75,280.0 L 292.5,280.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 286.25,273.75 L 292.5,273.75 L 292.5,280.0 L 286.25,280.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 280.0,273.75 L 286.25,273.75 L 286.25,280.0 L 280.0,280.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 269.75,273.75 L 276.0,273.75 L 276.0,280.0 L 269.75,280.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 263.5,273.75 L 269.75,273.75 L 269.75,280.0 L 263.5,280.0 Z" fill="#000" stroke="#888" />
+ <path d="M 257.25,273.75 L 263.5,273.75 L 263.5,280.0 L 257.25,280.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 251.0,273.75 L 257.25,273.75 L 257.25,280.0 L 251.0,280.0 Z" fill="#000" stroke="#888" />
+ <path d="M 244.75,273.75 L 251.0,273.75 L 251.0,280.0 L 244.75,280.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 238.5,273.75 L 244.75,273.75 L 244.75,280.0 L 238.5,280.0 Z" fill="#000" stroke="#888" />
+ <path d="M 232.25,273.75 L 238.5,273.75 L 238.5,280.0 L 232.25,280.0 Z" fill="#000" stroke="#888" />
+ <path d="M 226.0,273.75 L 232.25,273.75 L 232.25,280.0 L 226.0,280.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 215.75,273.75 L 222.0,273.75 L 222.0,280.0 L 215.75,280.0 Z" fill="#000" stroke="#888" />
+ <path d="M 209.5,273.75 L 215.75,273.75 L 215.75,280.0 L 209.5,280.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 203.25,273.75 L 209.5,273.75 L 209.5,280.0 L 203.25,280.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 197.0,273.75 L 203.25,273.75 L 203.25,280.0 L 197.0,280.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 190.75,273.75 L 197.0,273.75 L 197.0,280.0 L 190.75,280.0 Z" fill="#000" stroke="#888" />
+ <path d="M 184.5,273.75 L 190.75,273.75 L 190.75,280.0 L 184.5,280.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 178.25,273.75 L 184.5,273.75 L 184.5,280.0 L 178.25,280.0 Z" fill="#000" stroke="#888" />
+ <path d="M 172.0,273.75 L 178.25,273.75 L 178.25,280.0 L 172.0,280.0 Z" fill="#000" stroke="#888" />
+ <path d="M 161.75,273.75 L 168.0,273.75 L 168.0,280.0 L 161.75,280.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 155.5,273.75 L 161.75,273.75 L 161.75,280.0 L 155.5,280.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 149.25,273.75 L 155.5,273.75 L 155.5,280.0 L 149.25,280.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 143.0,273.75 L 149.25,273.75 L 149.25,280.0 L 143.0,280.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 136.75,273.75 L 143.0,273.75 L 143.0,280.0 L 136.75,280.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 130.5,273.75 L 136.75,273.75 L 136.75,280.0 L 130.5,280.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 124.25,273.75 L 130.5,273.75 L 130.5,280.0 L 124.25,280.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 118.0,273.75 L 124.25,273.75 L 124.25,280.0 L 118.0,280.0 Z" fill="#000" stroke="#888" />
+ <path d="M 107.75,273.75 L 114.0,273.75 L 114.0,280.0 L 107.75,280.0 Z" fill="#000" stroke="#888" />
+ <path d="M 101.5,273.75 L 107.75,273.75 L 107.75,280.0 L 101.5,280.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 95.25,273.75 L 101.5,273.75 L 101.5,280.0 L 95.25,280.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 89.0,273.75 L 95.25,273.75 L 95.25,280.0 L 89.0,280.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 82.75,273.75 L 89.0,273.75 L 89.0,280.0 L 82.75,280.0 Z" fill="#000" stroke="#888" />
+ <path d="M 76.5,273.75 L 82.75,273.75 L 82.75,280.0 L 76.5,280.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 70.25,273.75 L 76.5,273.75 L 76.5,280.0 L 70.25,280.0 Z" fill="#000" stroke="#888" />
+ <path d="M 64.0,273.75 L 70.25,273.75 L 70.25,280.0 L 64.0,280.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 53.75,273.75 L 60.0,273.75 L 60.0,280.0 L 53.75,280.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 47.5,273.75 L 53.75,273.75 L 53.75,280.0 L 47.5,280.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 41.25,273.75 L 47.5,273.75 L 47.5,280.0 L 41.25,280.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 35.0,273.75 L 41.25,273.75 L 41.25,280.0 L 35.0,280.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 28.75,273.75 L 35.0,273.75 L 35.0,280.0 L 28.75,280.0 Z" fill="#000" stroke="#888" />
+ <path d="M 22.5,273.75 L 28.75,273.75 L 28.75,280.0 L 22.5,280.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 16.25,273.75 L 22.5,273.75 L 22.5,280.0 L 16.25,280.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 10.0,273.75 L 16.25,273.75 L 16.25,280.0 L 10.0,280.0 Z" fill="#000" stroke="#888" />
+ <path d="M 10.0,270.75 L 438.0,270.75" fill="none" stroke="#e9b96e" stroke-width="1.5" />
+ <path d="M 116.0,250.0 L 116.0,250.0 L 116.0,250.0 L 116.0,270.75" fill="none" stroke="#e9b96e" stroke-width="1.5" />
+ <rect x="43.5" y="242.0" width="145.0" height="16.0" rx="8" fill="#fff" stroke="#000" />
+ <text font-family="'Segoe UI', Helvetica, Arial, sans-serif" font-size="12" transform="translate(116.0,250.0)" text-anchor="middle" dominant-baseline="central">load</text>
+ <text font-family="'Segoe UI', Helvetica, Arial, sans-serif" font-size="12" transform="translate(448.0,276.0)" text-anchor="start" dominant-baseline="central" paint-order="stroke" stroke-width="4" stroke-linejoin="round" stroke="white">pointer/scalar bits</text>
+ <path d="M 431.75,333.75 L 438.0,333.75 L 438.0,340.0 L 431.75,340.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 425.5,333.75 L 431.75,333.75 L 431.75,340.0 L 425.5,340.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 419.25,333.75 L 425.5,333.75 L 425.5,340.0 L 419.25,340.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 413.0,333.75 L 419.25,333.75 L 419.25,340.0 L 413.0,340.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 406.75,333.75 L 413.0,333.75 L 413.0,340.0 L 406.75,340.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 400.5,333.75 L 406.75,333.75 L 406.75,340.0 L 400.5,340.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 394.25,333.75 L 400.5,333.75 L 400.5,340.0 L 394.25,340.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 388.0,333.75 L 394.25,333.75 L 394.25,340.0 L 388.0,340.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 377.75,333.75 L 384.0,333.75 L 384.0,340.0 L 377.75,340.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 371.5,333.75 L 377.75,333.75 L 377.75,340.0 L 371.5,340.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 365.25,333.75 L 371.5,333.75 L 371.5,340.0 L 365.25,340.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 359.0,333.75 L 365.25,333.75 L 365.25,340.0 L 359.0,340.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 352.75,333.75 L 359.0,333.75 L 359.0,340.0 L 352.75,340.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 346.5,333.75 L 352.75,333.75 L 352.75,340.0 L 346.5,340.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 340.25,333.75 L 346.5,333.75 L 346.5,340.0 L 340.25,340.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 334.0,333.75 L 340.25,333.75 L 340.25,340.0 L 334.0,340.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 323.75,333.75 L 330.0,333.75 L 330.0,340.0 L 323.75,340.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 317.5,333.75 L 323.75,333.75 L 323.75,340.0 L 317.5,340.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 311.25,333.75 L 317.5,333.75 L 317.5,340.0 L 311.25,340.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 305.0,333.75 L 311.25,333.75 L 311.25,340.0 L 305.0,340.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 298.75,333.75 L 305.0,333.75 L 305.0,340.0 L 298.75,340.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 292.5,333.75 L 298.75,333.75 L 298.75,340.0 L 292.5,340.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 286.25,333.75 L 292.5,333.75 L 292.5,340.0 L 286.25,340.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 280.0,333.75 L 286.25,333.75 L 286.25,340.0 L 280.0,340.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 269.75,333.75 L 276.0,333.75 L 276.0,340.0 L 269.75,340.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 263.5,333.75 L 269.75,333.75 L 269.75,340.0 L 263.5,340.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 257.25,333.75 L 263.5,333.75 L 263.5,340.0 L 257.25,340.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 251.0,333.75 L 257.25,333.75 L 257.25,340.0 L 251.0,340.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 244.75,333.75 L 251.0,333.75 L 251.0,340.0 L 244.75,340.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 238.5,333.75 L 244.75,333.75 L 244.75,340.0 L 238.5,340.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 232.25,333.75 L 238.5,333.75 L 238.5,340.0 L 232.25,340.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 226.0,333.75 L 232.25,333.75 L 232.25,340.0 L 226.0,340.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 215.75,333.75 L 222.0,333.75 L 222.0,340.0 L 215.75,340.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 209.5,333.75 L 215.75,333.75 L 215.75,340.0 L 209.5,340.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 203.25,333.75 L 209.5,333.75 L 209.5,340.0 L 203.25,340.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 197.0,333.75 L 203.25,333.75 L 203.25,340.0 L 197.0,340.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 190.75,333.75 L 197.0,333.75 L 197.0,340.0 L 190.75,340.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 184.5,333.75 L 190.75,333.75 L 190.75,340.0 L 184.5,340.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 178.25,333.75 L 184.5,333.75 L 184.5,340.0 L 178.25,340.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 172.0,333.75 L 178.25,333.75 L 178.25,340.0 L 172.0,340.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 161.75,333.75 L 168.0,333.75 L 168.0,340.0 L 161.75,340.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 155.5,333.75 L 161.75,333.75 L 161.75,340.0 L 155.5,340.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 149.25,333.75 L 155.5,333.75 L 155.5,340.0 L 149.25,340.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 143.0,333.75 L 149.25,333.75 L 149.25,340.0 L 143.0,340.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 136.75,333.75 L 143.0,333.75 L 143.0,340.0 L 136.75,340.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 130.5,333.75 L 136.75,333.75 L 136.75,340.0 L 130.5,340.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 124.25,333.75 L 130.5,333.75 L 130.5,340.0 L 124.25,340.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 118.0,333.75 L 124.25,333.75 L 124.25,340.0 L 118.0,340.0 Z" fill="#000" stroke="#888" />
+ <path d="M 107.75,333.75 L 114.0,333.75 L 114.0,340.0 L 107.75,340.0 Z" fill="#000" stroke="#888" />
+ <path d="M 101.5,333.75 L 107.75,333.75 L 107.75,340.0 L 101.5,340.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 95.25,333.75 L 101.5,333.75 L 101.5,340.0 L 95.25,340.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 89.0,333.75 L 95.25,333.75 L 95.25,340.0 L 89.0,340.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 82.75,333.75 L 89.0,333.75 L 89.0,340.0 L 82.75,340.0 Z" fill="#000" stroke="#888" />
+ <path d="M 76.5,333.75 L 82.75,333.75 L 82.75,340.0 L 76.5,340.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 70.25,333.75 L 76.5,333.75 L 76.5,340.0 L 70.25,340.0 Z" fill="#000" stroke="#888" />
+ <path d="M 64.0,333.75 L 70.25,333.75 L 70.25,340.0 L 64.0,340.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 53.75,333.75 L 60.0,333.75 L 60.0,340.0 L 53.75,340.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 47.5,333.75 L 53.75,333.75 L 53.75,340.0 L 47.5,340.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 41.25,333.75 L 47.5,333.75 L 47.5,340.0 L 41.25,340.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 35.0,333.75 L 41.25,333.75 L 41.25,340.0 L 35.0,340.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 28.75,333.75 L 35.0,333.75 L 35.0,340.0 L 28.75,340.0 Z" fill="#000" stroke="#888" />
+ <path d="M 22.5,333.75 L 28.75,333.75 L 28.75,340.0 L 22.5,340.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 16.25,333.75 L 22.5,333.75 L 22.5,340.0 L 16.25,340.0 Z" fill="#fff" stroke="#888" />
+ <path d="M 10.0,333.75 L 16.25,333.75 L 16.25,340.0 L 10.0,340.0 Z" fill="#000" stroke="#888" />
+ <path d="M 10.0,223.0 L 438.0,223.0" fill="none" stroke="#729fcf" stroke-width="1.5" />
+ <path d="M 10.0,330.75 L 438.0,330.75" fill="none" stroke="#729fcf" stroke-width="1.5" />
+ <path d="M 224.0,223.0 L 224.0,306.875 L 224.0,306.875 L 224.0,330.75" fill="none" stroke="#729fcf" stroke-width="1.5" />
+ <path d="M 10.0,283.0 L 438.0,283.0" fill="none" stroke="#e9b96e" stroke-width="1.5" />
+ <path d="M 204.0,283.0 L 204.0,306.875 L 224.0,306.875" fill="none" stroke="#e9b96e" stroke-width="1.5" />
+ <circle cx="224.0" cy="306.875" r="10.0" fill="#fff" stroke="#000" />
+ <text font-family="'Segoe UI', Helvetica, Arial, sans-serif" font-size="12" transform="translate(224.0,306.875) skewY(0.0)" text-anchor="middle" dominant-baseline="central">&amp;</text>
+ <text font-family="'Segoe UI', Helvetica, Arial, sans-serif" font-size="12" transform="translate(448.0,336.0)" text-anchor="start" dominant-baseline="central" paint-order="stroke" stroke-width="4" stroke-linejoin="round" stroke="white">active pointer bits</text>
+ <path d="M 10.0,413.75 L 60.0,413.75 L 60.0,420.0 L 10.0,420.0 Z" fill="rgb(49,178,88)" stroke="#888" />
+ <path d="M 64.0,413.75 L 114.0,413.75 L 114.0,420.0 L 64.0,420.0 Z" fill="rgb(142,146,244)" stroke="#888" />
+ <path d="M 118.0,413.75 L 168.0,413.75 L 168.0,420.0 L 118.0,420.0 Z" fill="rgb(246,112,136)" stroke="#888" />
+ <path d="M 172.0,413.75 L 222.0,413.75 L 222.0,420.0 L 172.0,420.0 Z" fill="rgb(245,102,198)" stroke="#888" />
+ <path d="M 226.0,413.75 L 276.0,413.75 L 276.0,420.0 L 226.0,420.0 Z" fill="rgb(225,133,49)" stroke="#888" />
+ <path d="M 280.0,413.75 L 330.0,413.75 L 330.0,420.0 L 280.0,420.0 Z" fill="rgb(57,166,214)" stroke="#888" />
+ <path d="M 334.0,413.75 L 384.0,413.75 L 384.0,420.0 L 334.0,420.0 Z" fill="rgb(218,112,244)" stroke="#888" />
+ <path d="M 388.0,413.75 L 438.0,413.75 L 438.0,420.0 L 388.0,420.0 Z" fill="rgb(54,171,178)" stroke="#888" />
+ <path d="M 10.0,410.75 L 438.0,410.75" fill="none" stroke="#e9b96e" stroke-width="1.5" />
+ <path d="M 116.0,390.0 L 116.0,390.0 L 116.0,390.0 L 116.0,410.75" fill="none" stroke="#e9b96e" stroke-width="1.5" />
+ <rect x="43.5" y="382.0" width="145.0" height="16.0" rx="8" fill="#fff" stroke="#000" />
+ <text font-family="'Segoe UI', Helvetica, Arial, sans-serif" font-size="12" transform="translate(116.0,390.0)" text-anchor="middle" dominant-baseline="central">load 64 bytes</text>
+ <text font-family="'Segoe UI', Helvetica, Arial, sans-serif" font-size="12" transform="translate(448.0,416.0)" text-anchor="start" dominant-baseline="central" paint-order="stroke" stroke-width="4" stroke-linejoin="round" stroke="white">page memory</text>
+ <path d="M 10.0,493.75 L 60.0,493.75 L 60.0,500.0 L 10.0,500.0 Z" fill="rgb(49,178,88)" stroke="#888" />
+ <path d="M 64.0,493.75 L 114.0,493.75 L 114.0,500.0 L 64.0,500.0 Z" fill="rgb(245,102,198)" stroke="#888" />
+ <text font-family="'Segoe UI', Helvetica, Arial, sans-serif" font-size="12" transform="translate(448.0,496.0)" text-anchor="start" dominant-baseline="central" paint-order="stroke" stroke-width="4" stroke-linejoin="round" stroke="white">new pointers</text>
+ <path d="M 35.0,420.0 L 35.0,474.875 L 35.0,493.75 L 35.0,496.75" fill="none" stroke="rgb(49,178,88)" stroke-width="3" />
+ <path d="M 89.0,420.0 L 89.0,474.875" fill="none" stroke="rgb(142,146,244)" stroke-width="3" />
+ <path d="M 143.0,420.0 L 143.0,474.875" fill="none" stroke="rgb(246,112,136)" stroke-width="3" />
+ <path d="M 197.0,420.0 L 197.0,474.875 L 89.0,493.75 L 89.0,496.75" fill="none" stroke="rgb(245,102,198)" stroke-width="3" />
+ <path d="M 251.0,420.0 L 251.0,474.875" fill="none" stroke="rgb(225,133,49)" stroke-width="3" />
+ <path d="M 305.0,420.0 L 305.0,474.875" fill="none" stroke="rgb(57,166,214)" stroke-width="3" />
+ <path d="M 359.0,420.0 L 359.0,474.875" fill="none" stroke="rgb(218,112,244)" stroke-width="3" />
+ <path d="M 413.0,420.0 L 413.0,474.875" fill="none" stroke="rgb(54,171,178)" stroke-width="3" />
+ <rect x="10.0" y="458.875" width="428.0" height="16.0" rx="8" fill="#fff" stroke="#000" />
+ <text font-family="'Segoe UI', Helvetica, Arial, sans-serif" font-size="12" transform="translate(224.0,466.875)" text-anchor="middle" dominant-baseline="central">compress</text>
+ <path d="M 384.5,437.625 L 438.0,437.625 L 438.0,443.875 L 384.5,443.875 Z" fill="#fff" stroke="#888" />
+ <path d="M 331.0,437.625 L 384.5,437.625 L 384.5,443.875 L 331.0,443.875 Z" fill="#fff" stroke="#888" />
+ <path d="M 277.5,437.625 L 331.0,437.625 L 331.0,443.875 L 277.5,443.875 Z" fill="#fff" stroke="#888" />
+ <path d="M 224.0,437.625 L 277.5,437.625 L 277.5,443.875 L 224.0,443.875 Z" fill="#fff" stroke="#888" />
+ <path d="M 170.5,437.625 L 224.0,437.625 L 224.0,443.875 L 170.5,443.875 Z" fill="#000" stroke="#888" />
+ <path d="M 117.0,437.625 L 170.5,437.625 L 170.5,443.875 L 117.0,443.875 Z" fill="#fff" stroke="#888" />
+ <path d="M 63.5,437.625 L 117.0,437.625 L 117.0,443.875 L 63.5,443.875 Z" fill="#fff" stroke="#888" />
+ <path d="M 10.0,437.625 L 63.5,437.625 L 63.5,443.875 L 10.0,443.875 Z" fill="#000" stroke="#888" />
+ <text font-family="'Segoe UI', Helvetica, Arial, sans-serif" font-size="12" transform="translate(448.0,439.875)" text-anchor="start" dominant-baseline="central" paint-order="stroke" stroke-width="4" stroke-linejoin="round" stroke="white">active pointer mask</text>
+ <path d="M 10.0,343.0 L 60.0,343.0" fill="none" stroke="#729fcf" stroke-width="1.5" />
+ <path d="M 10.0,434.625 L 438.0,434.625" fill="none" stroke="#729fcf" stroke-width="1.5" />
+ <path d="M 35.0,343.0 L 35.0,360.0 L 224.0,360.0 L 224.0,434.625" fill="none" stroke="#729fcf" stroke-width="1.5" />
+ <rect x="189.0" y="352.0" width="70.0" height="16.0" rx="8" fill="#fff" stroke="#000" />
+ <text font-family="'Segoe UI', Helvetica, Arial, sans-serif" font-size="12" transform="translate(224.0,360.0)" text-anchor="middle" dominant-baseline="central">load mask</text>
+ <path d="M 10.0,543.75 L 60.0,543.75 L 60.0,550.0 L 10.0,550.0 Z" fill="rgb(52,174,148)" stroke="#888" opacity="0.5" />
+ <path d="M 64.0,543.75 L 114.0,543.75 L 114.0,550.0 L 64.0,550.0 Z" fill="rgb(138,166,49)" stroke="#888" opacity="0.5" />
+ <path d="M 118.0,543.75 L 168.0,543.75 L 168.0,550.0 L 118.0,550.0 Z" fill="rgb(181,154,49)" stroke="#888" opacity="0.5" />
+ <path d="M 172.0,543.75 L 222.0,543.75 L 222.0,550.0 L 172.0,550.0 Z" fill="rgb(49,178,88)" stroke="#888" />
+ <path d="M 226.0,543.75 L 276.0,543.75 L 276.0,550.0 L 226.0,550.0 Z" fill="rgb(245,102,198)" stroke="#888" />
+ <text font-family="'Segoe UI', Helvetica, Arial, sans-serif" font-size="12" transform="translate(448.0,546.0)" text-anchor="start" dominant-baseline="central" paint-order="stroke" stroke-width="4" stroke-linejoin="round" stroke="white">output buffer</text>
+ <path d="M 10.0,503.0 L 114.0,503.0" fill="none" stroke="#729fcf" stroke-width="1.5" />
+ <path d="M 172.0,540.75 L 276.0,540.75" fill="none" stroke="#729fcf" stroke-width="1.5" />
+ <path d="M 62.0,503.0 L 62.0,520.0 L 224.0,520.0 L 224.0,540.75" fill="none" stroke="#729fcf" stroke-width="1.5" />
+ <rect x="151.5" y="512.0" width="145.0" height="16.0" rx="8" fill="#fff" stroke="#000" />
+ <text font-family="'Segoe UI', Helvetica, Arial, sans-serif" font-size="12" transform="translate(224.0,520.0)" text-anchor="middle" dominant-baseline="central">append</text>
+ <path d="M 578.0,366.0 L 588.0,366.0 L 588.0,544.0 L 578.0,544.0" fill="none" stroke="#729fcf" stroke-width="3.0" />
+ <text font-family="'Segoe UI', Helvetica, Arial, sans-serif" font-size="12" transform="translate(603.0,459.0)" text-anchor="start" dominant-baseline="central" paint-order="stroke" stroke-width="4" stroke-linejoin="round" stroke="white">×128</text>
+</svg>
diff --git a/_content/blog/greenteagc/carousel.js b/_content/blog/greenteagc/carousel.js
new file mode 100644
index 00000000..44b0ec6e
--- /dev/null
+++ b/_content/blog/greenteagc/carousel.js
@@ -0,0 +1,37 @@
+document.addEventListener('DOMContentLoaded', function() {
+ setupFor("marksweep");
+ setupFor("greentea");
+});
+
+function setupFor(id) {
+ const next = document.getElementById(id+"-next");
+ const prev = document.getElementById(id+"-prev");
+ const caro = document.getElementById(id);
+ next.addEventListener('click', scrollRight(next, prev, caro));
+ prev.addEventListener('click', scrollLeft(next, prev, caro));
+ prev.disabled = true;
+ next.disabled = false;
+ prev.hidden = false;
+ next.hidden = false;
+ caro.classList.add('hide-overflow');
+}
+
+function scrollRight(n, p, c) {
+ return () => {
+ c.scrollLeft += c.getBoundingClientRect().width;
+ p.disabled = false;
+ if (c.scrollLeft === c.scrollWidth-c.clientWidth) {
+ n.disabled = true;
+ }
+ };
+}
+
+function scrollLeft(n, p, c) {
+ return () => {
+ c.scrollLeft -= c.getBoundingClientRect().width;
+ n.disabled = false;
+ if (c.scrollLeft === 0) {
+ p.disabled = true;
+ }
+ };
+}
diff --git a/_content/blog/greenteagc/graphflood-path.png b/_content/blog/greenteagc/graphflood-path.png
new file mode 100644
index 00000000..24600972
--- /dev/null
+++ b/_content/blog/greenteagc/graphflood-path.png
Binary files differ
diff --git a/_content/blog/greenteagc/graphflood-path2.png b/_content/blog/greenteagc/graphflood-path2.png
new file mode 100644
index 00000000..205af00e
--- /dev/null
+++ b/_content/blog/greenteagc/graphflood-path2.png
Binary files differ
diff --git a/_content/blog/greenteagc/greentea-060.png b/_content/blog/greenteagc/greentea-060.png
new file mode 100644
index 00000000..61e46444
--- /dev/null
+++ b/_content/blog/greenteagc/greentea-060.png
Binary files differ
diff --git a/_content/blog/greenteagc/greentea-062.png b/_content/blog/greenteagc/greentea-062.png
new file mode 100644
index 00000000..33879780
--- /dev/null
+++ b/_content/blog/greenteagc/greentea-062.png
Binary files differ
diff --git a/_content/blog/greenteagc/greentea-063.png b/_content/blog/greenteagc/greentea-063.png
new file mode 100644
index 00000000..ce5c2055
--- /dev/null
+++ b/_content/blog/greenteagc/greentea-063.png
Binary files differ
diff --git a/_content/blog/greenteagc/greentea-064.png b/_content/blog/greenteagc/greentea-064.png
new file mode 100644
index 00000000..a837da2a
--- /dev/null
+++ b/_content/blog/greenteagc/greentea-064.png
Binary files differ
diff --git a/_content/blog/greenteagc/greentea-066.png b/_content/blog/greenteagc/greentea-066.png
new file mode 100644
index 00000000..41bfc2d6
--- /dev/null
+++ b/_content/blog/greenteagc/greentea-066.png
Binary files differ
diff --git a/_content/blog/greenteagc/greentea-069.png b/_content/blog/greenteagc/greentea-069.png
new file mode 100644
index 00000000..9a202dfb
--- /dev/null
+++ b/_content/blog/greenteagc/greentea-069.png
Binary files differ
diff --git a/_content/blog/greenteagc/greentea-071.png b/_content/blog/greenteagc/greentea-071.png
new file mode 100644
index 00000000..4aa12e55
--- /dev/null
+++ b/_content/blog/greenteagc/greentea-071.png
Binary files differ
diff --git a/_content/blog/greenteagc/greentea-072.png b/_content/blog/greenteagc/greentea-072.png
new file mode 100644
index 00000000..e8418d54
--- /dev/null
+++ b/_content/blog/greenteagc/greentea-072.png
Binary files differ
diff --git a/_content/blog/greenteagc/greentea-074.png b/_content/blog/greenteagc/greentea-074.png
new file mode 100644
index 00000000..66f477f8
--- /dev/null
+++ b/_content/blog/greenteagc/greentea-074.png
Binary files differ
diff --git a/_content/blog/greenteagc/greentea-075.png b/_content/blog/greenteagc/greentea-075.png
new file mode 100644
index 00000000..98e71676
--- /dev/null
+++ b/_content/blog/greenteagc/greentea-075.png
Binary files differ
diff --git a/_content/blog/greenteagc/greentea-076.png b/_content/blog/greenteagc/greentea-076.png
new file mode 100644
index 00000000..778fa7ad
--- /dev/null
+++ b/_content/blog/greenteagc/greentea-076.png
Binary files differ
diff --git a/_content/blog/greenteagc/greentea-078.png b/_content/blog/greenteagc/greentea-078.png
new file mode 100644
index 00000000..aced289a
--- /dev/null
+++ b/_content/blog/greenteagc/greentea-078.png
Binary files differ
diff --git a/_content/blog/greenteagc/greentea-079.png b/_content/blog/greenteagc/greentea-079.png
new file mode 100644
index 00000000..2b8f8149
--- /dev/null
+++ b/_content/blog/greenteagc/greentea-079.png
Binary files differ
diff --git a/_content/blog/greenteagc/greentea-081.png b/_content/blog/greenteagc/greentea-081.png
new file mode 100644
index 00000000..68473980
--- /dev/null
+++ b/_content/blog/greenteagc/greentea-081.png
Binary files differ
diff --git a/_content/blog/greenteagc/greentea-082.png b/_content/blog/greenteagc/greentea-082.png
new file mode 100644
index 00000000..f034cfa1
--- /dev/null
+++ b/_content/blog/greenteagc/greentea-082.png
Binary files differ
diff --git a/_content/blog/greenteagc/greentea-083.png b/_content/blog/greenteagc/greentea-083.png
new file mode 100644
index 00000000..ab09b844
--- /dev/null
+++ b/_content/blog/greenteagc/greentea-083.png
Binary files differ
diff --git a/_content/blog/greenteagc/greentea-084.png b/_content/blog/greenteagc/greentea-084.png
new file mode 100644
index 00000000..15074634
--- /dev/null
+++ b/_content/blog/greenteagc/greentea-084.png
Binary files differ
diff --git a/_content/blog/greenteagc/greentea-085.png b/_content/blog/greenteagc/greentea-085.png
new file mode 100644
index 00000000..7df141c3
--- /dev/null
+++ b/_content/blog/greenteagc/greentea-085.png
Binary files differ
diff --git a/_content/blog/greenteagc/greentea-086.png b/_content/blog/greenteagc/greentea-086.png
new file mode 100644
index 00000000..e53d2276
--- /dev/null
+++ b/_content/blog/greenteagc/greentea-086.png
Binary files differ
diff --git a/_content/blog/greenteagc/greentea-087.png b/_content/blog/greenteagc/greentea-087.png
new file mode 100644
index 00000000..38d86e16
--- /dev/null
+++ b/_content/blog/greenteagc/greentea-087.png
Binary files differ
diff --git a/_content/blog/greenteagc/greentea-088.png b/_content/blog/greenteagc/greentea-088.png
new file mode 100644
index 00000000..a8a49716
--- /dev/null
+++ b/_content/blog/greenteagc/greentea-088.png
Binary files differ
diff --git a/_content/blog/greenteagc/greentea-089.png b/_content/blog/greenteagc/greentea-089.png
new file mode 100644
index 00000000..3e8dc0a9
--- /dev/null
+++ b/_content/blog/greenteagc/greentea-089.png
Binary files differ
diff --git a/_content/blog/greenteagc/greentea-090.png b/_content/blog/greenteagc/greentea-090.png
new file mode 100644
index 00000000..99ee6b6b
--- /dev/null
+++ b/_content/blog/greenteagc/greentea-090.png
Binary files differ
diff --git a/_content/blog/greenteagc/greentea-091.png b/_content/blog/greenteagc/greentea-091.png
new file mode 100644
index 00000000..3dfe51ec
--- /dev/null
+++ b/_content/blog/greenteagc/greentea-091.png
Binary files differ
diff --git a/_content/blog/greenteagc/greentea-092.png b/_content/blog/greenteagc/greentea-092.png
new file mode 100644
index 00000000..0f0a8c7d
--- /dev/null
+++ b/_content/blog/greenteagc/greentea-092.png
Binary files differ
diff --git a/_content/blog/greenteagc/greentea-093.png b/_content/blog/greenteagc/greentea-093.png
new file mode 100644
index 00000000..927150c6
--- /dev/null
+++ b/_content/blog/greenteagc/greentea-093.png
Binary files differ
diff --git a/_content/blog/greenteagc/greentea-094.png b/_content/blog/greenteagc/greentea-094.png
new file mode 100644
index 00000000..d62ba102
--- /dev/null
+++ b/_content/blog/greenteagc/greentea-094.png
Binary files differ
diff --git a/_content/blog/greenteagc/greentea-095.png b/_content/blog/greenteagc/greentea-095.png
new file mode 100644
index 00000000..8d0849c2
--- /dev/null
+++ b/_content/blog/greenteagc/greentea-095.png
Binary files differ
diff --git a/_content/blog/greenteagc/greentea-096.png b/_content/blog/greenteagc/greentea-096.png
new file mode 100644
index 00000000..2491334c
--- /dev/null
+++ b/_content/blog/greenteagc/greentea-096.png
Binary files differ
diff --git a/_content/blog/greenteagc/greentea-097.png b/_content/blog/greenteagc/greentea-097.png
new file mode 100644
index 00000000..3caa48f9
--- /dev/null
+++ b/_content/blog/greenteagc/greentea-097.png
Binary files differ
diff --git a/_content/blog/greenteagc/greentea-098.png b/_content/blog/greenteagc/greentea-098.png
new file mode 100644
index 00000000..46d1390e
--- /dev/null
+++ b/_content/blog/greenteagc/greentea-098.png
Binary files differ
diff --git a/_content/blog/greenteagc/greentea-099.png b/_content/blog/greenteagc/greentea-099.png
new file mode 100644
index 00000000..41330275
--- /dev/null
+++ b/_content/blog/greenteagc/greentea-099.png
Binary files differ
diff --git a/_content/blog/greenteagc/greentea-100.png b/_content/blog/greenteagc/greentea-100.png
new file mode 100644
index 00000000..4a9d16bd
--- /dev/null
+++ b/_content/blog/greenteagc/greentea-100.png
Binary files differ
diff --git a/_content/blog/greenteagc/greentea-101.png b/_content/blog/greenteagc/greentea-101.png
new file mode 100644
index 00000000..cdbbe53c
--- /dev/null
+++ b/_content/blog/greenteagc/greentea-101.png
Binary files differ
diff --git a/_content/blog/greenteagc/greentea-102.png b/_content/blog/greenteagc/greentea-102.png
new file mode 100644
index 00000000..bcffd52d
--- /dev/null
+++ b/_content/blog/greenteagc/greentea-102.png
Binary files differ
diff --git a/_content/blog/greenteagc/greentea-path.png b/_content/blog/greenteagc/greentea-path.png
new file mode 100644
index 00000000..9e5e079b
--- /dev/null
+++ b/_content/blog/greenteagc/greentea-path.png
Binary files differ
diff --git a/_content/blog/greenteagc/marksweep-007.png b/_content/blog/greenteagc/marksweep-007.png
new file mode 100644
index 00000000..a995d0a0
--- /dev/null
+++ b/_content/blog/greenteagc/marksweep-007.png
Binary files differ
diff --git a/_content/blog/greenteagc/marksweep-008.png b/_content/blog/greenteagc/marksweep-008.png
new file mode 100644
index 00000000..60ad3e65
--- /dev/null
+++ b/_content/blog/greenteagc/marksweep-008.png
Binary files differ
diff --git a/_content/blog/greenteagc/marksweep-009.png b/_content/blog/greenteagc/marksweep-009.png
new file mode 100644
index 00000000..ab3d1682
--- /dev/null
+++ b/_content/blog/greenteagc/marksweep-009.png
Binary files differ
diff --git a/_content/blog/greenteagc/marksweep-010.png b/_content/blog/greenteagc/marksweep-010.png
new file mode 100644
index 00000000..c9deebd6
--- /dev/null
+++ b/_content/blog/greenteagc/marksweep-010.png
Binary files differ
diff --git a/_content/blog/greenteagc/marksweep-011.png b/_content/blog/greenteagc/marksweep-011.png
new file mode 100644
index 00000000..f064cd27
--- /dev/null
+++ b/_content/blog/greenteagc/marksweep-011.png
Binary files differ
diff --git a/_content/blog/greenteagc/marksweep-012.png b/_content/blog/greenteagc/marksweep-012.png
new file mode 100644
index 00000000..9e11988a
--- /dev/null
+++ b/_content/blog/greenteagc/marksweep-012.png
Binary files differ
diff --git a/_content/blog/greenteagc/marksweep-013.png b/_content/blog/greenteagc/marksweep-013.png
new file mode 100644
index 00000000..b863f6b4
--- /dev/null
+++ b/_content/blog/greenteagc/marksweep-013.png
Binary files differ
diff --git a/_content/blog/greenteagc/marksweep-014.png b/_content/blog/greenteagc/marksweep-014.png
new file mode 100644
index 00000000..6c4dcfab
--- /dev/null
+++ b/_content/blog/greenteagc/marksweep-014.png
Binary files differ
diff --git a/_content/blog/greenteagc/marksweep-015.png b/_content/blog/greenteagc/marksweep-015.png
new file mode 100644
index 00000000..689cded5
--- /dev/null
+++ b/_content/blog/greenteagc/marksweep-015.png
Binary files differ
diff --git a/_content/blog/greenteagc/marksweep-016.png b/_content/blog/greenteagc/marksweep-016.png
new file mode 100644
index 00000000..c665077b
--- /dev/null
+++ b/_content/blog/greenteagc/marksweep-016.png
Binary files differ
diff --git a/_content/blog/greenteagc/marksweep-017.png b/_content/blog/greenteagc/marksweep-017.png
new file mode 100644
index 00000000..c674632e
--- /dev/null
+++ b/_content/blog/greenteagc/marksweep-017.png
Binary files differ
diff --git a/_content/blog/greenteagc/marksweep-018.png b/_content/blog/greenteagc/marksweep-018.png
new file mode 100644
index 00000000..65b5bd08
--- /dev/null
+++ b/_content/blog/greenteagc/marksweep-018.png
Binary files differ
diff --git a/_content/blog/greenteagc/marksweep-019.png b/_content/blog/greenteagc/marksweep-019.png
new file mode 100644
index 00000000..487ea093
--- /dev/null
+++ b/_content/blog/greenteagc/marksweep-019.png
Binary files differ
diff --git a/_content/blog/greenteagc/marksweep-020.png b/_content/blog/greenteagc/marksweep-020.png
new file mode 100644
index 00000000..79f7011a
--- /dev/null
+++ b/_content/blog/greenteagc/marksweep-020.png
Binary files differ
diff --git a/_content/blog/greenteagc/marksweep-021.png b/_content/blog/greenteagc/marksweep-021.png
new file mode 100644
index 00000000..954efb3d
--- /dev/null
+++ b/_content/blog/greenteagc/marksweep-021.png
Binary files differ
diff --git a/_content/blog/greenteagc/marksweep-022.png b/_content/blog/greenteagc/marksweep-022.png
new file mode 100644
index 00000000..44e71669
--- /dev/null
+++ b/_content/blog/greenteagc/marksweep-022.png
Binary files differ
diff --git a/_content/blog/greenteagc/marksweep-023.png b/_content/blog/greenteagc/marksweep-023.png
new file mode 100644
index 00000000..c6cd70ab
--- /dev/null
+++ b/_content/blog/greenteagc/marksweep-023.png
Binary files differ
diff --git a/_content/blog/greenteagc/marksweep-024.png b/_content/blog/greenteagc/marksweep-024.png
new file mode 100644
index 00000000..e9e155df
--- /dev/null
+++ b/_content/blog/greenteagc/marksweep-024.png
Binary files differ
diff --git a/_content/blog/greenteagc/marksweep-025.png b/_content/blog/greenteagc/marksweep-025.png
new file mode 100644
index 00000000..f9ce06ac
--- /dev/null
+++ b/_content/blog/greenteagc/marksweep-025.png
Binary files differ
diff --git a/_content/blog/greenteagc/marksweep-026.png b/_content/blog/greenteagc/marksweep-026.png
new file mode 100644
index 00000000..2f3d3dca
--- /dev/null
+++ b/_content/blog/greenteagc/marksweep-026.png
Binary files differ
diff --git a/_content/blog/greenteagc/marksweep-027.png b/_content/blog/greenteagc/marksweep-027.png
new file mode 100644
index 00000000..58b8f65a
--- /dev/null
+++ b/_content/blog/greenteagc/marksweep-027.png
Binary files differ
diff --git a/_content/blog/greenteagc/marksweep-028.png b/_content/blog/greenteagc/marksweep-028.png
new file mode 100644
index 00000000..bd2a654c
--- /dev/null
+++ b/_content/blog/greenteagc/marksweep-028.png
Binary files differ
diff --git a/_content/blog/greenteagc/marksweep-029.png b/_content/blog/greenteagc/marksweep-029.png
new file mode 100644
index 00000000..4bd16d43
--- /dev/null
+++ b/_content/blog/greenteagc/marksweep-029.png
Binary files differ
diff --git a/_content/blog/greenteagc/marksweep-030.png b/_content/blog/greenteagc/marksweep-030.png
new file mode 100644
index 00000000..8d03bc81
--- /dev/null
+++ b/_content/blog/greenteagc/marksweep-030.png
Binary files differ
diff --git a/_content/blog/greenteagc/marksweep-031.png b/_content/blog/greenteagc/marksweep-031.png
new file mode 100644
index 00000000..a72e4e06
--- /dev/null
+++ b/_content/blog/greenteagc/marksweep-031.png
Binary files differ
diff --git a/_content/blog/greenteagc/marksweep-032.png b/_content/blog/greenteagc/marksweep-032.png
new file mode 100644
index 00000000..34a79019
--- /dev/null
+++ b/_content/blog/greenteagc/marksweep-032.png
Binary files differ
diff --git a/_content/blog/greenteagc/marksweep-033.png b/_content/blog/greenteagc/marksweep-033.png
new file mode 100644
index 00000000..829277d0
--- /dev/null
+++ b/_content/blog/greenteagc/marksweep-033.png
Binary files differ
diff --git a/_content/blog/greenteagc/marksweep-034.png b/_content/blog/greenteagc/marksweep-034.png
new file mode 100644
index 00000000..e769d601
--- /dev/null
+++ b/_content/blog/greenteagc/marksweep-034.png
Binary files differ
diff --git a/_content/blog/greenteagc/marksweep-035.png b/_content/blog/greenteagc/marksweep-035.png
new file mode 100644
index 00000000..6a45f45d
--- /dev/null
+++ b/_content/blog/greenteagc/marksweep-035.png
Binary files differ
diff --git a/_content/blog/greenteagc/marksweep-036.png b/_content/blog/greenteagc/marksweep-036.png
new file mode 100644
index 00000000..abb61039
--- /dev/null
+++ b/_content/blog/greenteagc/marksweep-036.png
Binary files differ
diff --git a/_content/blog/greenteagc/marksweep-037.png b/_content/blog/greenteagc/marksweep-037.png
new file mode 100644
index 00000000..96797dd4
--- /dev/null
+++ b/_content/blog/greenteagc/marksweep-037.png
Binary files differ
diff --git a/_content/blog/greenteagc/marksweep-038.png b/_content/blog/greenteagc/marksweep-038.png
new file mode 100644
index 00000000..7eddb983
--- /dev/null
+++ b/_content/blog/greenteagc/marksweep-038.png
Binary files differ
diff --git a/_content/blog/greenteagc/marksweep-039.png b/_content/blog/greenteagc/marksweep-039.png
new file mode 100644
index 00000000..924ecd52
--- /dev/null
+++ b/_content/blog/greenteagc/marksweep-039.png
Binary files differ
diff --git a/_content/blog/greenteagc/marksweep-040.png b/_content/blog/greenteagc/marksweep-040.png
new file mode 100644
index 00000000..46ca2886
--- /dev/null
+++ b/_content/blog/greenteagc/marksweep-040.png
Binary files differ
diff --git a/_content/blog/greenteagc/marksweep-041.png b/_content/blog/greenteagc/marksweep-041.png
new file mode 100644
index 00000000..62748156
--- /dev/null
+++ b/_content/blog/greenteagc/marksweep-041.png
Binary files differ
diff --git a/_content/blog/greenteagc/marksweep-042.png b/_content/blog/greenteagc/marksweep-042.png
new file mode 100644
index 00000000..c3f69fd4
--- /dev/null
+++ b/_content/blog/greenteagc/marksweep-042.png
Binary files differ
diff --git a/_content/blog/greenteagc/marksweep-043.png b/_content/blog/greenteagc/marksweep-043.png
new file mode 100644
index 00000000..e758535f
--- /dev/null
+++ b/_content/blog/greenteagc/marksweep-043.png
Binary files differ
diff --git a/_content/blog/greenteagc/marksweep-044.png b/_content/blog/greenteagc/marksweep-044.png
new file mode 100644
index 00000000..e8f77abf
--- /dev/null
+++ b/_content/blog/greenteagc/marksweep-044.png
Binary files differ
diff --git a/_content/blog/greenteagc/marksweep-045.png b/_content/blog/greenteagc/marksweep-045.png
new file mode 100644
index 00000000..24fb6149
--- /dev/null
+++ b/_content/blog/greenteagc/marksweep-045.png
Binary files differ
diff --git a/_content/blog/greenteagc/marksweep-046.png b/_content/blog/greenteagc/marksweep-046.png
new file mode 100644
index 00000000..303f2325
--- /dev/null
+++ b/_content/blog/greenteagc/marksweep-046.png
Binary files differ
diff --git a/_content/blog/greenteagc/marksweep-047.png b/_content/blog/greenteagc/marksweep-047.png
new file mode 100644
index 00000000..9dceff2a
--- /dev/null
+++ b/_content/blog/greenteagc/marksweep-047.png
Binary files differ
diff --git a/_content/blog/greenteagc/marksweep-048.png b/_content/blog/greenteagc/marksweep-048.png
new file mode 100644
index 00000000..4c8cf82d
--- /dev/null
+++ b/_content/blog/greenteagc/marksweep-048.png
Binary files differ
diff --git a/_content/blog/greenteagc/timeline.png b/_content/blog/greenteagc/timeline.png
new file mode 100644
index 00000000..a6377c93
--- /dev/null
+++ b/_content/blog/greenteagc/timeline.png
Binary files differ