{"id":13439985,"url":"https://github.com/jepsen-io/maelstrom","last_synced_at":"2025-04-23T22:58:34.101Z","repository":{"id":43728380,"uuid":"88094811","full_name":"jepsen-io/maelstrom","owner":"jepsen-io","description":"A workbench for writing toy implementations of distributed systems.","archived":false,"fork":false,"pushed_at":"2025-02-04T20:38:45.000Z","size":1281,"stargazers_count":3239,"open_issues_count":17,"forks_count":196,"subscribers_count":26,"default_branch":"main","last_synced_at":"2025-04-23T22:58:20.745Z","etag":null,"topics":["distributed-systems","jepsen","testing"],"latest_commit_sha":null,"homepage":"","language":"Clojure","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"epl-1.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jepsen-io.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-04-12T20:47:04.000Z","updated_at":"2025-04-23T19:59:26.000Z","dependencies_parsed_at":"2023-02-09T17:00:38.098Z","dependency_job_id":"f3a9d3ae-92f1-456c-acd0-8c828bf74ba2","html_url":"https://github.com/jepsen-io/maelstrom","commit_stats":{"total_commits":287,"total_committers":36,"mean_commits":7.972222222222222,"dds":"0.20557491289198604","last_synced_commit":"0186f398f96564a0453dda97c07daeac67c3d8d7"},"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jepsen-io%2Fmaelstrom","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jepsen-io%2Fmaelstrom/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jepsen-io%2Fmaelstrom/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jepsen-io%2Fmaelstrom/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jepsen-io","download_url":"https://codeload.github.com/jepsen-io/maelstrom/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250528726,"owners_count":21445514,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["distributed-systems","jepsen","testing"],"created_at":"2024-07-31T03:01:18.733Z","updated_at":"2025-04-23T22:58:34.081Z","avatar_url":"https://github.com/jepsen-io.png","language":"Clojure","funding_links":[],"categories":["HarmonyOS","Clojure"],"sub_categories":["Windows Manager"],"readme":"# Maelstrom\n\n![Two images generated by Maelstrom runs of a transactional workload: a Lamport diagram showing requests flowing to transaction coordinators and on to a KV store, and a serialization anomaly consisting of dependency edges forming a cycle between transactions.](/doc/promo.png)\n\nMaelstrom is a workbench for learning distributed systems by writing your own.\nIt uses the [Jepsen](https://github.com/jepsen-io/jepsen) testing library to\ntest toy implementations of distributed systems. Maelstrom provides\nstandardized tests for things like \"a commutative set\" or \"a transactional\nkey-value store\", and lets you learn by writing implementations which those\ntest suites can exercise. It's used as a part of a distributed systems workshop\nby [Jepsen](https://jepsen.io/training).\n\nMaelstrom provides a [range of tests](/doc/workloads.md) for different kinds of\ndistributed systems, built on top of a [simple JSON\nprotocol](/doc/protocol.md) via STDIN and STDOUT. Users write servers [in any\nlanguage](/demo). Maelstrom runs those servers, sends them requests, routes\nmessages via a simulated network, and checks that clients observe expected\nbehavior. You want to write Plumtree in Bash? Byzantine Paxos in Intercal?\nMaelstrom is for you.\n\nMaelstrom's tooling lets users experiment with [simulated\nlatency](/doc/03-broadcast/02-performance.md) and [message\nloss](/doc/04-crdts/01-g-set.md#a-simple-g-set). Every test includes [timeline\nvisualizations](/doc/05-datomic/not-concurrent.png) of concurrency structure,\n[statistics](/doc/03-broadcast/02-performance.md#how-many-messages) on messages\nexchanged, [timeseries graphs](/doc/06-raft/final.png) to understand how\nlatency, availability, and throughput respond to changing conditions, and\n[Lamport diagrams](/doc/05-datomic/missing-value.png) so you can understand\nexactly how messages flow through your system. Maelstrom's checkers can verify\n[sophisticated safety properties](https://github.com/jepsen-io/elle) up to\nstrict serializability, and generate [intuitive, minimal\nexamples](/doc/05-datomic/g1-realtime.svg) of consistency anomalies.\n\nMaelstrom can help you model how a system responds to different cluster sizes,\nnetwork topologies, latency distributions, and faults like network partitions.\nMaelstrom also offers [simulated services](/doc/services.md) that you can use\nto build more complex systems.\n\nIt's built for testing toy systems, but don't let that fool you: Maelstrom is\nreasonably fast and can handle simulated clusters of 25+ nodes. On a 48-way\nXeon, it can use 94% of all cores, pushing upwards of 60,000 network\nmessages/sec.\n\n## Documentation\n\nThe Maelstrom Guide will take you through writing several different types of\ndistributed algorithms using Maelstrom. We begin by setting up Maelstrom and\nits dependencies, write our own tiny echo server, and move on to more\nsophisticated workloads.\n\n- [Chapter 1: Getting Ready](doc/01-getting-ready/index.md)\n- [Chapter 2: Echo](doc/02-echo/index.md)\n- [Chapter 3: Broadcast](doc/03-broadcast/index.md)\n- [Chapter 4: CRDTs](doc/04-crdts/index.md)\n- [Chapter 5: Datomic](doc/05-datomic/index.md)\n- [Chapter 6: Raft](doc/06-raft/index.md)\n\nThere are also several reference documents that may be helpful:\n\n- [Protocol](doc/protocol.md) defines Maelstrom's \"network\" protocol, message\n  structure, RPC semantics, and error handling.\n- [Workloads](doc/workloads.md) describes the various kinds of workloads that\n  Maelstrom can test, and define the messages involved in that particular\n  workload.\n- [Understanding Test Results](doc/results.md) explains how to interpret the\n  various plots, data structures, and log files generated by a test.\n- [Services](doc/services.md) discusses Maelstrom's built-in network services,\n  which you can use as primitives in building more complex systems.\n\n\n## Design Overview\n\nMaelstrom is a [Clojure](https://clojure.org/) program which runs on the [Java\nVirtual Machine](https://en.wikipedia.org/wiki/Java_virtual_machine). It uses\n[Jepsen](https://github.com/jepsen-io/jepsen) to generate operations, record a\nhistory of their results, and analyze what happens.\n\nWriting \"real\" distributed systems involves a lot of busywork: process\nmanagement, networking, and message serialization are complex, full of edge\ncases, and difficult to debug across languages. In addition, running a full\ncluster of virtual machines connected by a real IP network is tricky for many\nusers. Maelstrom strips these problems away so you can focus on the algorithmic\nessentials: process state, transitions, and messages.\n\nThe \"nodes\" in a Maelstrom test are plain old binaries written in any language.\nNodes read \"network\" messages as JSON from STDIN, write JSON \"network\" messages\nto STDOUT, and do their logging to STDERR. Maelstrom runs those nodes as\nprocesses on your local machine, and connects them via a simulated network.\nMaelstrom runs a collection of simulated network clients which make requests to\nthose nodes, receive responses, and records a history of those operations. At\nthe end of a test run, Maelstrom analyzes that history to identify safety\nviolations.\n\nThis allows learners to write their nodes in whatever language they are most\ncomfortable with, without having to worry about discovery, network\ncommunication, daemonization, writing their own distributed test harness, and\nso on. It also means that Maelstrom can perform sophisticated fault injection\nand trace analysis.\n\nMaelstrom starts in `maelstrom.core`, which parses CLI operations and\nconstructs a test map. It hands that off to Jepsen, which sets up the servers\nand Maelstrom services via `maelstrom.db`. Spawning binaries and handling their\nIO is done in `maelstrom.process`, and Maelstrom's internal services (e.g.\n`lin-kv` are defined in `maelstrom.service`. Jepsen then spawns clients\ndepending on the workload (`maelstrom.workload.*`) and a nemesis\n(`maelstrom.nemesis`) to inject faults.\n\nMessages between nodes are routed by `maelstrom.net`, and logged in\n`maelstrom.journal`. Clients send requests and parse responses via\n`maelstrom.client`, which also defines Maelstrom's RPC protocol.\n\nAt the end of the test, Jepsen checks the history using a checker built in\n`maelstrom.core`: workload-specific checkers are defined in their respective\nworkload namespaces. Network statistics are computed in\n`maelstrom.net.journal`, and Lamport diagrams are generated by\n`maelstrom.net.viz`.\n\n`maelstrom.doc` helps generate documentation based on `maelstrom.client`'s\nregistry of RPC types and workloads.\n\n## CLI Options\n\nA full list of options is available by running `java -jar maelstrom.jar test\n--help`. The important ones are:\n\n- `--workload NAME`: What kind of workload should be run?\n- `--bin SOME_BINARY`: The program you'd like Maelstrom to spawn instances of\n- `--node-count NODE-NAME`: How many instances of the binary should be spawned?\n\nTo get more information, use:\n\n- `--log-stderr`: Show STDERR output from each node in the Maelstrom log\n- `--log-net-send`: Log messages as they are sent into the network\n- `--log-net-recv`: Log messages as they are received by nodes\n\nTo make tests more or less aggressive, use:\n\n- `--time-limit SECONDS`: How long to run tests for\n- `--rate FLOAT`: Approximate number of requests per second\n- `--concurrency INT`: Number of clients to run concurrently. Use `4n` for 4 times the number of nodes.\n- `--latency MILLIS`: Approximate simulated network latency, during normal\n  operations.\n- `--latency-dist DIST`: What latency distribution should Maelstrom use?\n- `--nemesis FAULT_TYPE`: A comma-separated list of faults to inject\n- `--nemesis-interval SECONDS`: How long between nemesis operations, on average\n\nFor broadcast tests, try\n\n- `--topology TYPE`: Controls the shape of the network topology Jepsen offers\n  to nodes\n\nFor transactional tests, you can control transaction generation using\n\n- `--max-txn-length INT`: The maximum number of operations per transaction\n- `--key-count INT`: The number of concurrent keys to work with\n- `--max-writes-per-key INT`: How many unique write operations to generate per key.\n\nSSH options are unused; Maelstrom runs entirely on the local node.\n\n## Troubleshooting\n\n### Running ./maelstrom complains it's missing maelstrom.jar\n\nYou probably cloned this repository or downloaded the source and didn't compile\nit. Download the compiled release tarball instead; you'll find it on the GitHub\nrelease page.\n\nIf you want to run directly from source, you'll need the\n[Leiningen](https://leiningen.org) build system. Instead of `./maelstrom\n...`, run `lein run ...`.\n\n### Raft node processes still alive after maelstrom run\n\nYou may find that node processes maelstrom starts are not terminating at the end of a run as expected. To address this, make sure that if the process passed as `--bin` forks off a new process, it also handles the process' termination.\n\n#### Example\n\nIn `bin/raft`\n```sh\n#!/bin/bash\n\n# Forks a new process.\njava -jar target/raft.jar\n```\n\nIn `bin/raft`\n```sh\n#!/bin/bash\n\n# Replaces the shell without creating a new process.\nexec java -jar target/raft.jar\n```\n\n## License\n\nCopyright © 2017, 2020--2022 Kyle Kingsbury, Kit Patella, \u0026 Jepsen, LLC\n\nDistributed under the Eclipse Public License either version 1.0 or (at\nyour option) any later version.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjepsen-io%2Fmaelstrom","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjepsen-io%2Fmaelstrom","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjepsen-io%2Fmaelstrom/lists"}