Move.

Допис

Діліться своїми знаннями.

Jeff.
Jeff406
Aug 24, 2025
Питання та відповіді експертів

How does Move handle parallel execution?

Sui supports parallel execution. How does Move code need to be structured to benefit from this feature?

  • Move CLI
  • Move
  • Move Script
5
7
Поділитися
Коментарі
.

Відповіді

7
Matthardy.
Aug 25 2025, 00:19

Sui achieves parallel execution through its object-centric execution model rather than optimistic concurrency like some other blockchains. Move itself doesn’t introduce parallelism automatically; instead, your smart contract design and data layout determine whether transactions can run in parallel.

Here’s how it works and what you need to do:


How Sui Parallel Execution Works

Sui analyzes the input objects for each transaction before execution.

Transactions that do not touch the same objects can execute in parallel.

If two transactions both require mutable access to the same object, they will serialize, not run in parallel.

Immutable reads (shared by many transactions) don’t block parallelism.

Move modules themselves are deterministic and single-threaded; parallelism is achieved at the transaction scheduling level.


How to Structure Move Code for Parallelism

  1. Avoid Hotspots (Shared Objects)

Don’t put all state in one big shared object that everyone writes to (e.g., a global counter).

Instead, use owned objects or dynamic fields so each user or asset has its own state object.

Example:

Bad: Game { players: vector }

Good: Player { ... } objects owned by users.

  1. Use Shared Objects Only When Necessary

Shared objects are needed for global coordination (e.g., an AMM pool).

Minimize mutable fields inside shared objects to reduce contention.

  1. Batch Updates on Owned Objects

If your contract creates many objects, group related actions in one transaction using ProgrammableTransactionBlock.

Fewer transactions → less scheduling overhead.

  1. Leverage Immutable References

If you only need to read from a shared object, take an immutable reference instead of mutable.

Immutable reads don’t block parallel execution.

  1. Separate State by Design

For large systems (like DEX, lending), separate liquidity pools or vaults into their own objects.

This allows trades in Pool A and Pool B to execute concurrently.

5
Коментарі
.
acher.
Aug 24 2025, 23:53

You can take advantage of Sui’s parallel execution by writing Move code that minimizes dependencies on the same shared objects and instead works with distinct owned objects whenever possible. Sui’s runtime executes transactions in parallel when it can prove they don’t touch overlapping objects, so if your module logic consumes, mutates, or returns separate objects (like different NFTs, coins, or workflow states), those transactions can run at the same time without blocking each other. But if you rely too much on a single shared object (like a global counter or central registry), you’ll create contention points that serialize execution. The trick is to design your resources so each user mostly works on their own objects, and only use shared objects when absolutely necessary.

Here’s a simple illustration:

module parallel::example {
    use sui::object::{Self, UID};
    use sui::tx_context::TxContext;
    use sui::transfer;

    struct UserVault has key {
        id: UID,
        balance: u64,
    }

    /// Each user owns their own vault, so updates can run in parallel
    public entry fun create_vault(ctx: &mut TxContext) {
        let vault = UserVault { id: object::new(ctx), balance: 0 };
        transfer::transfer(vault, tx_context::sender(ctx));
    }

    /// Independent top-ups can be executed in parallel because each vault is unique
    public entry fun deposit(vault: &mut UserVault, amount: u64) {
        vault.balance = vault.balance + amount;
    }
}

If instead you stored everyone’s balances in one shared struct, all deposits would compete for the same lock, killing parallelism. The big takeaway is: design your Move objects with fine-grained ownership so unrelated transactions can scale in parallel, while keeping shared state only where absolutely needed (like governance or leaderboards).

2
Коментарі
.
290697tz.
Aug 25 2025, 19:41

Move itself does not execute in parallel; it is a deterministic language. However, Sui’s runtime allows parallel execution of transactions by analyzing object dependencies. The way you structure your Move code determines whether Sui can schedule your transactions in parallel.

Key Principle

Sui uses object-centric concurrency:

If two transactions touch different objects, they can run in parallel.

If they both mutate the same object, they are serialized.


How to Structure Move Code for Parallelism

  1. Use Separate Objects for Independent State

Instead of having a single GlobalState object for everything, break it into smaller objects.

Example: Each user’s balance is stored in their own object, not in a global table.


❌ Bad (Single Shared Object)

struct GlobalCounter has key { value: u64 }

public entry fun increment(counter: &mut GlobalCounter) { counter.value = counter.value + 1; }

Every increment touches the same GlobalCounter → all serialized.


✅ Good (Object Per User)

struct UserCounter has key { id: UID, value: u64 }

public entry fun increment(user_counter: &mut UserCounter) { user_counter.value = user_counter.value + 1; }

Each user owns a different object → parallel execution.


  1. Avoid Global Tables for High-Throughput Paths

Dynamic fields and large maps stored in a single object create hotspots.

Prefer per-object sharding instead.


  1. Leverage Object Transfers Instead of Global Locks

If multiple actors need temporary access to the same resource, transfer ownership instead of mutating a global state.


  1. Immutable Reads Are Parallel-Friendly

Multiple transactions can read the same object in parallel if they don’t mutate it.

Use &T (immutable reference) instead of &mut T when possible.


Gas Implications

Parallel execution does not reduce per-transaction gas, but it increases system throughput.

Transactions that mutate fewer shared objects have lower contention, so they commit faster.


Best Design Pattern

Game, auction, or marketplace apps should use one object per listing or player.

Avoid global counters for IDs; use TxContext::fresh_object_id() or UID instead.

