Workload Configuration

HH·2022년 1월 9일
0

Hyperledger Caliper

목록 보기
11/12

Workload Configuration

개요


Workload Module은 TX를 구성하고 제출하는 역할을 하기 때문에 캘리퍼 벤치마크의 핵심이다. 따라서 Workload Module은 비즈니스, 벤치마크, 또는 사용자 행위에 관련된 로직을 구현한다. Workload Module을 주어진 순간에 제출할 TX의 종류를 결정하는, 에뮬레이트된 SUT 클라이언트의 두뇌로 생각하자.

Workload Module 구현


Workload Module은 특정 API를 export하는 Node.js 모듈이다. 구현에 대한 추가 제한이 없으므로 (추가 임의 컴포넌트를 사용하는) 임의의 로직을 구현할 수 있다.

API


Workload Module은 캘리퍼의 다른 플러그형 모듈들과 마찬가지로 factory function들을 통해 로드된다. 따라서 워크로드 모듈 구현은 반드시 createWorkloadModule라고 이름 붙여진 단일 factory function을 export해야 한다:

/**
 * workload module의 새 인스턴스 생성
 * @return {WorkloadModuleInterface}
 */
function createWorkloadModule() {
    return new MyWorkload();
}

module.exports.createWorkloadModule = createWorkloadModule;

이 factory function은 반드시 WorkloadModuleInterface 클래스를 구현하는 인스턴스를 반환해야 한다. 완전한 구현은 예시를 참고하자.

이 인터페이스는 아래 세가지 비동기 함수를 포함한다:

initializeWorkloadModule


initializeWorkloadModule 함수는 각 라운드 전에 워커 프로세스에 의해 호출되어 모듈에 아래 컨텍스트 인수들(contextual arguments)을 제공한다:
1. workerIndex (Number) 워크로드 모듈을 인스턴스화하는 워커의 인덱스이다. 0부터 시작한다(0-based index)
2. totalWorkers (Number) 라운드에 참여하는 총 워커의 수이다.
3. roundIndex (Number) 현재 실행되는 라운드의 인덱스이다. 0부터 시작한다.
4. roundArguments (Object) 사용자가 벤치마크 구성 파일을 통해 라운드에 제공하는 인수들이다.
5. sutAdapter (BlockchainConnector) 기반 SUT의 커넥터이다.
6. sutContext (Object) SUT 커넥터에서 제공하는 커스텀 컨텍스트 오브젝트이다.

이 함수는 벤치마크 구성 파일에서 제공된 워크로드 모듈 인수의 유효성을 검증하기 좋은 위치이다. 또한 나중에 submitTransaction 함수에서 TX 컨텐츠를 빠르게 어셈블링하기 위해 필요한 모든 전처리를 여기서 수행하는 것이 좋다.

submitTransaction


submitTransaction함수는 워크로드 생성의 중추이다. rate controller가 다음 TX를 활성화 할 때마다 워커 프로세스가 이 함수를 호출한다. 따라서 고빈도(high frequency) 스케줄링 설정을 따라가기 위해서는 이 함수 구현을 가능한 한 효율적으로 유지하는 것이 중요하다.

이 함수에는 어떤 파라미터도 필요하지 않다. 하지만 이 함수는 커넥터 API를 통해 TX를 제출해야 하는 책임이 있다.

cleanupWorkloadModule


cleanupWorkloadModule함수는 라운드가 끝날 때 호출된다. 워크로드 구현에 필요한 모든 리소스 정리에 사용될 수 있다.

Simple base class


인터페이스를 직접 구현할 수도 있지만, 캘리퍼는 필요한 인터페이스를 구현하고 몇 가지 일반적인 하우스키핑 작업을 수행하는 simple utility base class를 제공한다. 따라서 WorkloadModuleBase 클래스를 상속하면 더 간단한 구현이 가능하다.

base class는 아래 유틸리티들을 제공한다:

  • initializeWorkloadModule 함수의 파라미터와 일치하는 생성자에서 인스턴스 변수를 생성한다.
  • initializeWorkloadModule 함수에 대한, 받은 인수를 인스턴스 변수에 저장하는 구현을 제공한다.
  • cleanupWorkloadModule 함수에 대한 no-op 구현을 제공한다.

