{"id":13447180,"url":"https://github.com/mogill/ems","last_synced_at":"2025-03-21T17:30:56.385Z","repository":{"id":15523745,"uuid":"18258202","full_name":"mogill/ems","owner":"mogill","description":"Extended Memory Semantics - Persistent shared object memory and parallelism for Node.js and Python","archived":false,"fork":false,"pushed_at":"2020-08-07T14:30:46.000Z","size":1283,"stargazers_count":595,"open_issues_count":5,"forks_count":41,"subscribers_count":27,"default_branch":"master","last_synced_at":"2025-03-02T00:03:07.553Z","etag":null,"topics":["ems","extended-memory-semantics","javascript","json","json-data","multithreading","non-volatile-memory","openmp","parallel","persistent-data","persistent-data-structure","persistent-memory","python","shared-memory"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mogill.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}},"created_at":"2014-03-30T05:28:45.000Z","updated_at":"2025-01-04T13:15:33.000Z","dependencies_parsed_at":"2022-08-07T08:01:10.714Z","dependency_job_id":null,"html_url":"https://github.com/mogill/ems","commit_stats":null,"previous_names":[],"tags_count":10,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mogill%2Fems","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mogill%2Fems/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mogill%2Fems/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mogill%2Fems/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mogill","download_url":"https://codeload.github.com/mogill/ems/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244838077,"owners_count":20518780,"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":["ems","extended-memory-semantics","javascript","json","json-data","multithreading","non-volatile-memory","openmp","parallel","persistent-data","persistent-data-structure","persistent-memory","python","shared-memory"],"created_at":"2024-07-31T05:01:10.247Z","updated_at":"2025-03-21T17:30:55.935Z","avatar_url":"https://github.com/mogill.png","language":"JavaScript","readme":"OSX | Linux | Node 4.1-14.x, Python2/3:\n[![Build Status](https://travis-ci.org/mogill/ems.svg?branch=master)](https://travis-ci.org/mogill/ems)\n[![npm version](https://badge.fury.io/js/ems.svg)](https://www.npmjs.com/package/ems)\n\n### [API Documentation](http://mogill.github.io/ems/Docs/reference.html) | [EMS Website](http://mogill.github.io/ems/Docs/index.html)\n\n\n\n# Extended Memory Semantics (EMS)\n__EMS makes possible persistent shared memory parallelism between Node.js, Python, and C/C++__.\n\nExtended Memory Semantics (EMS) unifies synchronization and storage primitives\nto address several challenges of parallel programming:\n+ Allows any number or kind of processes to share objects\n+ Manages synchronization and object coherency\n+ Implements persistence to non-volatile memory and secondary storage\n+ Provides dynamic load-balancing between processes\n+ May substitute or complement other forms of parallelism\n\n## [Examples: Parallel web servers, word counting](https://github.com/mogill/ems/tree/master/Examples)\n\n#### Table of Contents\n* [Parallel Execution Models Supported](#Types-of-Concurrency) Fork Join, Bulk Synchronous Parallel, User defined\n* [Atomic Operations](#Built-in-Atomic-Operations) Atomic Read-Modify-Write operations\n* [Examples](https://github.com/mogill/ems/tree/master/Examples) Parallel web servers, word counting\n* [Benchmarks](#Examples-and-Benchmarks) Bandwidth, Transaction processing\n* [Synchronization as a Property of the Data, Not a Duty for Tasks](#Synchronization-Property) Full/Empty tags\n* [Installation](#Installation) Downloading from Git or NPM\n* [Roadmap](#Roadmap) The Future™! It's all already happened\n\n#### EMS is targeted at tasks too large for one core or one process but too small for a scalable cluster\n\nA modern multi-core server has 16-32 cores and nearly 1TB of memory,\nequivalent to an entire rack of systems from a few years ago.\nAs a consequence, jobs formerly requiring a Map-Reduce cluster\ncan now be performed entirely in shared memory on a single server\nwithout using distributed programming.\n\n## Sharing Persistent Objects Between Python and Javascript\n\u003cimg src=\"Docs/ems_js_py.gif\" /\u003e\n\nInter-language example in [interlanguage.{js,py}](https://github.com/mogill/ems/tree/master/Examples/Interlanguage)\nThe animated GIF demonstrates the following steps:\n* Start Node.js REPL, create an EMS memory\n* Store \"Hello\"\n* Open a second session, begin the Python REPL\n* Connect Python to the EMS shared memory\n* Show the object created by JS is present in Python\n* Modify the object, and show the modification can be seen in JS\n* Exit both REPLs so no programs are running to \"own\" the EMS memory\n* Restart Python, show the memory is still present\n* Initialize a counter from Python\n* Demonstrate atomic Fetch and Add in JS\n* Start a loop in Python incrementing the counter\n* Simultaneously print and modify the value from JS\n* Try to read \"empty\" data from Python, the process blocks\n* Write the empty memory, marking it full, Python resumes execution\n\n## Types of Concurrency\n\u003ctable\u003e\n    \u003ctr\u003e\n      \u003ctd width=\"50%\"\u003e\nEMS extends application capabilities to include transactional memory and\nother fine-grained synchronization capabilities.\n\u003cbr\u003e\u003cbr\u003e\nEMS implements several different parallel execution models:\n\u003cul\u003e\n\u003cli\u003e \u003cB\u003eFork-Join Multiprocess\u003c/B\u003e: execution begins with a single process that creates new processes\n  when needed, those processes then wait for each other to complete.\n\n\u003cli\u003e \u003cB\u003eBulk Synchronous Parallel\u003c/B\u003e: execution begins with each process starting the program at the\n  \u003ccode\u003emain\u003c/code\u003e entry point and executing all the statements\n\n\u003cli\u003e \u003cB\u003eUser Defined\u003c/B\u003e: parallelism may include ad-hoc processes and mixed-language applications\n\u003c/ul\u003e\n\t\t\u003c/td\u003e\n        \u003ctd width=\"50%\"\u003e\n        \u003ccenter\u003e\n    \t\t  \u003cimg height=\"350px\" style=\"margin: 10px;\" src=\"Docs/typesOfParallelism.svg\" type=\"image/svg+xml\"  /\u003e\n            \u003c/center\u003e\n            \u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n    \u003ctd width=\"50%\"\u003e\n        \u003ccenter\u003e\n    \t\t  \u003cimg height=\"350px\" style=\"margin: 10px;\" src=\"Docs/ParallelContextsBSP.svg\" type=\"image/svg+xml\" /\u003e\n        \u003c/center\u003e\n    \u003c/td\u003e\n    \u003ctd\u003e\n        \u003ccenter\u003e\n    \t\t  \u003cimg height=\"350px\" style=\"margin: 10px;\" src=\"Docs/ParallelContextsFJ.svg\" type=\"image/svg+xml\" /\u003e\n        \u003c/center\u003e\n    \u003c/td\u003e\n    \u003c/tr\u003e\n\u003c/table\u003e\n\n\n## Built in Atomic Operations\nEMS operations may performed using any JSON data type, read-modify-write operations\nmay use any combination of JSON data types.\nlike operations on ordinary data.\n\nAtomic read-modify-write operations are available\nin all concurrency modes, however collectives are not\navailable in user defined modes.\n\n- __Atomic Operations__:\n\tRead, write, readers-writer lock, read when full and atomically mark empty, write when empty and atomically mark full\n\n- __Primitives__:\n\tStacks, queues, transactions\n\n- __Read-Modify-Write__:\n\tFetch-and-Add, Compare and Swap\n\n- __Collective Operations__:\n\tAll basic [OpenMP](https://en.wikipedia.org/wiki/OpenMP)\n    collective operations are implemented in EMS:\n    dynamic, block, guided, as are the full complement of static loop scheduling,\n    barriers, master and single execution regions\n\n## Examples and Benchmarks\n\n### [API Documentation](http://mogill.github.io/ems/Docs/reference.html) | [EMS Website](http://mogill.github.io/ems/Docs/index.html)\n\n### Word Counting Using Atomic Operations\n[Word counting example](https://github.com/mogill/ems/tree/master/Examples)\n\nMap-Reduce is often demonstrated using word counting because each document can\nbe processed in parallel, and the results of each document's dictionary reduced\ninto a single dictionary.  This EMS implementation also\niterates over documents in parallel, but it maintains a single shared dictionary\nacross processes, atomically incrementing the count of each word found.\nThe final word counts are sorted and the most frequently appearing words\nare printed with their counts.\n\n\u003cimg height=\"300px\" src=\"Docs/wordcount.svg\" /\u003e\n\nThe performance of this program was measured using an Amazon EC2 instance:\u003cbr\u003e\n`c4.8xlarge (132 ECUs, 36 vCPUs, 2.9 GHz, Intel Xeon E5-2666v3, 60 GiB memory`\nThe leveling of scaling around 16 cores despite the presence of ample work\nmay be related to the use of non-dedicated hardware:\nHalf of the 36 vCPUs are presumably HyperThreads or otherwise shared resource.\nAWS instances are also bandwidth limited to EBS storage, where our Gutenberg\ncorpus is stored.\n\n### Bandwidth Benchmarking\n[STREAMS Example](https://github.com/mogill/ems/tree/master/Examples/STREAMS)\n\nA benchmark similar to [STREAMS](https://www.cs.virginia.edu/stream/)\ngives us the maximum speed EMS double precision\nfloating point operations can be performed on a\n`c4.8xlarge (132 ECUs, 36 vCPUs, 2.9 GHz, Intel Xeon E5-2666v3, 60 GiB memory`.\n\n\u003cimg src=\"Docs/streams.svg\" type=\"image/svg+xml\" height=\"300px\"\u003e\n\n\n### Benchmarking of Transactions and Work Queues\n[Transactions and Work Queues Example](https://github.com/mogill/ems/tree/master/Examples)\n\nTransactional performance is measured alone, and again with a separate\nprocess appending new processes as work is removed from the queue.\nThe experiments were run using an Amazon EC2 instance:\u003cbr\u003e\n\u003ccode\u003ec4.8xlarge (132 ECUs, 36 vCPUs, 2.9 GHz, Intel Xeon E5-2666v3, 60 GiB memory\u003c/code\u003e\n\n#### Experiment Design\nSix EMS arrays are created, each holding 1,000,000 numbers.  During the\nbenchmark, 1,000,000 transactions are performed, each transaction involves 1-5\nrandomly selected elements of randomly selected EMS arrays.\nThe transaction reads all the elements and\nperforms a read-modify-write operation involving at least 80% of the elements.\nAfter all the transactions are complete, the array elements are checked\nto confirm all the operations have occurred.\n\nThe parallel process scheduling model used is *block dynamic* (the default),\nwhere each process is responsible for successively smaller blocks\nof iterations.  The execution model is *bulk synchronous parallel*, each\nprocesses enters the program at the same main entry point\nand executes all the statements in the program.\n`forEach` loops have their normal semantics of performing all iterations,\n`parForEach` loops are distributed across threads, each process executing\nonly a portion of the total iteration space.\n\n\n\u003ctable width=100%\u003e\n\t\u003ctr\u003e\n    \t\u003ctd width=\"50%\"\u003e\n\t    \u003ccenter\u003e\n\t\t\t\u003cimg style=\"vertical-align:text-top;\" src=\"Docs/tm_no_q.svg\" /\u003e\n            \u003cbr\u003e\u003cb\u003eImmediate Transactions:\u003c/b\u003e Each process generates a transaction on integer data then immediately performs it.\n    \t\u003c/center\u003e\n\t    \u003c/td\u003e\n    \t\u003ctd width=\"50%\"\u003e\n\t    \u003ccenter\u003e\n\t\t\t\u003cimg style=\"vertical-align:text-top;\" src=\"Docs/tm_from_q.svg\" /\u003e\n            \u003cbr\u003e\u003cb\u003eTransactions from a Queue:\u003c/b\u003e One of the processes generates the individual transactions and appends\n\t\t\t\tthem to a work queue the other threads get work from.\n                \u003cB\u003eNote:\u003c/b\u003e As the number of processes increases, the process generating the transactions\n\t\t    \tand appending them to the work queue is starved out by processes performing transactions,\n                naturally maximizing the data access rate.\n\t    \u003c/center\u003e\n\t    \u003c/td\u003e\n    \u003c/tr\u003e\n\t\u003ctr\u003e\n    \t\u003ctd width=\"50%\"\u003e\n\t    \u003ccenter\u003e\n\t\t\t\u003cimg style=\"vertical-align:text-top;\" src=\"Docs/tm_no_q_str.svg\"/\u003e\n            \u003cbr\u003e\u003cb\u003eImmediate Transactions on Strings:\u003c/b\u003e Each process generates a transaction appending to\n\t\t\ta string, and then immediately performs the transaction.\n    \t\u003c/center\u003e\n\t    \u003c/td\u003e\n    \t\u003ctd width=\"50%\"\u003e\n        \u003ccenter\u003e\n        \u003cb\u003eMeasurements\u003c/b\u003e\n        \u003c/center\u003e\u003cbr\u003e\n        \u003cb\u003eElem. Ref'd:\u003c/b\u003e Total number of elements read and/or written\n\t\t\u003cbr\u003e\n        \u003cb\u003eTable Updates:\u003c/b\u003e Number of different EMS arrays (tables) written to\n\t\t\u003cbr\u003e\n        \u003cb\u003eTrans. Performed:\u003c/b\u003e Number of transactions performed across all EMS arrays (tables)\n\t\t\u003cbr\u003e\n        \u003cb\u003eTrans. Enqueued:\u003c/b\u003e Rate transactions are added to the work queue (only 1 generator thread in these experiments)\n\t    \u003c/td\u003e\n    \u003c/tr\u003e\n\u003c/table\u003e\n\n\n\n## [Synchronization as a Property of the Data, Not a Duty for Tasks](#Synchronization-Property)\n\n### [API Documentation](http://mogill.github.io/ems/Docs/reference.html) | [EMS Website](http://mogill.github.io/ems/Docs/index.html)\n\nEMS internally stores tags that are used for synchronization of\nuser data, allowing synchronization to happen independently of\nthe number or kind of processes accessing the data.  The tags\ncan be thought of as being in one of three states, _Empty,\nFull,_ or _Read-Only_, and the EMS intrinsic functions\nenforce atomic access through automatic state transitions.\n\nThe EMS array may be indexed directly using an integer, or using a key-index\nmapping from any primitive type.  When a map is used, the key and data\nitself are updated atomically.\n\n\u003ctable \u003e\n    \u003ctr\u003e\n      \u003ctd\u003e\n    \u003ccenter\u003e\n      \u003cimg style=\"width:350px; \"\n\t   src=\"Docs/memLayoutLogical.svg\" type=\"image/svg+xml\" /\u003e\n      \u003cem\u003e    \u003cbr\u003e\u003cbr\u003e\n    EMS memory is an array of JSON values\n        (Number, Boolean, String, Undefined, or Object) accessed using atomic\n        operators and/or transactional memory.  Safe parallel access\n        is managed by passing through multiple gates: First mapping a\n        key to an index, then accessing user data protected by EMS\n        tags, and completing the whole operation atomically.\n    \u003c/em\u003e\n      \u003c/center\u003e\n    \u003c/td\u003e\n    \u003ctd width=\"50%\"\u003e\n      \u003ccenter\u003e\n  \u003cimg style=\"height:270px; \"\n   src=\"Docs/fsmSimple.svg\" type=\"image/svg+xml\" /\u003e\n    \u003cem\u003e    \u003cbr\u003e\u003cbr\u003e EMS Data Tag Transitions \u0026 Atomic operations:\n    F=Full, E=Empty, X=Don't Care, RW=Readers-Writer lock (# of current readers)\n    CAS=Compare-and-Swap, FAA=Fetch-and-Add\u003c/em\u003e\n      \u003c/center\u003e\n    \u003c/td\u003e\n    \u003c/tr\u003e\n\u003c/table\u003e\n\n\n## More Technical Information\n\nFor a more complete description of the principles of operation,\ncontact the author at ems@rotang.com\n\n[ Complete API reference ](https://github.com/mogill/ems/tree/master/Docs/reference.html)\n\n\u003cbr\u003e\n\u003ccenter\u003e\n  \u003cimg src=\"Docs/blockDiagram.svg\" type=\"image/svg+xml\" height=\"300px\" style=\"vertical-align:text-top;\"/\u003e\n\u003c/center\u003e\n\n\n## Installation\n\nBecause all systems are already multicore,\nparallel programs require no additional equipment, system permissions,\nor application services, making it easy to get started.\nThe reduced complexity of\nlightweight threads communicating through shared memory\nis reflected in a rapid code-debug cycle for ad-hoc application development.\n\n### Quick Start with the Makefile\nTo build and test all C, Python 2 and 3, and Node.js targets,\na makefile can automate most build and test tasks.\n\n```sh\ndunlin\u003e make help\n         Extended Memory Semantics  --  Build Targets\n===========================================================\n    all                       Build all targets, run all tests\n    node                      Build only Node.js\n    py                        Build both Python 2 and 3\n\n    py[2|3]                   Build only Python2 or 3\n    test                      Run both Node.js and Py tests\n    test[_js|_py|_py2|_py3]   Run only Node.js, or only Py tests, respectively\n    clean                     Remove all files that can be regenerated\n    clean[_js|_py|_py2|_py3]  Remove Node.js or Py files that can be regenerated\n```\n\n\n### Install via npm\nEMS is available as a NPM Package.  EMS depends on the Node addon API\n(N-API) package.\n\n```sh\nnpm install ems\n```\n\n### Install via GitHub\nDownload the source code, then compile the native code:\n\n```sh\ngit clone https://github.com/mogill/ems.git\ncd ems\nnpm install\n```\n\n\n### Installing for Python\nPython users should download and install EMS git (see above).\nThere is no PIP package, but not due lack of desire or effort.\nA pull request is most welcome!\n\n\n### Run Some Examples\n\nClick here for __[Detailed Examples](https://github.com/mogill/ems/tree/master/Examples)__.\n\nOn a Mac and most Linux\ndistributions EMS will \"just work\", but\nsome Linux distributions restrict access to shared memory.  The\nquick workaround is to run jobs as root, a long-term solution will\nvary with Linux distribution.\n\n\nRun the work queue driven transaction processing example on 8 processes:\n```sh\nnpm run \u003cexample\u003e\n```\n\nOr manually via:\n```sh\ncd Examples\nnode concurrent_Q_and_TM.js 8\n```\n\nRunning all the tests with 8 processes:\n```sh\nnpm run test      # Alternatively: npm test\n```\n\n```sh\ncd Tests\nrm -f EMSthreadStub.js   # Do not run the machine generated script used by EMS\nfor test in `ls *js`; do node $test 8; done\n```\n\n## Platforms Supported\nAs of 2016-05-01, Mac/Darwin and Linux are supported.  A windows port pull request is welcomed!\n\n\n## Roadmap\nEMS 1.0 uses Nan for long-term Node.js support, we continue to\ndevelop on OSX and Linux via Vagrant.\n\nEMS 1.3 introduces a C API.\n\nEMS 1.4 Python API\n\nEMS 1.4.8 Improved examples and documentation\n\nEMS 1.5 Refactored JS-EMS object conversion temporary storage\n\nEMS 1.6 **[This Release]** Updated to replace deprecated NodeJS NAN API with the N-API.\n\nEMS 1.7 **[Planned]** Key deletion that frees all resources.  Replace open hashing with chaining.\n\nEMS 1.8 **[Planned]** Memory allocator based on\n*R. Marotta, M. Ianni, A. Scarselli, A. Pellegrini and F. Quaglia, \"NBBS: A Non-Blocking Buddy System for Multi-core Machines,\" 2019 19th IEEE/ACM International Symposium on Cluster, Cloud and Grid Computing (CCGRID), Larnaca, Cyprus, 2019, pp. 11-20, doi: 10.1109/CCGRID.2019.00011.*\n\nEMS 1.9 **[Planned]** Vectorized JSON indexer.\n\nEMS 1.10 **[Planned]** Support for [persistent main system memory (PMEM)](http://pmem.io/) when\nmultiple processes are supported.\n\nEMS 2.0 **[Planned]** New API which more tightly integrates with\nES6, Python, and other dynamically typed languages languages,\nmaking atomic operations on persistent memory more transparent.\n\n## License\nBSD, other commercial and open source licenses are available.\n\n## Links\n[API Documentation](http://mogill.github.io/ems/Docs/reference.html)\n\n[EMS Website](http://mogill.github.io/ems/Docs/index.html)\n\n[Download the NPM](https://www.npmjs.org/package/ems)\n\n[Get the source at GitHub](https://github.com/mogill/ems)\n\n## About\nJace A Mogill specializes in hardware/software co-design of\nresource constrained computing at both the largest and smallest scales.\nHe has over 20 years experience with distributed, multi-core, FPGA, CGRA, GPU, CPU,\nand custom computer architectures.\n\n###### Copyright (C)2011-2020 Jace A Mogill\n","funding_links":[],"categories":["JavaScript"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmogill%2Fems","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmogill%2Fems","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmogill%2Fems/lists"}