2
Коментарі
.
Tucker.
Aug 25 2025, 19:43

Move itself doesn’t provide built-in parallel execution, but Sui’s execution layer does through object-level dependency analysis. To leverage this, your Move code must be designed to minimize conflicts.


How Parallel Execution Works in Sui

Sui analyzes which objects each transaction reads/writes.

If two transactions write to the same object, they run sequentially.

If they operate on disjoint sets of objects, they can execute in parallel.


How to Structure Move Code for Maximum Parallelism

  1. Design for Object Granularity

Avoid putting all state in a single “global” object.

Instead, use fine-grained objects (e.g., one per user, per asset, or per auction).

Example:

struct UserProfile has key { id: UID, balance: u64 }

Each profile is a separate object, so two users updating their balances won’t block each other.


  1. Avoid Centralized Counters and Maps

A single counter or global map becomes a hotspot because all transactions need &mut access.

Instead, use UID-based IDs from TxContext for unique IDs without a shared counter.


  1. Minimize &mut Access

If your function only needs to read data, use &T instead of &mut T.

Immutable reads don’t create write conflicts, so they can happen in parallel.


  1. Dynamic Fields & Parallelism

Dynamic fields attach key-value pairs to an object.

If multiple transactions modify different keys on the same parent object, they still conflict because the parent object is being mutated.

To avoid this, split dynamic fields across objects if high parallelism is needed.


  1. Transfers Instead of Shared Updates

For temporary ownership (e.g., lending), transfer the object instead of locking a global registry.


Example: Parallel-Friendly Auction Design

❌ Serial Design (One AuctionHouse object)

struct AuctionHouse has key { listings: vector // all auctions here }

Every new listing modifies AuctionHouse, creating a bottleneck.

✅ Parallel Design (One object per auction)

struct Auction has key { id: UID, item: u64, price: u64 }

Now, each auction is independent → multiple bids and listings execute in parallel.


Why This Matters

High TPS dApps (DeFi, GameFi) need sharding by design.

If your code forces all transactions to touch a single object, you lose Sui’s parallel advantage.

2
Коментарі
.
SuiLover.
Aug 25 2025, 20:33

You can take advantage of Sui’s parallel execution by writing Move code that minimizes dependencies on the same shared objects and instead works with distinct owned objects whenever possible. Sui’s runtime executes transactions in parallel when it can prove they don’t touch overlapping objects, so if your module logic consumes, mutates, or returns separate objects (like different NFTs, coins, or workflow states), those transactions can run at the same time without blocking each other. But if you rely too much on a single shared object (like a global counter or central registry), you’ll create contention points that serialize execution. The trick is to design your resources so each user mostly works on their own objects, and only use shared objects when absolutely necessary.

Here’s a simple illustration:

module parallel::example { use sui::object::{Self, UID}; use sui::tx_context::TxContext; use sui::transfer;

struct UserVault has key {
    id: UID,
    balance: u64,
}

/// Each user owns their own vault, so updates can run in parallel
public entry fun create_vault(ctx: &mut TxContext) {
    let vault = UserVault { id: object::new(ctx), balance: 0 };
    transfer::transfer(vault, tx_context::sender(ctx));
}

/// Independent top-ups can be executed in parallel because each vault is unique
public entry fun deposit(vault: &mut UserVault, amount: u64) {
    vault.balance = vault.balance + amount;
}

} If instead you stored everyone’s balances in one shared struct, all deposits would compete for the same lock, killing parallelism. The big takeaway is: design your Move objects with fine-grained ownership so unrelated transactions can scale in parallel, while keeping shared state only where absolutely needed (like governance or leaderboards).

2
Коментарі
.
shamueely.
Aug 25 2025, 00:17

In Sui, parallel execution works because transactions that touch different objects can be processed at the same time without conflicts. Move helps you benefit from this by making you structure your code around object ownership. If your function only reads or writes to objects owned by the caller, or to uniquely borrowed references, those transactions can run in parallel with others. But if multiple transactions try to mutate the same shared object, Sui will serialize them to avoid conflicts. That means you should design modules so that each user’s state is stored in separate objects rather than a single shared one. For example, instead of one big global registry that everyone writes to, create individual objects (like accounts, vaults, or NFTs) that belong to users. This reduces contention and maximizes concurrency.

Here’s a simple illustration:

module bank::vault {
    use sui::object::{Self, UID};
    use sui::tx_context::{Self, TxContext};
    use sui::transfer;

    struct Vault has key {
        id: UID,
        balance: u64,
    }

    public entry fun create_vault(ctx: &mut TxContext) {
        let vault = Vault { id: object::new(ctx), balance: 0 };
        transfer::transfer(vault, tx_context::sender(ctx));
    }

    public entry fun deposit(v: &mut Vault, amount: u64) {
        v.balance = v.balance + amount;
    }
}

Each user owns their own Vault. Since no two deposits touch the same object, Sui can execute them in parallel. But if you built a single SharedVault that everyone deposits into, those transactions would be forced into sequential execution.

So the best practice is to design your code around independent, owned objects when you want scale, and use shared objects only when global coordination is absolutely needed.

1
Коментарі
.

Ви знаєте відповідь?

Будь ласка, увійдіть та поділіться нею.

Move is an executable bytecode language used to implement custom transactions and smart contracts.

242Пости541Відповіді
Sui.X.Peera.

Зароби свою частку з 1000 Sui

Заробляй бали репутації та отримуй винагороди за допомогу в розвитку спільноти Sui.

Кампанія винагородСерпень