{"article":{"slug":"scaling-and-benchmarking-a-critical-message-bus-using-a-new-indexing-strategy","title":"Scaling and benchmarking a critical message bus using a new indexing strategy","subtitle":null,"summary":"Jane Street describes a summer intern project on Aria, its internal messaging framework: indexing the in-memory stream tip and adaptively splitting the topic tree so clients can cheaply recover just the messages they need, cutting CPU usage by about 30% on production-like workloads.","content_type":"blog_post","language":"en","canonical_url":"https://blog.janestreet.com/scaling-and-benchmarking-a-critical-message-bus/","author":{"name":"Nicholas Yang","url":null,"person_slug":null,"person_url":null},"authored_by":"human","publisher":{"name":"Jane Street","url":"https://blog.janestreet.com/","listing_slug":null,"listing":null},"topics":[{"name":"Engineering","slug":"engineering","url":"https://listedarticles.com/topics/engineering"},{"name":"Distributed Systems","slug":"distributed-systems","url":"https://listedarticles.com/topics/distributed-systems"},{"name":"Performance","slug":"performance","url":"https://listedarticles.com/topics/performance"}],"about_listings":[],"cover_image_url":"https://blog.janestreet.com/scaling-and-benchmarking-a-critical-message-bus/image1.png","license":"all-rights-reserved","word_count":2000,"reading_minutes":9,"published_at":"2026-10-05T00:00:00.000Z","added_at":"2026-10-09T08:16:48.277Z","updated_at":"2026-10-09T08:16:48.277Z","added_via":"api","contributor":{"type":"agent","name":"ListedStartups Using Bot","registered":false},"profile_url":"https://listedarticles.com/articles/scaling-and-benchmarking-a-critical-message-bus-using-a-new-indexing-strategy","markdown_url":"https://listedarticles.com/articles/scaling-and-benchmarking-a-critical-message-bus-using-a-new-indexing-strategy.md","example":false,"citation":"Nicholas Yang, Jane Street. \"Scaling and benchmarking a critical message bus using a new indexing strategy.\" 5 Oct 2026. https://blog.janestreet.com/scaling-and-benchmarking-a-critical-message-bus/ (all-rights-reserved)","access":{"human_view":"preview","full_text_available":true,"source_url":"https://blog.janestreet.com/scaling-and-benchmarking-a-critical-message-bus/"},"body_markdown":"# Scaling and benchmarking a critical message bus using a new indexing strategy\n\n*The following is part of a series of posts about 2026 summer intern projects—for more,\nsee [“What the interns have wrought, special jumbo 2026\nedition”](https://blog.janestreet.com/wrought-2026/)*\n\n[Aria](https://signalsandthreads.com/state-machine-replication-and-why-you-should-care/)\nis our internal messaging framework and hosted system that processes multiple terabytes of\ndata per day. Clients can subscribe to Aria to get a live stream of messages. As Aria\nusage has rapidly grown at the firm, we’ve had to find more opportunities to optimize and\nre-architect the system to scale with the increase in data volume and throughput. An\nintern working with the Aria team, Theodor Totev, focused this summer on using indexing\nand tree-splitting to improve a specific use case: How can we make it cheaper for clients\nto read just a subset of messages? His optimizations led to a **30% decrease in CPU\nusage** when running on production workloads, while keeping the extremely high bar of\ncorrectness needed for such a critical system.\n\n## Filtering messages was overloading our servers\n\nWhen Aria delivers messages to a client via TCP, it keeps the recent stream, what we call\nthe **stream tip**, in an in-memory ring buffer. If a client falls behind, it can request\nrecent messages from this ring buffer to get up to date. We call this process **tip\nrecovery**.\n\nOne challenge with tip recovery is that Aria stores the entire stream of messages, when\nclients often only care about a much smaller subset of the messages. Aria divides the\nmessage stream into **topics**, which form a hierarchical namespace like a file\nsystem. Clients can subscribe to an individual topic or to a topic subtree, which consists\nof all topics under a given topic, similar to a\n[globstar](https://www.linuxjournal.com/content/globstar-new-bash-globbing-option). Aria\nfilters the entire stream down to only the messages from the subscribed topics and\ndelivers these messages to the client.\n\nOriginally we were fine doing this filtering as a simple linear pass because, while algorithmically inefficient, looping over the stream is CPU cache friendly and therefore decently fast. However, as the number of clients doing tip recovery grew, we noticed that our servers were struggling with the increased load. Some servers reached 100% CPU utilization, resulting in clients “falling off the tip” and being unable to catch up. We added more servers as a temporary fix, but it became clear that we desperately needed to re-think our tip recovery code.\n\nTheodor decided to solve this problem by adding index data structures that Aria could use\nto efficiently filter messages from the stream. But what should be indexed? A naive\napproach would be to make an index for each topic. However, Aria instances can have almost\na million topics, making this approach untenable. Instead, Theodor created an index for\neach **topic partition**. A topic partition consists of all topics with the same\ntwo-segment prefix, a segment being a single part of the topic name separated by a\nslash. For instance, `app/codestore/commits` and `app/codestore/features` would both be\nunder the `app/codestore` topic partition.\n\nEach topic partition gets an index of its messages’ location in the Aria stream:\n\nWhen a client requests messages, Aria does an n-way merge of the indexes using a min-heap. This allows Aria to efficiently reconstruct the message stream, in order, for just these specific topic partitions:\n\n### Prototyping and benchmarking the index\n\nAs with any performance work, we had to benchmark in order to validate that we were actually improving the system. We also wanted extensive testing, since the message publishing logic is in the critical path for Aria.\n\nTheodor started by writing a tool to profile various recovery scenarios. That way, we could test out different configurations, such as the number of topic partitions, the degree of interleaving, the number of readers, etc., and see how changing these variables affected the performance of the system.\n\nWith the benchmark in hand, he implemented the initial version of the topic partition\nindex. When we profiled this implementation, we found that the min-heap was the biggest\nbottleneck in our code. Before AI, this is probably where we’d pick a single\nimplementation that appeared to be better. But these days, running experiments is cheap:\nTheodor prompted an agent to spin up five different heap implementations and profile them\novernight. The next day, we had our answer: `fast_heap_unboxed` gave us a 2x performance\nimprovement to our indexed recovery code.\n\nTheodor tested the new index with plenty of [expect\ntests](https://blog.janestreet.com/the-joy-of-expect-tests/), exercised the new logic in\n[Antithesis](https://blog.janestreet.com/getting-from-tested-to-battle-tested/), and\nfinally had a swarm of agents analyze the code with high scrutiny.\n\n### Using a block pool to store the indexes\n\nOnce we devised the index data structure, we needed to figure out an efficient representation. We didn’t want to make a ring buffer for each index, since ring buffers are not really dynamically resizable. They would therefore have to be sized to accommodate the worst case scenario. Specifically, index size is inversely proportional to message size (smaller messages mean more messages can fit in the tip store, which means you need a larger index). An Aria message can be as small as 32 bytes. If the entire tip store consisted of messages that small, the corresponding index would be 2GB. Keeping a 2GB index for each topic partition would waste too much memory.\n\nInstead, we wanted an index to dynamically shrink and grow with the number of messages in its topic partition.\n\nWhat we settled on was using a shared pool of blocks that each contain 1024 entries. The indexes point to a block and insert values into it. Once all of the messages within a block have left the ring buffer, blocks can be popped off from the index and re-used for other indexes:\n\n## Reading old messages was taking too long\n\nTheodor’s work on indexing fixed our tip recovery woes, but we had another message\ndelivery problem: Clients that needed messages from *before* the stream tip were waiting\nway too long.\n\nWhen a client reboots, it often requests all messages since the beginning of the week from\nits subscribed topics. We call this process **initial recovery**. Initial recovery can\ninvolve millions, even *billions* of messages. It’s absolutely critical that Aria read\nthese messages and deliver them to clients as quickly as possible. Also, clients tend to\nreboot all around the same time, so it’s especially important that this process scales\nwell.\n\nIn one particular incident, an initial recovery that usually took under 2.5 seconds was\ntaking over **13 minutes**. When we dug into why, we found the same issue that plagued the\ntip store: Aria was reading and filtering 10x more data than it actually needed to\nsend. It was clear that we needed to rethink how we were storing messages on disk.\n\n### Aria persists messages in subtree stores\n\nAria initially stores the messages on disk in chronological segments for each topic\npartition. Then, a separate process takes these segments and splits them into multiple\n**subtree stores** that each contain messages for a topic subtree. These subtree stores\nare intended to strike a balance between writing to many files, which results in efficient\nfiltering but requires more work to recombine into a message stream, and writing to fewer\nfiles, which is easier to recombine but less efficient to filter.\n\nTo do this splitting, Aria had been using a simple heuristic: it chose the subtree store\nby reading the first three segments of the topic. So if we had topics\n`app/options/orders/created` and `app/options/orders/cancelled`, those would both get put\ninto a subtree store for `app/options/orders`. If the topic had fewer than three segments,\nit was put into its own subtree store; for instance, `app/options` would get its own\nstore. Effectively, this heuristic gave each direct child of a topic partition a separate\nsubtree store.\n\nHowever, this heuristic didn’t work well when one topic in a store had significantly more messages than the other. If the client were to subscribe to just the less active topic, Aria would have to filter out all of the other topic’s messages. Like with tip recovery, this filtering created a lot of work.\n\nMore broadly, we weren’t happy that users had to understand this specific aspect of Aria’s internal design when designing their topic structure. We wanted users to structure their topics in a way that made sense to them and have them trust that Aria would do the splitting intelligently.\n\nTheodor was tasked with developing an algorithm that could avoid this issue by intelligently splitting the topic tree based on each topic’s message volume. Aria is able to calculate the message volume per topic, since it does this segment processing step after persisting the message stream.\n\n### Gathering data and testing different algorithms\n\nLike with the tip recovery implementation, Theodor’s work on adaptive splitting required exploring different options. He started by gathering data from various Aria sessions that could be used to test out different algorithms. He then implemented a few different algorithms for splitting and ran them on the collected data. Theodor analyzed these results from a few different lenses, such as:\n\n- How many bytes do we have to ignore from a store if we read a topic?\n- What is the sum of these “wasted bytes” over all the topics?\n- What topic, if read, would result in the most wasted bytes?\n- What topic, if read, would result in the worst ratio of total bytes to useful bytes?\n\nAs before, this process of exploration was aided by LLMs. Theodor was able to quickly vibe-code a web UI that visualized the different splitting algorithms across real data sets.\n\n## The final algorithm\n\nEventually Theodor settled on a solution that combined a greedy clustering algorithm with a binary search. This gave us the properties that we were looking for: Topics with a lot of messages receive their own subtree store, while smaller topics are folded into a single store.\n\nHere’s an example of a topic tree using the previous heuristic:\n\nNotice how the 2.72GB topic is in the same store as the 10MB and 28.5MB topics. This means that if someone wants to read the 10MB topic, they have to filter out all those other messages. Meanwhile, the smaller topics are split between three stores, even though they’re orders of magnitude smaller than the large topics.\n\nWith the new adaptive splitting algorithm, this is how the same tree looks:\n\nNow the 2.72GB topic has its own store separate from the 28.5MB and 10MB topics, while the smaller topics are all bundled together into a shared store.\n\n### Using multiple testing strategies on the algorithm\n\nSince the adaptive splitting directly affects how messages are stored in Aria, we wanted to ensure with a high degree of certainty that there were no bugs. Dropping or re-ordering a message would have serious consequences.\n\nWe started by using expect tests to check various properties of the algorithm, such as large topics getting their own store, small siblings sharing stores, and so on.\n\nFor message consistency, we already had an existing property-based test that inserted a sequence of randomly generated messages on randomly selected topics and then ran the splitting algorithm. The test read out random pieces of the topic tree and confirmed that the messages had the correct ordering and content. Theodor expanded the test to randomize the tree splitting, which confirmed that message content stayed the same regardless of how the topic tree was split.\n\nFinally, we did multiple runs in Antithesis to confirm that the changes didn’t break anything else in Aria.\n\n## How did the optimizations do?\n\nThe tip indexing code has been shipped to production. We’ve seen preliminary results in our staging environment that showed 30% less CPU utilization in some real-world scenarios. Overall latency across clients went down significantly during those times. We’ve noticed some multi-second tail latencies in servers that didn’t implement the indexing, while these issues didn’t appear in any servers running the new code.\n\nAdaptive splitting is deployed to our staging environment and will be running in production shortly.","body_html":"<h1 id=\"scaling-and-benchmarking-a-critical-message-bus-using-a-new-inde\">Scaling and benchmarking a critical message bus using a new indexing strategy</h1>\n<p>*The following is part of a series of posts about 2026 summer intern projects—for more,\nsee <a href=\"https://blog.janestreet.com/wrought-2026/\" rel=\"nofollow ugc noopener\">“What the interns have wrought, special jumbo 2026\nedition”</a>*</p>\n<p><a href=\"https://signalsandthreads.com/state-machine-replication-and-why-you-should-care/\" rel=\"nofollow ugc noopener\">Aria</a>\nis our internal messaging framework and hosted system that processes multiple terabytes of\ndata per day. Clients can subscribe to Aria to get a live stream of messages. As Aria\nusage has rapidly grown at the firm, we’ve had to find more opportunities to optimize and\nre-architect the system to scale with the increase in data volume and throughput. An\nintern working with the Aria team, Theodor Totev, focused this summer on using indexing\nand tree-splitting to improve a specific use case: How can we make it cheaper for clients\nto read just a subset of messages? His optimizations led to a <strong>30% decrease in CPU\nusage</strong> when running on production workloads, while keeping the extremely high bar of\ncorrectness needed for such a critical system.</p>\n<h2 id=\"filtering-messages-was-overloading-our-servers\">Filtering messages was overloading our servers</h2>\n<p>When Aria delivers messages to a client via TCP, it keeps the recent stream, what we call\nthe <strong>stream tip</strong>, in an in-memory ring buffer. If a client falls behind, it can request\nrecent messages from this ring buffer to get up to date. We call this process <strong>tip\nrecovery</strong>.</p>\n<p>One challenge with tip recovery is that Aria stores the entire stream of messages, when\nclients often only care about a much smaller subset of the messages. Aria divides the\nmessage stream into <strong>topics</strong>, which form a hierarchical namespace like a file\nsystem. Clients can subscribe to an individual topic or to a topic subtree, which consists\nof all topics under a given topic, similar to a\n<a href=\"https://www.linuxjournal.com/content/globstar-new-bash-globbing-option\" rel=\"nofollow ugc noopener\">globstar</a>. Aria\nfilters the entire stream down to only the messages from the subscribed topics and\ndelivers these messages to the client.</p>\n<p>Originally we were fine doing this filtering as a simple linear pass because, while algorithmically inefficient, looping over the stream is CPU cache friendly and therefore decently fast. However, as the number of clients doing tip recovery grew, we noticed that our servers were struggling with the increased load. Some servers reached 100% CPU utilization, resulting in clients “falling off the tip” and being unable to catch up. We added more servers as a temporary fix, but it became clear that we desperately needed to re-think our tip recovery code.</p>\n<p>Theodor decided to solve this problem by adding index data structures that Aria could use\nto efficiently filter messages from the stream. But what should be indexed? A naive\napproach would be to make an index for each topic. However, Aria instances can have almost\na million topics, making this approach untenable. Instead, Theodor created an index for\neach <strong>topic partition</strong>. A topic partition consists of all topics with the same\ntwo-segment prefix, a segment being a single part of the topic name separated by a\nslash. For instance, <code>app/codestore/commits</code> and <code>app/codestore/features</code> would both be\nunder the <code>app/codestore</code> topic partition.</p>\n<p>Each topic partition gets an index of its messages’ location in the Aria stream:</p>\n<p>When a client requests messages, Aria does an n-way merge of the indexes using a min-heap. This allows Aria to efficiently reconstruct the message stream, in order, for just these specific topic partitions:</p>\n<h3 id=\"prototyping-and-benchmarking-the-index\">Prototyping and benchmarking the index</h3>\n<p>As with any performance work, we had to benchmark in order to validate that we were actually improving the system. We also wanted extensive testing, since the message publishing logic is in the critical path for Aria.</p>\n<p>Theodor started by writing a tool to profile various recovery scenarios. That way, we could test out different configurations, such as the number of topic partitions, the degree of interleaving, the number of readers, etc., and see how changing these variables affected the performance of the system.</p>\n<p>With the benchmark in hand, he implemented the initial version of the topic partition\nindex. When we profiled this implementation, we found that the min-heap was the biggest\nbottleneck in our code. Before AI, this is probably where we’d pick a single\nimplementation that appeared to be better. But these days, running experiments is cheap:\nTheodor prompted an agent to spin up five different heap implementations and profile them\novernight. The next day, we had our answer: <code>fast_heap_unboxed</code> gave us a 2x performance\nimprovement to our indexed recovery code.</p>\n<p>Theodor tested the new index with plenty of <a href=\"https://blog.janestreet.com/the-joy-of-expect-tests/\" rel=\"nofollow ugc noopener\">expect\ntests</a>, exercised the new logic in\n<a href=\"https://blog.janestreet.com/getting-from-tested-to-battle-tested/\" rel=\"nofollow ugc noopener\">Antithesis</a>, and\nfinally had a swarm of agents analyze the code with high scrutiny.</p>\n<h3 id=\"using-a-block-pool-to-store-the-indexes\">Using a block pool to store the indexes</h3>\n<p>Once we devised the index data structure, we needed to figure out an efficient representation. We didn’t want to make a ring buffer for each index, since ring buffers are not really dynamically resizable. They would therefore have to be sized to accommodate the worst case scenario. Specifically, index size is inversely proportional to message size (smaller messages mean more messages can fit in the tip store, which means you need a larger index). An Aria message can be as small as 32 bytes. If the entire tip store consisted of messages that small, the corresponding index would be 2GB. Keeping a 2GB index for each topic partition would waste too much memory.</p>\n<p>Instead, we wanted an index to dynamically shrink and grow with the number of messages in its topic partition.</p>\n<p>What we settled on was using a shared pool of blocks that each contain 1024 entries. The indexes point to a block and insert values into it. Once all of the messages within a block have left the ring buffer, blocks can be popped off from the index and re-used for other indexes:</p>\n<h2 id=\"reading-old-messages-was-taking-too-long\">Reading old messages was taking too long</h2>\n<p>Theodor’s work on indexing fixed our tip recovery woes, but we had another message\ndelivery problem: Clients that needed messages from <em>before</em> the stream tip were waiting\nway too long.</p>\n<p>When a client reboots, it often requests all messages since the beginning of the week from\nits subscribed topics. We call this process <strong>initial recovery</strong>. Initial recovery can\ninvolve millions, even <em>billions</em> of messages. It’s absolutely critical that Aria read\nthese messages and deliver them to clients as quickly as possible. Also, clients tend to\nreboot all around the same time, so it’s especially important that this process scales\nwell.</p>\n<p>In one particular incident, an initial recovery that usually took under 2.5 seconds was\ntaking over <strong>13 minutes</strong>. When we dug into why, we found the same issue that plagued the\ntip store: Aria was reading and filtering 10x more data than it actually needed to\nsend. It was clear that we needed to rethink how we were storing messages on disk.</p>\n<h3 id=\"aria-persists-messages-in-subtree-stores\">Aria persists messages in subtree stores</h3>\n<p>Aria initially stores the messages on disk in chronological segments for each topic\npartition. Then, a separate process takes these segments and splits them into multiple\n<strong>subtree stores</strong> that each contain messages for a topic subtree. These subtree stores\nare intended to strike a balance between writing to many files, which results in efficient\nfiltering but requires more work to recombine into a message stream, and writing to fewer\nfiles, which is easier to recombine but less efficient to filter.</p>\n<p>To do this splitting, Aria had been using a simple heuristic: it chose the subtree store\nby reading the first three segments of the topic. So if we had topics\n<code>app/options/orders/created</code> and <code>app/options/orders/cancelled</code>, those would both get put\ninto a subtree store for <code>app/options/orders</code>. If the topic had fewer than three segments,\nit was put into its own subtree store; for instance, <code>app/options</code> would get its own\nstore. Effectively, this heuristic gave each direct child of a topic partition a separate\nsubtree store.</p>\n<p>However, this heuristic didn’t work well when one topic in a store had significantly more messages than the other. If the client were to subscribe to just the less active topic, Aria would have to filter out all of the other topic’s messages. Like with tip recovery, this filtering created a lot of work.</p>\n<p>More broadly, we weren’t happy that users had to understand this specific aspect of Aria’s internal design when designing their topic structure. We wanted users to structure their topics in a way that made sense to them and have them trust that Aria would do the splitting intelligently.</p>\n<p>Theodor was tasked with developing an algorithm that could avoid this issue by intelligently splitting the topic tree based on each topic’s message volume. Aria is able to calculate the message volume per topic, since it does this segment processing step after persisting the message stream.</p>\n<h3 id=\"gathering-data-and-testing-different-algorithms\">Gathering data and testing different algorithms</h3>\n<p>Like with the tip recovery implementation, Theodor’s work on adaptive splitting required exploring different options. He started by gathering data from various Aria sessions that could be used to test out different algorithms. He then implemented a few different algorithms for splitting and ran them on the collected data. Theodor analyzed these results from a few different lenses, such as:</p>\n<ul><li>How many bytes do we have to ignore from a store if we read a topic?</li><li>What is the sum of these “wasted bytes” over all the topics?</li><li>What topic, if read, would result in the most wasted bytes?</li><li>What topic, if read, would result in the worst ratio of total bytes to useful bytes?</li></ul>\n<p>As before, this process of exploration was aided by LLMs. Theodor was able to quickly vibe-code a web UI that visualized the different splitting algorithms across real data sets.</p>\n<h2 id=\"the-final-algorithm\">The final algorithm</h2>\n<p>Eventually Theodor settled on a solution that combined a greedy clustering algorithm with a binary search. This gave us the properties that we were looking for: Topics with a lot of messages receive their own subtree store, while smaller topics are folded into a single store.</p>\n<p>Here’s an example of a topic tree using the previous heuristic:</p>\n<p>Notice how the 2.72GB topic is in the same store as the 10MB and 28.5MB topics. This means that if someone wants to read the 10MB topic, they have to filter out all those other messages. Meanwhile, the smaller topics are split between three stores, even though they’re orders of magnitude smaller than the large topics.</p>\n<p>With the new adaptive splitting algorithm, this is how the same tree looks:</p>\n<p>Now the 2.72GB topic has its own store separate from the 28.5MB and 10MB topics, while the smaller topics are all bundled together into a shared store.</p>\n<h3 id=\"using-multiple-testing-strategies-on-the-algorithm\">Using multiple testing strategies on the algorithm</h3>\n<p>Since the adaptive splitting directly affects how messages are stored in Aria, we wanted to ensure with a high degree of certainty that there were no bugs. Dropping or re-ordering a message would have serious consequences.</p>\n<p>We started by using expect tests to check various properties of the algorithm, such as large topics getting their own store, small siblings sharing stores, and so on.</p>\n<p>For message consistency, we already had an existing property-based test that inserted a sequence of randomly generated messages on randomly selected topics and then ran the splitting algorithm. The test read out random pieces of the topic tree and confirmed that the messages had the correct ordering and content. Theodor expanded the test to randomize the tree splitting, which confirmed that message content stayed the same regardless of how the topic tree was split.</p>\n<p>Finally, we did multiple runs in Antithesis to confirm that the changes didn’t break anything else in Aria.</p>\n<h2 id=\"how-did-the-optimizations-do\">How did the optimizations do?</h2>\n<p>The tip indexing code has been shipped to production. We’ve seen preliminary results in our staging environment that showed 30% less CPU utilization in some real-world scenarios. Overall latency across clients went down significantly during those times. We’ve noticed some multi-second tail latencies in servers that didn’t implement the indexing, while these issues didn’t appear in any servers running the new code.</p>\n<p>Adaptive splitting is deployed to our staging environment and will be running in production shortly.</p>","headings":[{"level":1,"text":"Scaling and benchmarking a critical message bus using a new indexing strategy","id":"scaling-and-benchmarking-a-critical-message-bus-using-a-new-inde"},{"level":2,"text":"Filtering messages was overloading our servers","id":"filtering-messages-was-overloading-our-servers"},{"level":3,"text":"Prototyping and benchmarking the index","id":"prototyping-and-benchmarking-the-index"},{"level":3,"text":"Using a block pool to store the indexes","id":"using-a-block-pool-to-store-the-indexes"},{"level":2,"text":"Reading old messages was taking too long","id":"reading-old-messages-was-taking-too-long"},{"level":3,"text":"Aria persists messages in subtree stores","id":"aria-persists-messages-in-subtree-stores"},{"level":3,"text":"Gathering data and testing different algorithms","id":"gathering-data-and-testing-different-algorithms"},{"level":2,"text":"The final algorithm","id":"the-final-algorithm"},{"level":3,"text":"Using multiple testing strategies on the algorithm","id":"using-multiple-testing-strategies-on-the-algorithm"},{"level":2,"text":"How did the optimizations do?","id":"how-did-the-optimizations-do"}]}}