Skip to content

ertgrulll/dyno

Repository files navigation

Dyno

pub package GitHub issues Maintenance

Creates an isolation pool and manages it dynamically to run a closure isolated.

Tip: running heavy computations isolated prevents lags in application. An isolate has it's own memory and event loop.

Features

➡️ It doesn't create isolates for every process, communicates bidirectionally with isolations.

➡️ Has a load balancer, creates and kills isolates automatically according to load.

➡️ Allows the use of certain isolate for certain processes.

➡️ Lightweight, only 171 lines of code.

Getting started

Add dependency to pubspec.yaml:

dyno: ^0.0.4

Usage

  • Import dyno,
import 'package:dyno/dyno.dart' as dyno;
  • prepare isolates before use. (This an optional step)

Dyno creates isolates as needed, but preparing speeds up first run. You can prepare dyno on the splash screen or any other desired place.

dyno.prepare(single: false);

prepare creates two isolate by default, but creates one when single parameter is set to true.

  • Running isolated,

    • Closure, use with caution, may capture more then it's need and may cause exception.
    final result = await dyno.run<String>(() {
      // Some complex process.
      return 'result of process';
    });
    • Static, top level or parameterized function(can accept max 4 parameters).
    Future<MyObject> myFunc(String param1) async {
      final myResult = await doSomething(param1);
    
      return myResults;
    }
    final result = await dyno.run<MyObject>(myFunc, param1: 'myParam');

    or

    final result = await dyno.run<MyObject>((String param1) async {
      final myResult = await doSomething(param1);
    
      return myResults;
    }, param1: 'myParam');

Isolator Reserve

Isolator reserving useful for processes that require initialization. Isolates don't share memory, once you initialize a class or a package in the main isolate, you can't use it in another isolate without initializing it for isolation. Dyno excludes reserved isolators from automatic clean and keeps them alive until unreserve called.

An example use case may be cache supported api requests. Reserve an isolate, initialize your local database package(tested with Hive) and send all requests, encode/decode jsons, save it to the local database in reserved isoalator and return result.

Reserve an isolator and initialize required classes/packages inside it,

await dyno.reserve('my_api_isolator');
dyno.run(initializeMyLocalDb, key: 'my_api_isolator');

And use reserved isolator later by sending key to the run method,

dyno.run<Profile>((String userId) async {
  final profile = await getProfileFromMyRemoteDb(userId);
  await MyCache.add(profile);

  return profile;
}, param1: 'myUserId', key: 'my_api_isolator');

When you want to let dyno to clean reserved isolator, call dyno.unreserve('my_api_isolator').


Isolator Limit

When the run method is called, Dyno creates a new isolator if all the created isolators are in use. If run is called repeatedly, the isolation count can increase very quickly, which can block the UI builds.

The default limit is three if the number of host device processors is less than three, otherwise the number of processors. When isolator count reaches to the limit, Dyno runs on the least loaded isolator. Limit can be changed by calling limit method.

  dyno.limit(2);

Maintainer

Hey, I'm Ertuğrul, please feel free to ask any questions about this tool. If you find Dyno useful, you can hit the like button and give a star to project on Github to motivate me or treat me with coffee.