Giter VIP home page Giter VIP logo

gwasm-runner's Introduction

gwasm-runner Build Status

Command line tool for running gWasm compatible apps locally, via Golem Unlimited or via Brass Golem.

It introduces minimalistic gwasm dispatcher API that resembles map-reduce paradigm. This API with only three operations:

  1. split - divide the problem into subproblems.
  2. execute - performs computation for all subproblems independently.
  3. merge - collect all computation results and formulate final result.

enables developers to easily implement applications and run them on top of the Golem Unlimited and also on Brass Golem 0.21 and later.

building from sources

Having below prereqs just invoke

cargo build --release

prerequisites

You need to have C compiler, Python 2, AutoConf 2.13 and yasm

on Ubuntu (16.04+)

sudo apt-get install clang-6.0 autoconf2.13 yasm

on macOS

xcode-select --install

Use Homebrew to install Python 2, AutoConf 2.13 and Yasm:

brew install python@2 [email protected] yasm
# remove newer version of autoconf
brew unlink autoconf
# and use 2.13 instead
ac=`which autoconf213` && sudo ln -s "$ac" "${ac%213}"

Running a WASM binary

The first step here is obtaining a WASM binary compatible with the runner. This means that the binary must conform to the runner's split-execute-merge API. A list of compatible binaries can be found in the wasm-store repository. Of course, you can also create your own program. As our example we're going to use mandelbrot, a Mandelbrot fractal visualiser.

Running on the Golem network

Using gwasm-runner, you can execute the WASM binary in the Golem network, taking advantage of parallelism by splitting the work between multiple providers.

To create a task you will need to have an instance of Golem (version 0.21+) running locally on your machine. This instance will act as a requestor within the Golem network. Assuming that we want to run the mandelbrot example, issue the below command:

./gwasm-runner /path/to/mandelbrot.wasm --backend=Brass -- 1000 1000 4

Let's take a closer look at that command:

  • The first argument to the runner is the path to the WASM binary. Please note that the runner expects the corresponding .js file to be present in the same directory as the WASM binary.
  • Brass stands for Brass Golem, the name for the current iteration of the Golem project.
  • The parameters after -- are passed directly to the WASM program, therefore they are app-specific. In the case of the mandelbrot example, the first two numbers (1000 1000) are the width and height of the output image. The last number (4) is the subtask count, which determines the number subtasks we want to split our work into.