base class를 상속할 경우 사용자는 submitTransaction 함수만 구현하면 된다. 추가적으로, 필요하다면 초기화 로직을 extend하거나 override할 수 있다.

예시


아래는 워크로드 모듈 구현(WorkloadModuleBase 구현과 거의 동일하다)의 완성된 (임의 샘플) 예시이다:

'use strict';

const { WorkloadModuleInterface } = require('@hyperledger/caliper-core');

class MyWorkload extends WorkloadModuleInterface {
    constructor() {
        super();
        this.workerIndex = -1;
        this.totalWorkers = -1;
        this.roundIndex = -1;
        this.roundArguments = undefined;
        this.sutAdapter = undefined;
        this.sutContext = undefined;
    }
    
    async initializeWorkloadModule(workerIndex, totalWorkers, roundIndex, roundArguments, sutAdapter, sutContext) {
        this.workerIndex = workerIndex;
        this.totalWorkers = totalWorkers;
        this.roundIndex = roundIndex;
        this.roundArguments = roundArguments;
        this.sutAdapter = sutAdapter;
        this.sutContext = sutContext;
    }
    
    async submitTransaction() {
        let txArgs = {
            // "mycontract"를 위한 TX arguments
        };

        return this.sutAdapter.invokeSmartContract('mycontract', 'v1', txArgs, 30);
    }
    
    async cleanupWorkloadModule() {
        // NOOP
    }
}

function createWorkloadModule() {
    return new MyWorkload();
}

module.exports.createWorkloadModule = createWorkloadModule;

utility base class를 사용한 보다 단순한 구현은 아래와 같다:

'use strict';

const { WorkloadModuleBase } = require('@hyperledger/caliper-core');

class MyWorkload extends WorkloadModuleBase {
    async submitTransaction() {
        let txArgs = {
            // TX arguments for "mycontract"
        };

        return this.sutAdapter.invokeSmartContract('mycontract', 'v1', txArgs, 30);
    }
}

function createWorkloadModule() {
    return new MyWorkload();
}

module.exports.createWorkloadModule = createWorkloadModule;

Workload Module 구성


주어진 라운드에 워크로드 모듈을 사용하려면 벤치마크 구성 파일에서 해당 모듈을 참조하기만 하면 된다.

  1. test.rounds[i].workload.module 속성을 워크로드 모듈 파일 경로로 설정한다. 이 경로는 절대경로이거나 구현된 워크스페이스 경로에 대한 상대경로일 수 있다. 또한 이 속성을 퍼블리시된 워크로드 모듈의 패키지 이름으로 지정할 수 있다. 하지만 이 경우에는 해당 모듈을 먼저 설치해야 한다.
  2. 모듈이 여러 설정들을 지원한다면, test.rounds[i].workload.arguments 속성 오브젝트를 그에 따라 설정한다. 이것이 초기화 시 모듈에 전달될 것이다.

팁 & 트릭


아래 어드바이스는 워크로드 모듈 구현을 향상시키는 데 도움이 될 것이다.
1. (코어 캘리퍼 모듈을 포함해) 모든 Node.js 모듈을 코드에서 사용할 수 있다. 모듈화는 구현을 깔끔하고 관리하고 쉽도록 유지하기 위해 중요하다.
2. 서드 파티 모듈을 사용한다면 그것들이 워크로드 모듈에서 사용가능하도록 만드는 것은 개발자가 직접 작업해야 한다(your responsibility). 일반적으로 캘리퍼 시작 전에 모듈 디렉토리에서 npm install호출이 필요하다.
3. 캘리퍼는 로깅이나 런타임 구성와 같은 몇몇 코어 유틸리티를 편의성을 위해 제공하고 있다. 바퀴를 재발명하지 말고 이것들을 사용하자.
4. submitTransaction function은 워커의 워크로드 생성 루프의 hot path에 있다. 계산 집약적인 작업을 조심스럽게 수행해야 한다. 이것이 TXs의 스케줄링 정확도를 떨어트릴 수 있다. 그 대신 initializeWorkloadModule에서 값비싼 전처리 작업을 수행할 수 있다.

라이선스

The Caliper codebase is released under the Apache 2.0 license. Any documentation developed by the Caliper Project is licensed under the Creative Commons Attribution 4.0 International License. You may obtain a copy of the license, titled CC-BY-4.0, at http://creativecommons.org/licenses/by/4.0/.

0개의 댓글