Rust
Pinocchio for Dummies

Pinocchio for Dummies

Продуктивність

Хоча багато розробників звертаються до Pinocchio для детального контролю над полями облікових записів, його справжня сила полягає в забезпеченні максимальної продуктивності.

У цьому розділі ми розглянемо практичні стратегії для досягнення оптимальної ефективності у ваших програмах Solana.

Superfluous Checks

Розробники часто додають додаткові обмеження для облікових записів з міркувань безпеки, але це може створювати непотрібні накладні витрати. Важливо розрізняти необхідні та надлишкові перевірки.

Наприклад, коли просто читаєте з Token Account або Mint, десеріалізація та валідація необхідні. Але якщо ці самі облікові записи пізніше використовуються в CPI (Cross-Program Invocation), будь-яка невідповідність або помилка призведе до збою інструкції в цей момент. Таким чином, попередні перевірки можуть бути надлишковими.

Аналогічно, перевірка "власника" токен-акаунта часто є зайвою; особливо якщо обліковий запис контролюється PDA (Program Derived Address). Якщо власник неправильний, CPI не вдасться через недійсні сіди. У випадках, коли переказ не виконується через PDA, вам слід зосередитися на перевірці отримувача, особливо при внесенні коштів на рахунок, контрольований PDA, оскільки інтереси відправника узгоджені з інтересами програми.

Розглянемо приклад Escrow:

...

Associated Token Program

Associated Token Accounts (ATA) зручні, але мають вартість продуктивності. Уникайте примусового їх використання, якщо це не є абсолютно необхідним, і ніколи не вимагайте їх створення в логіці ваших інструкцій. Для більшості сценаріїв шаблон init-if-needed додає непотрібну складність і використання ресурсів (як у інструкціях Amm, які складаються маршрутизаторами на кшталт Jupiter).

Якщо ваша програма покладається на ATA, переконайтеся, що вони створені зовнішньо. У вашій програмі перевіряйте їхню правильність, безпосередньо виводячи очікувану адресу таким чином:

rust
let (associated_token_account, _) = find_program_address(
    &[
        self.accounts.owner.key(),
        self.accounts.token_program.key(),
        self.accounts.mint.key(),
    ],
    &pinocchio_associated_token_account::ID,
);

Мінімізуючи непотрібні перевірки та вимоги до облікових записів, ви зменшуєте обчислювальні витрати та оптимізуєте виконання вашої програми, розкриваючи повний потенціал продуктивності нативної розробки на Solana.

Додавання перевірок для раннього завершення інструкції має свої переваги, оскільки спожиті обчислювальні одиниці будуть точно нижчими. Тому подумайте, чи інструкція буде в основному використовуватися з прапорцями на кшталт { skipPreflight: true }.

Perf Flag

Прапорці функцій Rust надають потужний спосіб умовної компіляції коду, дозволяючи вмикати та вимикати функціональність для різних профілів збірки, таких як розробка, тестування або максимальна продуктивність у виробництві.

Це особливо корисно в програмах Solana, де кожна обчислювальна одиниця має значення.

Налаштування прапорців функцій

Прапорці функцій визначаються у вашому файлі Cargo.toml у розділі [features]. Наприклад, ви можете захотіти прапорець perf, який вмикає оптимізацію продуктивності шляхом вимкнення логування та додаткових перевірок:

 
[features]
default = ["perf"]
perf = []

Тут функція perf увімкнена за замовчуванням, але ви можете перевизначити її під час збірки або тестування.

Використання прапорців функцій у коді

Ви можете використовувати атрибути умовної компіляції Rust для включення або виключення коду на основі активної функції. Наприклад:

rust
pub fn process(ctx: Context<'info>) -> ProgramResult {
    #[cfg(not(feature = "perf"))]
    sol_log("Create Class");
    Self::try_from(ctx)?.execute()
}

Більшість програм повертають назву інструкції як лог, щоб полегшити налагодження та переконатися, що викликається правильна інструкція.

Однак це дорого коштує і насправді не потрібно, окрім як для покращення читабельності в оглядачі та для полегшення налагодження.

rust
#[cfg(not(feature = "perf"))]
if name.len() > MAX_NAME_LEN {
    return Err(ProgramError::InvalidArgument);
}

Інший приклад — це надлишкові перевірки, які ми обговорювали раніше.

Якщо ми знаємо, що наша інструкція безпечна без цих перевірок, ми не повинні робити їх стандартними, а натомість сховати їх за прапорцем.

У цьому прикладі ми створили прапорець perf, щоб вказати, що якщо ми хочемо, щоб програма була максимально продуктивною, ми повинні використовувати прапорець perf під час її компіляції.

Збірка з різними прапорцями

Щоб зібрати вашу програму з функцією perf або без неї, використовуйте:

  • З оптимізацією продуктивності (за замовчуванням):
 
cargo build-bpf
  • З додатковими перевірками та логуванням:
 
cargo build-bpf --no-default-features

Цей підхід дозволяє підтримувати єдину кодову базу, яку можна налаштувати для безпеки розробки або швидкості в продакшені, просто перемикаючи прапорець функції.

Blueshift © 2025Commit: 6d01265