dimanche 26 mars 2023

Very long startup time in a program simulating a matrix digital rain using `curses.h` library and random numbers

I am trying to write a program simulating the matrix digital rain using curses.h library and random numbers. The program seems to be working but the startup of the program is very slow (up to 10 seconds on MacOS 11.6.1, 2.8GHz Quad-Core Intel Core i7). Why is that? Is it relate to how random numbers are used? How can I improve the code so that the start of the program becomes snappy

Here is the code:

/*matrix_digital_rain.c*/

#include <curses.h>
#include <unistd.h>
#include <locale.h>
#include <time.h>
#include <stdlib.h>
#include <string.h>
#include "set_characters.h"
#include "hyperparameters.h"
#include "functions.h"

int main() {
  srand((unsigned) time(NULL));   // Initialization, should only be called once.
  setlocale(LC_ALL, "");
  int max_y = 0, max_x = 0;
  Drop_init_vals drop_init_vals01;
  //Drop_init_vals drop_init_vals02;
  //Drop_init_vals drop_init_vals03;
  //Drop_init_vals drop_init_vals04;
  //Drop_init_vals drop_init_vals05;
  //Drop_init_vals drop_init_vals06;
  //Drop_init_vals drop_init_vals07;
  //Drop_init_vals drop_init_vals08;
  //Drop_init_vals drop_init_vals09;

  int iter_start01 = rand() % ITER_START_RANGE; 
  //int iter_start02 = rand() % ITER_START_RANGE; 
  //int iter_start03 = rand() % ITER_START_RANGE; 
  //int iter_start04 = rand() % ITER_START_RANGE; 
  //int iter_start05 = rand() % ITER_START_RANGE; 
  //int iter_start06 = rand() % ITER_START_RANGE; 
  //int iter_start07 = rand() % ITER_START_RANGE; 
  //int iter_start08 = rand() % ITER_START_RANGE; 
  //int iter_start09 = rand() % ITER_START_RANGE; 

  int iter = 0;
 
  initscr();
  noecho();
  curs_set(FALSE);
  start_color();
  init_color(CUSTOM_GREEN1, 90, 280, 90);
  init_color(CUSTOM_GREEN2, 100, 500, 100);
  init_color(CUSTOM_GREEN3, 100, 900, 100);
  init_color(COLOR_BLACK, 0, 0, 0);

  char char_set[DIM_1_ARRAY_STRING][DIM_2_ARRAY_STRING] = {SET_CHAR};
  char str_display[DIM_0_ARRAY_STRING][DIM_1_ARRAY_STRING][DIM_2_ARRAY_STRING];
  for (int i = 0; i<DIM_0_ARRAY_STRING; i++){
    for (int j = 0; j<LEN_STRING_DISPLAY; j++){
      strcpy(str_display[i][j], char_set[rand() % N_COMMAS]);
    }
  }

  while(1) 
  {
    getmaxyx(stdscr, max_y, max_x);
 
    clear();

    if (iter % ITER_REFRESH == iter_start01){
      drop_init_vals01 = random_drop_init_vals(drop_init_vals01, iter);
      drop_init_vals01.n_dim_str = 0;
    }

    print_n_string_from_string_array_struct(
      drop_init_vals01,
      str_display,
      iter
    );

/*
    if (iter % ITER_REFRESH == iter_start02){
      drop_init_vals02 = random_drop_init_vals(drop_init_vals02, iter);
      drop_init_vals02.n_dim_str = 1;
    }
    print_n_string_from_string_array_struct(
      drop_init_vals02,
      str_display,
      iter
    );


    if (iter % ITER_REFRESH == iter_start03){
      drop_init_vals03 = random_drop_init_vals(drop_init_vals03, iter);
      drop_init_vals03.n_dim_str = 2;
    }
    print_n_string_from_string_array_struct(
      drop_init_vals03,
      str_display,
      iter
    );

    if (iter % ITER_REFRESH == iter_start04){
      drop_init_vals04 = random_drop_init_vals(drop_init_vals04, iter);
      drop_init_vals04.n_dim_str = 3;
    }
    print_n_string_from_string_array_struct(
      drop_init_vals04,
      str_display,
      iter
    );


    if (iter % ITER_REFRESH == iter_start05){
      drop_init_vals05 = random_drop_init_vals(drop_init_vals05, iter);
      drop_init_vals05.n_dim_str = 4;
    }
    print_n_string_from_string_array_struct(
      drop_init_vals05,
      str_display,
      iter
    );


    if (iter % ITER_REFRESH == iter_start06){
      drop_init_vals06 = random_drop_init_vals(drop_init_vals06, iter);
      drop_init_vals06.n_dim_str = 5;
    }
    print_n_string_from_string_array_struct(
      drop_init_vals06,
      str_display,
      iter
    );


    if (iter % ITER_REFRESH == iter_start07){
      drop_init_vals07 = random_drop_init_vals(drop_init_vals07, iter);
      drop_init_vals07.n_dim_str = 6;
    }
    print_n_string_from_string_array_struct(
      drop_init_vals07,
      str_display,
      iter
    );

    if (iter % ITER_REFRESH == iter_start08){
      drop_init_vals08 = random_drop_init_vals(drop_init_vals08, iter);
      drop_init_vals08.n_dim_str = 7;
    }
    print_n_string_from_string_array_struct(
      drop_init_vals08,
      str_display,
      iter
    );

    if (iter % ITER_REFRESH == iter_start09){
      drop_init_vals09 = random_drop_init_vals(drop_init_vals09, iter);
      drop_init_vals09.n_dim_str = 8;
    }
    print_n_string_from_string_array_struct(
      drop_init_vals09,
      str_display,
      iter
    );

*/

    iter++;

    refresh();
    usleep(DELAY);
 
  }
  attron(COLOR_PAIR(1));
  attron(COLOR_PAIR(2));
  attron(COLOR_PAIR(3));
 
  endwin();
  refresh();
  use_default_colors();
}
/*functions.c*/

