Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Remove cobprof.h
Browse files Browse the repository at this point in the history
lefessan committed Nov 20, 2023
1 parent 42459b3 commit ac2d932
Showing 11 changed files with 110 additions and 67 deletions.
2 changes: 0 additions & 2 deletions cobc/codegen.c
Original file line number Diff line number Diff line change
@@ -13733,8 +13733,6 @@ output_cob_prof_data ()

output_local ("/* cob_prof data */\n\n");

output_local ("#include <libcob/cobprof.h>\n\n");

output_local ("static const char *procedures_names[%d] = {\n", procedures_list_len + 1);
while (l) {
output_local (" \"%s\",\n", l->text);
32 changes: 32 additions & 0 deletions config/runtime.cfg
Original file line number Diff line number Diff line change
@@ -217,6 +217,38 @@
# Example: COB_CURRENT_DATE "2026/03/16 16:40:52"
# current_date YYYYMMDDHHMMSS+01:00

# Environment name: COB_PROF_FILE
# Parameter name: prof_file
# Purpose: to define where COBOL profiling output should go
# Type: string : $$ is replaced by process id
# Default: $$-prof.csv
# Example: PROF_FILE ${HOME}/$$-prof.csv

# Environment name: COB_PROF_DISABLE
# Parameter name: prof_disable
# Purpose: to disable profiling for modules compiled with profiling
# Type: boolean
# Default: false
# Example: PROF_DISABLE no

# Environment name: COB_PROF_MAX_DEPTH
# Parameter name: prof_max_depth
# Purpose: the number of sections and paragraphs that can be nested;
# if the nesting level is higher than this threshold,
# profiling is disabled automatically
# Type: integer
# Default: 255
# Example: PROF_MAX_DEPTH ${HOME}/$$-prof.csv

# Environment name: COB_IS_RUNNING_IN_TESTMODE
# Parameter name: testsuite_mode
# Purpose: whether we are running the testsuite; In such a case,
# the output is made deterministic: for example, profiling
# does not output times but numbers of calls
# Type: boolean
# Default: false
# Example: TESTSUITE_MODE no

#
## Call environment
#
36 changes: 7 additions & 29 deletions doc/gnucobol.texi
Original file line number Diff line number Diff line change
@@ -1774,36 +1774,13 @@ Then executing your program will automatically profile the module(s)
and generate a CSV result file. By default, this file is called
@code{<pid>-prof.csv}.

The following environment variables (and the corresponding option in
the runtime configuration) are available to tune the behavior of
profiling during execution:
Some environment variables (and the corresponding options in the
runtime configuration) can be used to tune the behavior of profiling
during execution: @code{COB_PROF_FILE}, @code{COB_PROF_DISABLE},
@code{COB_PROF_MAX_DEPTH} and @code{COB_IS_RUNNING_IN_TESTMODE},
@pxref{Appendix I, Runtime Configuration, Runtime Configuration} for
more information.

@table @code

@item COB_PROF_FILE (prof_file)

This variable specifies the name of the CSV file generated at the end
of execution.

@item COB_PROF_DISABLE (prof_disable)

This variable disables profiling for all modules, even the ones
compiled with @code{-fprof}.

@item COB_PROF_MAX_DEPTH (prof_max_depth)

This variable can be used to increase the maximal number of recursions
allowed during profiling. The default (and minimal) setting is
255. The maximal is 100,000,000. If the number of recursions is
greater than the maximal depth, profiling is disabled and will not
generate any file.

@item COB_IS_RUNNING_IN_TESTMODE (testsuite_mode)

This variable is used when running the testsuite. The timings will be
replaced by the number of calls, to make the output deterministic.

@end table

@node Profiling results
@section Profiling results
@@ -1851,6 +1828,7 @@ The number of calls to this section/paragraph

@end table


@subsection Consideration for @code{GO TO}

When executing a @code{GO TO} that targets a section or a paragraph
5 changes: 2 additions & 3 deletions libcob/ChangeLog
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
2023-09-04 Fabrice Le Fessant <fabrice.le_fessant@ocamlpro.com> and Emilien Lemaire <emilien.lemaire@ocamlpro.com>

* Makefile.am: add `profiling.c` and `cobprof.h` in sources and headers
* Makefile.am: add `profiling.c` to sources
* profiling.c, cobprof.h: implement profiling functions (time spent in each
procedure of the program)
* common.c: include `cobprof.h`
* common.c: add 4 environments variables COB_PROF_FILE, COB_PROF_MAX_DEPTH,
COB_PROF_DISABLE and COB_IS_RUNNING_IN_TESTMODE
COB_PROF_ENABLE and COB_IS_RUNNING_IN_TESTMODE

2023-07-28 Simon Sobisch <simonsobisch@gnu.org>

2 changes: 1 addition & 1 deletion libcob/Makefile.am
Original file line number Diff line number Diff line change
@@ -42,7 +42,7 @@ libcob_la_LDFLAGS = $(COB_FIX_LIBTOOL) -version-info 6:0:2 -no-undefined
AM_LDFLAGS = $(COB_FIX_LIB)

pkgincludedir = $(includedir)/libcob
pkginclude_HEADERS = common.h version.h cobgetopt.h cobprof.h \
pkginclude_HEADERS = common.h version.h cobgetopt.h \
exception.def exception-io.def statement.def

# Add rules for code-coverage testing, as provided by AX_CODE_COVERAGE
2 changes: 1 addition & 1 deletion libcob/coblocal.h
Original file line number Diff line number Diff line change
@@ -348,7 +348,7 @@ typedef struct __cob_settings {

char *cob_dump_filename; /* Place to write dump of variables */
char *cob_prof_filename; /* Place to write profiling data */
int cob_prof_disable; /* Whether profiling is disabled */
int cob_prof_enable; /* Whether profiling is enabled */
int cob_prof_max_depth; /* Max stack depth during profiling (255 by default) */
int cob_testsuite_mode; /* Running in testsuite mode */
int cob_dump_width; /* Max line width for dump */
1 change: 0 additions & 1 deletion libcob/cobprof.h
Original file line number Diff line number Diff line change
@@ -34,7 +34,6 @@ struct cobprof_info {
unsigned int * called_count ; /* Array of execution counts */
const char** procedures_names ; /* Array of procedures names */
size_t procedures_count; /* Number of procedures */
int active; /* Whether profiling is active for this module */
};

/* Function called to start profiling a COBOL module. Allocates the
2 changes: 1 addition & 1 deletion libcob/common.c
Original file line number Diff line number Diff line change
@@ -496,7 +496,7 @@ static struct config_tbl gc_conf[] = {
{"COB_CORE_FILENAME", "core_filename", "./core.libcob", NULL, GRP_MISC, ENV_STR, SETPOS (cob_core_filename)},
{"COB_DUMP_FILE", "dump_file", NULL, NULL, GRP_MISC, ENV_FILE, SETPOS (cob_dump_filename)},
{"COB_PROF_FILE", "prof_file", NULL, NULL, GRP_MISC, ENV_FILE, SETPOS (cob_prof_filename)},
{"COB_PROF_DISABLE", "prof_disable", "0", NULL, GRP_MISC, ENV_BOOL, SETPOS (cob_prof_disable)},
{"COB_PROF_ENABLE", "prof_enable", "0", NULL, GRP_MISC, ENV_BOOL, SETPOS (cob_prof_enable)},
{"COB_PROF_MAX_DEPTH", "prof_max_depth", "255", NULL, GRP_MISC, ENV_UINT, SETPOS (cob_prof_max_depth)},
{"COB_IS_RUNNING_IN_TESTMODE", "testsuite_mode", "0", NULL, GRP_MISC, ENV_BOOL, SETPOS (cob_testsuite_mode)},
{"COB_DUMP_WIDTH", "dump_width", "100", NULL, GRP_MISC, ENV_UINT, SETPOS (cob_dump_width)},
29 changes: 29 additions & 0 deletions libcob/common.h
Original file line number Diff line number Diff line change
@@ -2915,4 +2915,33 @@ typedef char * cobchar_t;

/*******************************/


/* Type to store nanoseconds */
typedef unsigned long long cob_ns_time;

/* Structure storing profiling information about each COBOL module */
struct cobprof_info {
const char* program_id ;
cob_ns_time * total_times ; /* Array of execution times */
unsigned int * called_count ; /* Array of execution counts */
const char** procedures_names ; /* Array of procedures names */
size_t procedures_count; /* Number of procedures */
};

/* Function called to start profiling a COBOL module. Allocates the
cobprof_info structure that will be used to store the counters and
times. */
COB_EXPIMP struct cobprof_info *cob_prof_init (
const char *program_id,
const char**procedures_names,
size_t procedures_count);

/* Functions used to instrument the generated C code and measure
* counters and times */
COB_EXPIMP void cob_prof_enter_paragraph (struct cobprof_info *, int);
COB_EXPIMP void cob_prof_exit_paragraph (struct cobprof_info *, int);
COB_EXPIMP void cob_prof_enter_section (struct cobprof_info *, int);
COB_EXPIMP void cob_prof_exit_section (struct cobprof_info *, int);
COB_EXPIMP void cob_prof_goto (struct cobprof_info *, int);

#endif /* COB_COMMON_H */
60 changes: 34 additions & 26 deletions libcob/profiling.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
Copyright (C) 2003-2023 Free Software Foundation, Inc.
Copyright (C) 2023 Free Software Foundation, Inc.
Written by Emilien Lemaire and Fabrice Le Fessant.
This file is part of GnuCOBOL.
@@ -31,7 +31,6 @@
#include "tarstamp.h"
#include "config.h"
#include "common.h"
#include "cobprof.h"

#include <sys/types.h>
#ifdef HAVE_UNISTD_H
@@ -63,7 +62,7 @@ static cob_ns_time *start_times;
static int *called_procedures;
static struct cobprof_info* *called_runtimes;
static int current_idx = -1;
static int is_active = 1; /* we may want to disable profiling globally */
static int is_active = 0;
static int is_test = 0;
static const char* prof_program_id;

@@ -128,32 +127,42 @@ is_section (struct cobprof_info *info, int proc_idx)
return !!strstr (info->procedures_names[proc_idx], "||");
}

static void
prof_init_static ()
{
static int init_done = 0;

if (!init_done && cobsetptr){
init_done = 1;
is_active = cobsetptr->cob_prof_enable;
if (is_active){
is_test = cobsetptr->cob_testsuite_mode;
max_prof_depth = cobsetptr->cob_prof_max_depth;
if (max_prof_depth < PROF_DEFAULT_DEPTH){
max_prof_depth = PROF_DEFAULT_DEPTH;
}
if (max_prof_depth > PROF_MAX_DEPTH){
max_prof_depth = PROF_MAX_DEPTH;
}
start_times = cob_malloc (max_prof_depth * sizeof(cob_ns_time));
called_procedures = cob_malloc (max_prof_depth * sizeof(int));
called_runtimes = cob_malloc (max_prof_depth * sizeof(struct cobprof_info*));
}
}
}

void cob_init_prof (cob_global *lptr, cob_settings *sptr)
{
cobglobptr = lptr;
cobsetptr = sptr;

is_test = cobsetptr->cob_testsuite_mode;
is_active = !cobsetptr->cob_prof_disable;

max_prof_depth = cobsetptr->cob_prof_max_depth;
if (max_prof_depth < PROF_DEFAULT_DEPTH){
max_prof_depth = PROF_DEFAULT_DEPTH;
}
if (max_prof_depth > PROF_MAX_DEPTH){
max_prof_depth = PROF_MAX_DEPTH;
}
start_times = cob_malloc (max_prof_depth * sizeof(cob_ns_time));
called_procedures = cob_malloc (max_prof_depth * sizeof(int));
called_runtimes = cob_malloc (max_prof_depth * sizeof(struct cobprof_info*));
}

struct cobprof_info *
cob_prof_init (const char *program_id,
const char **procedures_names,
size_t procedures_count)
{

prof_init_static();
if (!prof_program_id) prof_program_id = program_id ;

if (is_active){
@@ -166,7 +175,6 @@ cob_prof_init (const char *program_id,
info->called_count = cob_malloc ( procedures_count * sizeof(unsigned int) );
info->procedures_names = procedures_names;
info->procedures_count = procedures_count;
info->active = 1; /* in the future, we may want to desactivate profiling on a per-module basis */

item = cob_malloc (sizeof(struct cobprof_info_list));
item->info = info;
@@ -182,7 +190,7 @@ cob_prof_enter_paragraph (struct cobprof_info *info, int proc_idx)
{
cob_ns_time t;

if (!is_active || info == NULL || !info->active) return;
if (!is_active || info == NULL) return;

t = get_ns_time ();

@@ -205,7 +213,7 @@ cob_prof_enter_section (struct cobprof_info *info, int proc_idx)
{
cob_ns_time t;

if (!is_active || info == NULL || !info->active) return;
if (!is_active || info == NULL) return;

t = get_ns_time ();

@@ -228,7 +236,7 @@ cob_prof_exit_paragraph (struct cobprof_info *info, int proc_idx)
{
cob_ns_time t;

if (!is_active || info == NULL || !info->active) return;
if (!is_active || info == NULL) return;

t = get_ns_time ();

@@ -247,7 +255,7 @@ cob_prof_exit_section (struct cobprof_info *info, int proc_idx)
{
cob_ns_time t;

if (!is_active || info == NULL || !info->active) return;
if (!is_active || info == NULL) return;

t = get_ns_time ();

@@ -275,7 +283,7 @@ cob_prof_goto (struct cobprof_info *info, int proc_idx)
int curr_proc;
struct cobprof_info *curr_info;

if (!is_active || info == NULL || !info->active) return;
if (!is_active || info == NULL) return;

curr_proc = called_procedures[current_idx];
curr_info = called_runtimes[current_idx];
@@ -381,6 +389,8 @@ cob_prof_end ()
char prof_file_buf[COB_NORMAL_BUFF];
const char* prof_filename = NULL;

prof_init_static ();

if (!cobsetptr || !is_active || !prof_program_id) return;

while (current_idx >= 0) {
@@ -409,8 +419,6 @@ cob_prof_end ()
cob_ns_time section_time = 0;
cob_ns_time section_cumul_time = 0;

if (!info->active) continue;

fprintf (file, "program id,section,paragraph,location,kind,time ns,time,ncalls\n");
for (int i = 0; i < info->procedures_count; i++) {
cob_ns_time time = is_test ? info->called_count[i] : info->total_times[i];
6 changes: 3 additions & 3 deletions tests/testsuite.src/used_binaries.at
Original file line number Diff line number Diff line change
@@ -1043,7 +1043,7 @@ prog.cob: in paragraph 'PARA-0003':
prog.cob:11: warning: GO TO SECTION '2ND'
])

AT_CHECK([COB_PROF_FILE=prof.csv ./prog])
AT_CHECK([COB_PROF_ENABLE=1 COB_PROF_FILE=prof.csv ./prog])

#note: The time here is actually the number of times the procedure has been run, to avoid
# any indeterminism in the running time of the procedure.
@@ -1079,7 +1079,7 @@ AT_CAPTURE_FILE([prof.csv])

AT_CHECK([$COMPILE -fprof -x prog.cob])

AT_CHECK([COB_PROF_FILE=prof.csv ./prog], [0], [HELLO
AT_CHECK([COB_PROF_ENABLE=1 COB_PROF_FILE=prof.csv ./prog], [0], [HELLO
WORLD
])

@@ -1108,7 +1108,7 @@ AT_CAPTURE_FILE([prof.csv])

AT_CHECK([$COMPILE -fprof -x prog.cob])

AT_CHECK([COB_PROF_FILE=prof.csv ./prog], [0], [HELLO
AT_CHECK([COB_PROF_ENABLE=1 COB_PROF_FILE=prof.csv ./prog], [0], [HELLO
WORLD
])

0 comments on commit ac2d932

Please sign in to comment.