{"id":32789452,"url":"https://github.com/r3shape/libecx","last_synced_at":"2025-11-05T10:01:57.004Z","repository":{"id":321671171,"uuid":"1057516039","full_name":"r3shape/libECX","owner":"r3shape","description":"A minimal, performant ECS library written in C.","archived":false,"fork":false,"pushed_at":"2025-10-30T21:22:04.000Z","size":124,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-10-30T23:12:09.461Z","etag":null,"topics":["c99","ecs","single-header"],"latest_commit_sha":null,"homepage":"https://github.com/r3shape/Uniform","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/r3shape.png","metadata":{"files":{"readme":"README.md","changelog":null,"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,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-09-15T20:49:13.000Z","updated_at":"2025-10-30T21:22:07.000Z","dependencies_parsed_at":"2025-10-30T23:12:28.950Z","dependency_job_id":"d63cd34f-4c7e-4135-9686-e152f43672ef","html_url":"https://github.com/r3shape/libECX","commit_stats":null,"previous_names":["r3shape/libecx"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/r3shape/libECX","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/r3shape%2FlibECX","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/r3shape%2FlibECX/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/r3shape%2FlibECX/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/r3shape%2FlibECX/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/r3shape","download_url":"https://codeload.github.com/r3shape/libECX/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/r3shape%2FlibECX/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":282799913,"owners_count":26729199,"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","status":"online","status_checked_at":"2025-11-05T02:00:05.946Z","response_time":58,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["c99","ecs","single-header"],"created_at":"2025-11-05T10:01:52.443Z","updated_at":"2025-11-05T10:01:56.997Z","avatar_url":"https://github.com/r3shape.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ![r3shape-labs](https://github.com/user-attachments/assets/ac634f13-e084-4387-aded-4679eb048cac)  \u003cbr\u003e libECX\n| NOTE: ECX is dependant upon the [_libR3_ ](https://github.com/r3shape/libR3) runtime library, and built with [_r3make_ ](https://github.com/r3shape/r3make).\n\n**libECX** an ECS implementation designed as a **minimal, cache-aware, fully deterministic entity–component runtime** implemented in **pure C99**.\n\n## libECX 1.1.0 Benchmark\n\nPerformance measured on **15,000,000 entities**\n\n| Operation                                     | Time (ms) | Throughput                                           |\n| --------------------------------------------- | --------- | ---------------------------------------------------- |\n| **Entity Spawn + Bind (pos + vel)**           | 401.8     | **37.3 M ent/sec**                                   |\n| **Query Configuration (Compose + Decompose)** | 76.7      | **13.0 M ent/sec**                                   |\n| **Move System — Single Frame (pos += vel)**   | 134.6     | **111.4 M ent/sec** (~ **1.9 M ent/frame @ 60 fps**) |\n\n### Highlights\n\n* **`ECXComposition`:** unified component-field composition with full arena locality.\n* **Pointer-based iteration:** eliminated composition copy overhead for massive speedup.\n* **Peak throughput:** \u003e 110 M entities/sec on single-threaded CPU workloads.\n* **Fully deterministic:** every run produces identical state evolution and timings.\n* **Memory-local design:** all component and query data share a single arena allocator.\n\n\n## Runtime Flow\n\nA typical runtime pass:\n\n```c\nECXComponent pos = ecxNewComponent((ECXComponentDesc){\n    .mask = (1 \u003c\u003c 0), .max = 100,\n    .fields = 3,\n    .fieldv = (ECXFieldDesc[]){\n        { .hash=\"x\", .stride=sizeof(f32) },\n        { .hash=\"y\", .stride=sizeof(f32) },\n        { .hash=\"z\", .stride=sizeof(f32) }\n    }\n});\n\nECXEntity e1 = ecxNewEntity();\necxBind(e1, pos);\n\necxSetField(0, \u0026(f32){123.4f}, e1, pos);\n\nf32 val;\necxGetField(0, \u0026val, e1, pos);\n\nECXQuery query = ecxQuery((ECXQueryDesc){ .all = (1 \u003c\u003c 0) });\necxIter(query, sys, NULL);\n```\n\n## Key Properties\n\n| Feature                 | Description                                                                |\n| ----------------------- | -------------------------------------------------------------------------- |\n| **Performance**         | O(1) entity/component access. No heap churn.                               |\n| **Cache Coherence**     | SoA layout; field-major for SIMD/SoA traversal.                            |\n| **Incremental Updates** | Configs and queries update immediately upon bind/unbind.                   |\n| **Lifetime Safety**     | Generational handles prevent UAF and stale references.                     |\n| **Reflection-Free**     | No strings or RTTI at runtime. All hashes precomputed.                     |\n| **Arena-Based**         | All component fields allocated contiguously in arena memory.               |\n| **Portable**            | Pure ISO C99. No platform dependencies.                                    |\n\n## Systems and Iteration\n\nlibECX adopts a **stateless system model**:\nSystems are just function pointers with a consistent signature:\n\n```c\ntypedef none (*ECXSystem)(u32 index, ptr user, ECXComposition* comp);\n```\n\nThe runtime uses this lightweight iteration API:\n\n```c\nnone ecxIter(ECXQuery query, ECXSystem sys, ptr user);\n```\n\nThis allows for maximum control — systems are pure functions,\nand queries/configs act as live, incrementally updated views of entity membership.\n\n## Example Output\n\n```\n[r3kit::SUCCESS] position component: 256\n[r3kit::SUCCESS] e1, e2, e3: 4294969765, 8589937061, 12884904357\n[r3kit::SUCCESS] e1 bound to pos: 4294969765, 256\n[r3kit::SUCCESS] e3 bound to pos: 12884904357, 256\n[r3kit::SUCCESS] e1 field 0 (x field) got: 1234.43\n[r3kit::SUCCESS] e3 field 0 (x field) got: 420.69\n```\n\n## Future Work (v2.0 Roadmap)\n\n* **Reactive systems:** automatic config invalidation and rebuild on structural change.\n* **Dependency graphs:** automatic system ordering and dependency management.\n* **Thread-safe configs:** atomic bind/unbind for multi-threaded iteration.\n* **Per-component slabs:** replace linear arena with fragment-reclaiming slab allocators.\n* **Dynamic archetypes:** cached query graphs for faster filter reuse.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fr3shape%2Flibecx","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fr3shape%2Flibecx","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fr3shape%2Flibecx/lists"}