#include "hyperparameters.h"
#include "functions.h"
#include <curses.h>
#include <time.h>
#include <stdlib.h>


void print_GREEN1(int y1, int x1, int i, int n_string, int n_dim_str, char str_display[][DIM_1_ARRAY_STRING][DIM_2_ARRAY_STRING])
{
  init_pair(1, CUSTOM_GREEN1, COLOR_BLACK);
  attron(COLOR_PAIR(1));
  mvprintw(y1+i-n_string, x1, str_display[n_dim_str][i]);
}

void print_GREEN2(int y1, int x1, int i, int n_string, int n_dim_str, char str_display[][DIM_1_ARRAY_STRING][DIM_2_ARRAY_STRING])
{
  init_pair(2, CUSTOM_GREEN2, COLOR_BLACK);
  attron(COLOR_PAIR(2));
  mvprintw(y1+i-n_string, x1, str_display[n_dim_str][i]);
}

void print_GREEN3(int y1, int x1, int i, int n_string, int n_dim_str, char str_display[][DIM_1_ARRAY_STRING][DIM_2_ARRAY_STRING])
{
  init_pair(3, CUSTOM_GREEN3, COLOR_BLACK);
  attron(COLOR_PAIR(3));
  mvprintw(y1+i-n_string, x1, str_display[n_dim_str][i]);
}


Drop_init_vals random_drop_init_vals(Drop_init_vals drop_init_vals, int iter)
{
  

  struct timespec ts;
  clock_gettime(CLOCK_MONOTONIC, &ts);

  srand((unsigned int) (time_t)ts.tv_nsec);

  drop_init_vals.y1 = 0;
  drop_init_vals.x1 = rand() % X1_RANGE;
  drop_init_vals.n_string = 5 + rand() % N_STRING_RANGE;
  drop_init_vals.iter_init = iter;
  return drop_init_vals;
}

void print_n_string_from_string_array_struct(Drop_init_vals drop_init_vals, char str_display[][DIM_1_ARRAY_STRING][DIM_2_ARRAY_STRING], int iter)
{
  int y1 = drop_init_vals.y1;
  int x1 = drop_init_vals.x1;
  int n_string = drop_init_vals.n_string;
  int n_dim_str = drop_init_vals.n_dim_str;
  int y_start = iter - drop_init_vals.iter_init;


  int count = 0;
  for (int i=y_start; i<y_start+n_string; i++)
  {
    if (count == 0 || count == 1){
      print_GREEN1(y1, x1, i, n_string, n_dim_str, &str_display[n_dim_str]);
    }
    else if (count == 2 || count == 3 || count == 4){
      print_GREEN2(y1, x1, i, n_string, n_dim_str, &str_display[n_dim_str]);
    }
    else{
      print_GREEN3(y1, x1, i, n_string, n_dim_str, &str_display[n_dim_str]);
    }
    count++;
  }
}