Should you need to change the default configuration for the runner (e.g. whether to use Ethereum's mainnet or testnet), there is an option to use a JSON configuration file. By default, the following values are used when creating a Golem task:

{
    "data_dir": "/home/user/.local/share/golem/default",
    "address": "127.0.0.1:61000",
    "budget": 1.0,
    "name": "gwasm-task",
    "net": "testnet",
    "subtask_timeout": "00:10:00",
    "task_timeout": "00:30:00"
}

To override the default values you will need to create your own, local configuration file. The path to this file depends on your operating system, here are examples for each platform:

  • Linux: $HOME/.config/g-wasm-runner/brass/config.json
  • MacOS: $HOME/Library/Application Support/g-wasm-runner/brass/config.json
  • Windows: C:\Users\<USER_NAME>\AppData\Roaming\Golem Factory\g-wasm-runner\brass\config.json

As for the contents, you can copy the JSON object shown above and modify its fields as required. The runner will print its currently used configuration upon start-up.

gwasm-runner's People

Contributors

etam avatar filipgolem avatar kmazurek avatar macil avatar nieznanysprawiciel avatar prekucki avatar stranger80 avatar tworec avatar

Stargazers

 avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

gwasm-runner's Issues

gwasm-dispatcher license

Is gwasm-dispatcher meant to be covered by the GPLv3 LICENSE file in the root of the repo? If it's GPLv3 and if including gwasm-dispatcher is necessary to make a webassembly binary that runs on Golem, then I believe any webassembly binaries submitted to Golem using it would need to have their whole source be open and be GPLv3, which I'm assuming is not intended. Using a more permissive license like MIT or Apache 2 specifically for the part that people build into their wasm binaries would avoid this.

Add confirmation step before running significant tasks

Once the program is started, a confirmation step should be shown for tasks which are significant (i.e. may have financial consequences for the user and/or affect a larger network).
As part of this change, a -y flag should also be added to the runner to allow for skipping the confirmation altogether.

gwasm-api docs

  • Write cargo docs.
  • Write small examples & link tutorial
  • API as 0.1 in crates.io

[Api] Split

  • buid task manifest
  • dump lobs to files in execution workdir

gwasm-runner hungs up on High Sierra

gwasm-runner falls into an endless loop within split step in both Local and Golem Brass backends. It uses 100% of a single CPU core.

I'm using it under

  • macOS 10.13.6 and
  • Rust 1.37.0 (eae3437df 2019-08-13)
  • and gwasm-runner from master (53f4627)
kinneret:~/git/gwasm-runner master (53f4627)$ ./target/release/gwasm-runner ../mandelbrot/target/wasm32-unknown-emscripten/release/mandelbrot.wasm --backend Brass -- 1000 1000 4
[2019-11-13T16:07:03Z INFO  gwasm_runner::brass_runner] Working directory: /Users/tworec/Library/Caches/g-wasm-runner/brass/84d3e0e9-1d3b-469f-bde9-41d6e1d66f31
[2019-11-13T16:07:03Z INFO  gwasm_runner::brass_runner] Using GolemConfig {
    address: "127.0.0.1:61011",
    bid: 1.0,
    data_dir: "/Users/tworec/Library/Application Support/golem/b0.22req",
    name: "gwasm-task",
    net: TestNet,
    task_timeout: Timeout(
        00:30:00,
    ),
    subtask_timeout: Timeout(
        00:10:00,
    ),
}
[2019-11-13T16:07:03Z INFO  sp_wasm_engine::sandbox::engine] Initializing SpiderMonkey engine
[2019-11-13T16:07:03Z INFO  sp_wasm_engine::sandbox] Setting exec args [ 'split', '/task_dir/', '1000', '1000', '4' ]
^C
kinneret:~/git/gwasm-runner master (53f4627)$ ./target/release/gwasm-runner ../mandelbrot/target/wasm32-unknown-emscripten/release/mandelbrot.wasm -- 1000 1000 1
[2019-11-13T16:09:09Z INFO  sp_wasm_engine::sandbox::engine] Initializing SpiderMonkey engine
work dir: /Users/tworec/Library/Caches/g-wasm-runner/local/40b3de66-f247-44fc-b838-d50af4a7b3c8/split
[2019-11-13T16:09:09Z INFO  sp_wasm_engine::sandbox] Setting exec args [ 'split', '/task_dir/', '1000', '1000', '1' ]
^C

[Api] Execute

  • Parse manifest.
  • Build output files.
  • Serialize output.

Errors out on macOS with dangling symlinks in root

I've noticed that if there is a dangling symlink present in the mapped/overlaid directory (as part of the HostFS set up in golemfactory/sp-wasm, gwasm-runner will fail with a rather cryptic error message.

After some prodding, I've managed to narrow the surface down to this bit of code in golemfactory/sp-wasm:

impl INode for Arc<DirFsInode> {
    type Stream = File;

    fn lookup(&self, name: &str) -> io::Result<Option<Self>> {
        let node = match name {
            "." => Some(self.clone()),
            ".." => Some(
                self.parent
                    .as_ref()
                    .map(Clone::clone)
                    .unwrap_or_else(|| self.clone()),
            ),
            _ => {
                let lookup_path = self.lookup_path.join(name);
                if lookup_path.exists() {
                    let m = lookup_path.metadata()?;

                    Some(Arc::new(DirFsInode {
                        lookup_path,
                        m,
                        parent: Some(self.clone()),
                    }))
                } else {
                    None
                }
            }
        };
        Ok(node)
    }
...
}

and in particular

            _ => {
                let lookup_path = self.lookup_path.join(name);
                if lookup_path.exists() {
                    let m = lookup_path.metadata()?;

                    Some(Arc::new(DirFsInode {
                        lookup_path,
                        m,
                        parent: Some(self.clone()),
                    }))
                } else {
                    None
                }
            }

in this bit, if we hit a dangling symlink, according to docs, lookup_path.exists returns false, and hence, this fn will return None which as a result causes errors later on down the line when, I believe, we try to mount the /.

[Api] Merge

  • Parses manifest for each subtask
  • Parses the output of each subtask

Invalid task order in merge

test

gwasm-runner -b Golem target/wasm32-unknown-emscripten/release/mandelbrot.wasm 1000 1000 5

Result

out

On local

gwasm-runner -vv -b local target/wasm32-unknown-emscripten/release/mandelbrot.wasm 1000 1000 5

out

Improve configuration for Brass backend

Description

Currently, Brass tasks are configured using a single JSON file. This file includes fields both related to the running Golem instance (e.g. address, Ethereum network) as well as specific to the task being created (task and subtask timeouts, task budget).

This setup proves to be impractical for running tasks with varying parameters. A more flexible approach would be to allow for passing task parameters in the call to gwasm_runner. The Golem Unlimited backend already uses an URL to define both node and task configuration.

Technical details

To run a Brass task, the following parameters are used (as defined in the config file along with default values):

{
    "data_dir": "/home/user/.local/share/golem/default",
    "address": "127.0.0.1:61000",
    "budget": 1.0,
    "name": "gwasm-task",
    "net": "testnet",
    "subtask_timeout": "00:10:00",
    "task_timeout": "00:30:00"
}

Having the data dir and network to run on we can obtain the node's address and port by reading its app_cfg.ini file. The task's name can default to the name of the WASM binary. In many cases the default path to the data dir will also be sufficient.

Proposed solution

Instead of a configuration file the Brass backend could use an URL passed directly to gwasm-runner. Example of a possible URL:
golem:///home/user/custom-datadir?net=mainnet&budget=5.0&task_timeout=00:15:00&subtask_timeout=00:05:00

Requirements:

  • Sensible defaults for all required values with an ability to overwrite them if necessary (including data dir path).
  • Using values from a set of predefined environment variables if they are present.

Workdir cleanup

  1. The working runner should create lockfile for the current working dir.
  2. On new workdir allocation, it should check if there any free working dirs to remove. (Cleanup should happen in background).

Useage of non-existent `mkdir -f` flag in runner-update script

The runner-update script referenced here in the gWASM quick start guide incorrectly invokes mkdir -f here which is causing the following error output:

[jacobseth@localhost code]$ curl -sSf https://golemfactory.github.io/gwasm-runner/runner-update.sh | bash
-== GOLEM GWASM runner DEV Update ==-
which: no gwasm-runner in (/home/jacobseth/code/bin ... )
mkdir: invalid option -- 'f'
Try 'mkdir --help' for more information.
installing to /home/jacobseth/.cargo/bin/gwasm-runner
download gwasm-runner-linux-0.3.1.tar.gz   [ done ] 
installing to /home/jacobseth/.cargo/bin/gwasm-runner    [ done ] 

Oddly the file it's attempting to interact with $BASE_PATH isn't referenced beyond this call so I imagine its inclusion is erroneous. This was encountered on fedora 30.

Add support for specifying task budget

Golem version 0.22 has introduced a new marketplace for WASM tasks. Payments to the providers are now based on their CPU usage during computations, as well as on the overall task's budget.
This means that we need to be able to specify the overall GNT budget for a tasks created by gwasm-runner.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.