전공 - 소프트웨어공학 과제

과제 내용

  • 정수 값(데이터)을 저장한다.
  • 데이터를 발생시키는 쓰레드와 데이터를 꺼내는 쓰레드에 의해 사용된다.
  • 발생된 데이터는 다음 데이터 발생 전까지 저장되지 않으면 사라진다.
  • 데이터 발생, 소모 주기가 정규분포를 형성하도록 구현하여 시뮬레이션 진행
  • 데이터 발생기에서는 데이터를 0, 1, 2, 3, 4, 5, 6, …… 형태로 생한다. (데이터 소모기에서는 데이터가 누락되었는지 여부를 바로 파악가능)
  • 여러 가지 변수(버퍼의 크기, 쓰레드 실행주기의 분포)에 따른 문제점 분석

Ringbuffer

void rtos::RingBuffer::put(int item) noexcept;`

버퍼에 정수 data를 저장한다. 빈 공간이 없는 경우 새로운 데이터를 쓰지 않고 넘어간다.(no-op)

void rtos::RingBuffer::putWithoutOverride(int item) noexcept;`

버퍼에 정수 data를 저장한다. 빈 공간이 없는 경우 빈 공간이 생길때까지 기다린다.

void rtos::RingBuffer::get();`

버퍼에서 값을 꺼낸다(FIFO). 버퍼가 비어 있는 경우 EmptyBufferReadException 예외를 던진다.

void rtos::RingBuffer::getFromNotEmptyBuffer() noexcept;`

버퍼에서 값을 꺼낸다. 버퍼가 비어 있는 경우 값이 저장될때까지 기다린다.

Simulation

Real-Time system에서 ringbuffer가 사용되는 상황을 재현

Requirements

  1. 생성기(producer)와 처리기(consumer)가 독립된 쓰레드에서 동일한 버퍼에 접근한다.
  2. 생성기와 처리기 실행주기를 설정할 수 있어야 한다.
  3. 생성기의 동작을 stdout에 출력한다.

설계

testcase_diagram

화살표의 방향은 데이터가 이동하는 방향

  • producer - 일정 주기마다 데이터를 생성하고 버퍼에 저장한다.
  • consumer - 일정 주기마다 데이터를 버퍼에서 꺼낸다.
  • observer - msgq에 저장된 메세지를 stdout에 출력한다.
  • msgq - 데이터가 생성, 처리될때의 timestamp와 처리된 내용을 저장하는 큐
  • msgqLock - msgq에 할당된 mutex

변수 설정

아래의 설정값을 변경하여 측정값을 얻을 수 있다. 생성기와 처리기를 여러 개 실행할 수 있도록 구현하였다.

/**
 * @brief 시뮬레이션 변수
 */
namespace SIMUL_PARAM {

    const int BUFFER_SIZE = 10;

    const double PROD_SIGMA = 6.0; // 데이터 발생주기 표준편차
    const double CONS_SIGMA = 1.0; // 데이터 처리주기 표준편차

    const int DURATION = 1000; // 시뮬레이션 진행 시간 (milliseconds)
    const int DURATION_MARGIN = 20;
    const int SAMPLE_SIZE = 50; // 정규분포를 이루는 주기의 개수

    // testcase a
    const period TA_PROD_PERIOD = 50; // 데이터 평균발생주기 (milliseconds)
    const period TA_CONS_PERIOD = 40; // 데이터 평균처리주기 (milliseconds)
    const int TA_PROD_NUM = 1;
    const int TA_CONS_NUM = 1;

    // testcase b
    const period TB_PROD_PERIOD = 20; // 데이터 평균발생주기 (milliseconds)
    const period TB_CONS_PERIOD = 20; // 데이터 평균처리주기 (milliseconds)
    const int TB_PROD_NUM = 1;
    const int TB_CONS_NUM = 1;

    // testcase c
    const period TC_PROD_PERIOD = 50; // 데이터 평균발생주기 (milliseconds)
    const period TC_CONS_PERIOD = 60; // 데이터 평균처리주기 (milliseconds)
    const int TC_PROD_NUM = 5;
    const int TC_CONS_NUM = 1;

    const size_t MSG_LENGTH = 80;

}; // SIMUL_PARAM

실행

  • case a) 데이터 평균 처리 속도 > 데이터 평균 발생 속도

    case_a

    결과
    시뮬레이션 진행 시간: 1000ms
    버퍼 크기: 10
    표본 크기: 50
    Producer의 데이터 생성주기 평균: 50ms
    Consumer의 데이터 소비주기 평균: 40ms
    Producer의 데이터 생성주기 표준편차: 6.00
    Consumer의 데이터 소비주기 표준편차: 1.00
    빈 버퍼에 접근한 비율: 25.00% (처리기는 25% 확률로 빈 버퍼에 접근하게 된다)
    손실된 데이터 비율: 0.00%

  • case b) 데이터 평균 처리 속도 = 데이터 평균 발생 속도

    case_b

    결과 시뮬레이션 진행 시간: 1000ms
    버퍼 크기: 10
    표본 크기: 50
    Producer의 데이터 생성주기 평균: 20ms
    Consumer의 데이터 소비주기 평균: 20ms
    Producer의 데이터 생성주기 표준편차: 6.00
    Consumer의 데이터 소비주기 표준편차: 1.00
    빈 버퍼에 접근한 비율: 2.33%
    손실된 데이터 비율: 0.00%

  • case c) 데이터 평균 처리 속도 < 데이터 평균 발생 속도

    case_c

    (발생기 쓰레드 5개)

    결과
    시뮬레이션 진행 시간: 1000ms
    버퍼 크기: 10
    표본 크기: 50
    Producer의 데이터 생성주기 평균: 50ms
    Consumer의 데이터 소비주기 평균: 60ms
    Producer의 데이터 생성주기 표준편차: 6.00
    Consumer의 데이터 소비주기 표준편차: 1.00
    빈 버퍼에 접근한 비율: 0.00%
    손실된 데이터 비율: 21.74%

코드

github repo

reference

  • Software Engineering 8th edition -Ian Sommerville

Comments