//int gen_rand_int(){
//  struct timespec ts;
//  clock_gettime(CLOCK_MONOTONIC, &ts);
//
//  srand((unsigned int) (time_t)ts.tv_nsec);
//
//  return rand();
//}
/*functions.h*/

#ifndef FUNCTIONS_H
#define FUNCTIONS_H

typedef struct {
  int x1, y1, n_string, n_dim_str, iter_init; 
} Drop_init_vals ;


int gen_rand_int(void);
void print_n_string_from_string_array_struct(Drop_init_vals drop_init_vals, char str_display[][DIM_1_ARRAY_STRING][DIM_2_ARRAY_STRING], int iter);
Drop_init_vals random_drop_init_vals(Drop_init_vals drop_init_vals, int iter);

void print_GREEN1(int y1, int x1, int i, int n_string, int n_dim_str, char str_display[][DIM_1_ARRAY_STRING][DIM_2_ARRAY_STRING]);
void print_GREEN2(int y1, int x1, int i, int n_string, int n_dim_str, char str_display[][DIM_1_ARRAY_STRING][DIM_2_ARRAY_STRING]);
void print_GREEN3(int y1, int x1, int i, int n_string, int n_dim_str, char str_display[][DIM_1_ARRAY_STRING][DIM_2_ARRAY_STRING]);



#endif
/*hyperparameters.c*/

#ifndef HYPERPARAMETERS_H
#define HYPERPARAMETERS_H

#define DELAY 60000 //480000
#define CUSTOM_GREEN1 8
#define CUSTOM_GREEN2 9
#define CUSTOM_GREEN3 10
#define COLOR_BLACK 0
#define DIM_0_ARRAY_STRING 20
#define DIM_1_ARRAY_STRING 200
#define DIM_2_ARRAY_STRING 4
#define LEN_STRING_DISPLAY 100 
#define MAX_Y 100 
#define MAX_X 100 
#define N_STRING_MAX 20

#define Y1_RANGE 10
#define X1_RANGE 30
#define N_STRING_RANGE 5
#define Y_START_RANGE 15
#define ITER_REFRESH 60
#define ITER_START_RANGE 25


#endif
/*set_characters.c*/

#ifndef SET_CHARACTERS_H
#define SET_CHARACTERS_H

#define N_COMMAS 56

#define SET_CHAR "ㇰ", "ㇱ", "ㇲ","ㇳ","ㇴ","ㇵ","ㇶ","ㇷ","ㇸ","ㇹ","ㇺ","ㇻ","ㇼ","ㇽ","ㇾ", "+", ",", "-", ".", "/", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "<", "=", ">", "T", "H","E", "M", "A", "T", "R", "I", "X", "Z", ":", "・", ".", "=", "*", "+", "-", "<", ">", "¦", "|", "#", "_"


#endif
#makefile

CC = gcc 
CFLAGS = -Wextra -Wall -Wfloat-equal -Wundef -Wshadow -Wpointer-arith -Wcast-align -Wstrict-prototypes -Wstrict-overflow=5 -Wwrite-strings -Waggregate-return -Wcast-qual -Wswitch-default -Wswitch-enum -Wconversion -Wunreachable-code -pedantic -Wmissing-prototypes -Wstrict-prototypes -Wold-style-definition

BINC=matrix_digital_rain

allc: $(BINC) 

$(BINC): $(BINC).c $(BINC).o functions.o
    $(CC) $(CFLAGS) $(BINC).o functions.o -o $@ -lncurses

$(BINC).o: $(BINC).c set_characters.h hyperparameters.h
    $(CC) $(CFLAGS) -c $(BINC).c

functions.o: functions.c functions.h
    $(CC) $(CFLAGS) -c functions.c 

clean:
    $(RM) -rf $(BINC) *.dSYM *.o

runc: allc
    ./$(BINC)



Aucun commentaire:

Enregistrer un commentaire