Ready to test profiling.

This commit is contained in:
C. Guy Yarvin 2014-11-28 18:19:11 -08:00
parent 9370f2c479
commit b3a64933bc
12 changed files with 258 additions and 203 deletions

View File

@ -64,7 +64,7 @@ INCLUDE=i
MDEFINES=-DU3_OS_$(OS) -DU3_OS_ENDIAN_$(ENDIAN) -D U3_LIB=\"$(LIB)\"
# NOTFORCHECKIN - restore -O3
CFLAGS= $(COSFLAGS) -O3 -msse3 -ffast-math \
CFLAGS= $(COSFLAGS) -g -msse3 -ffast-math \
-funsigned-char \
-I/usr/local/include \
-I/opt/local/include \

View File

@ -20,6 +20,7 @@
# include "n/j.h" // u3j: jet control
# include "n/m.h" // u3m: master state
# include "n/n.h" // u3n: nock execution
# include "n/o.h" // u3o: config options
# include "n/r.h" // u3r: noun access (error returns)
# include "n/t.h" // u3t: profiling / tracing
# include "n/x.h" // u3x: noun access (error crashes)

11
i/n/a.h
View File

@ -144,8 +144,8 @@
struct { // profile stack
c3_d nox_d; // nock steps
u3_noun don; // ++path
u3_noun day; // profile data, ++doss
u3_noun don; // (list batt)
u3_noun day; // doss, only in u3H (moveme)
} pro;
struct { // memoization
@ -154,13 +154,10 @@
} u3a_road;
typedef u3a_road u3_road;
/* u3a_flag: flags for how.fag_w.
/* u3a_flag: flags for how.fag_w. All arena related.
*/
enum u3a_flag {
u3a_flag_debug = 0x1, // debug memory
u3a_flag_gc = 0x2, // garbage collect once
u3a_flag_sand = 0x4, // sand mode, bump allocation
u3a_flag_die = 0x8 // process was asked to exit
u3a_flag_sand = 0x1, // bump allocation (XX not impl)
};

View File

@ -97,11 +97,9 @@
u3j_soft(u3_noun cor,
const c3_c* tam_c);
/* u3j_find(): battery to driver number, or 0.
**
** `bat` is RETAINED by the caller.
/* u3j_find(): in warm state, return u3_none or calx. RETAINS.
*/
c3_l
u3_weak
u3j_find(u3_noun bat);
/* u3j_kick(): try to kick by jet. If no kick, produce u3_none.

87
i/n/o.h
View File

@ -6,78 +6,29 @@
**/
/* u3o_config: process / system configuration.
*/
typedef struct _u3o_config {
u3_noun who; // single identity
c3_c* dir_c; // execution directory (pier)
c3_w wag_w; // flags (both ways)
} u3o_config;
/* u3e_line: control line.
/* u3o_flag: process/system flags.
**
** _debug flags are set outside u3 and heard inside it.
** _check flags are set inside u3 and heard outside it.
*/
typedef struct _u3e_line {
c3_w pag_w;
c3_w mug_w;
} u3e_line;
/* u3e_control: memory change, control file.
*/
typedef struct _u3e_control {
c3_d evt_d; // event number
c3_w nor_w; // new page count north
c3_w sou_w; // new page count south
c3_w pgs_w; // number of changed pages
u3e_line mem_u[0]; // per page
} u3e_control;
/* u3_cs_patch: memory change, top level.
*/
typedef struct _u3_cs_patch {
c3_i ctl_i;
c3_i mem_i;
u3e_control* con_u;
} u3_ce_patch;
/* u3e_image: memory segment, open file.
*/
typedef struct _u3e_image {
c3_c* nam_c; // segment name
c3_i fid_i; // open file, or 0
c3_w pgs_w; // length in pages
} u3e_image;
/* u3e_pool: entire memory system.
*/
typedef struct _u3e_pool {
c3_c* dir_c; // path to
c3_d evt_d; // last patch written at event
c3_w dit_w[u3a_pages >> 5]; // touched since last save
u3e_image nor_u; // north segment
u3e_image sou_u; // south segment
} u3e_pool;
enum u3o_flag { // execution flags
u3o_debug_ram = 0x1, // debug: gc
u3o_debug_cpu = 0x2, // debug: profile
u3o_check_corrupt = 0x4, // check: gc memory
u3o_check_fatal = 0x8, // check: unrecoverable
u3o_verbose = 0x10 // be remarkably wordy
};
/** Globals.
**/
/* u3_Pool / u3P: global memory control.
/* u3_Config / u3C: global memory control.
*/
c3_global u3e_pool u3e_Pool;
# define u3P u3e_Pool
/** Functions.
**/
/* u3e_fault(): handle a memory event with libsigsegv protocol.
*/
c3_i
u3e_fault(void* adr_v, c3_i ser_i);
/* u3e_save():
*/
void
u3e_save(void);
/* u3e_live(): start the persistence system. Return c3y if no image.
*/
c3_o
u3e_live(c3_o nuu_o, c3_c* dir_c);
/* u3e_dirty(): count dirty pages.
*/
c3_w
u3e_dirty(void);
c3_global u3o_config u3o_Config;
# define u3C u3o_Config

View File

@ -34,10 +34,10 @@
void
u3t_samp(void);
/* u3t_come(): push on profile stack.
/* u3t_come(): push on profile stack; return yes if active push. RETAIN.
*/
void
u3t_come(u3_atom cog);
c3_o
u3t_come(u3_noun bat);
/* u3t_flee(): pop off profile stack.
*/

View File

@ -565,11 +565,6 @@
c3_global c3_c* u3_Local;
c3_global c3_c* u3_System;
c3_global c3_o u3_Flag_Abort;
c3_global c3_o u3_Flag_Garbage;
c3_global c3_o u3_Flag_Profile;
c3_global c3_o u3_Flag_Verbose;
/** Functions.
**/
/* Urbit time: 128 bits, leap-free.

70
n/j.c
View File

@ -196,10 +196,10 @@ _cj_sham(u3_noun som) // XX wrong, does not match ++sham
return haf;
}
/* _cj_warm_fend(): in warm state, return u3_none or calx. RETAINS.
/* u3j_find(): in warm state, return u3_none or calx. RETAINS.
*/
u3_weak
_cj_warm_fend(u3_noun bat)
u3j_find(u3_noun bat)
{
u3a_road* rod_u = u3R;
@ -321,7 +321,7 @@ _cj_hot_mine(u3_noun mop, u3_noun cor)
// Calculate parent axis.
//
if ( c3y == hr_mop ) {
u3_noun cax = _cj_warm_fend(u3h(u3r_at(q_mop, cor)));
u3_noun cax = u3j_find(u3h(u3r_at(q_mop, cor)));
par_l = u3h(u3h(cax));
u3z(cax);
@ -349,42 +349,6 @@ u3j_boot(void)
fprintf(stderr, "boot: installed %d jets\n", jax_l);
}
/* _cj_find(): search for jet, old school. `bat` is RETAINED.
*/
c3_l
_cj_find(u3_noun bat)
{
u3a_road* rod_u = u3R;
while ( 1 ) {
u3_weak jaw = u3h_gut(rod_u->jed.har_p, bat);
if ( u3_none != jaw ) {
u3_assure(u3a_is_cat(u3h(jaw)));
#if 0
if ( rod_u != u3R ) {
fprintf(stderr, "got: %x in %p/%p, %d\r\n",
bat, rod_u, rod_u->jed.har_p, jax);
}
#endif
return (c3_l)u3h(jaw);
}
if ( rod_u->par_u ) {
rod_u = rod_u->par_u;
}
else return 0;
}
}
/* u3j_find(): search for jet. `bat` is RETAINED.
*/
c3_l
u3j_find(u3_noun bat)
{
return _cj_find(bat);
}
/* _cj_soft(): kick softly by arm axis.
*/
static u3_noun
@ -467,7 +431,7 @@ _cj_hook_in(u3_noun cor,
if ( !_(u3du(cor)) ) { return u3m_bail(c3__fail); }
{
u3_weak cax = _cj_warm_fend(bat);
u3_weak cax = u3j_find(bat);
if ( u3_none == cax ) { return u3m_bail(c3__fail); }
{
@ -578,7 +542,7 @@ _cj_fine(u3_noun cup, u3_noun mop, u3_noun cor)
return c3n;
}
else {
u3_weak cax = _cj_warm_fend(u3h(pac));
u3_weak cax = u3j_find(u3h(pac));
if ( u3_none == cax ) {
return c3n;
@ -610,7 +574,7 @@ u3j_kick(u3_noun cor, u3_noun axe)
if ( !_(u3du(cor)) ) { return u3_none; }
{
u3_noun bat = u3h(cor);
u3_weak cax = _cj_warm_fend(bat);
u3_weak cax = u3j_find(bat);
if ( u3_none == cax ) { return u3_none; }
{
@ -633,13 +597,31 @@ u3j_kick(u3_noun cor, u3_noun axe)
u3j_core* cop_u = &u3D.ray_u[jax_l];
c3_l inx_l = inx;
u3j_harm* ham_u = &cop_u->arm_u[inx_l];
c3_o pof_o = __(u3C.wag_w & u3o_debug_cpu);
u3_noun pro;
u3z(cax);
if ( _(pof_o) ) {
pof_o = u3t_come(bat);
}
pro = _cj_kick_z(cor, cop_u, ham_u, axe);
if ( u3_none == pro ) {
if ( _(pof_o) ) {
pro = u3n_nock_on(cor, u3nq(9, axe, 0, 1));
u3t_flee();
return pro;
}
else return u3_none;
}
else {
if ( _(pof_o) ) {
u3t_flee();
}
return pro;
}
}
}
}
}
@ -699,7 +681,7 @@ _cj_mine(u3_noun cey, u3_noun cor)
}
else {
u3_noun tab = u3h(rah);
u3_weak cax = _cj_warm_fend(tab);
u3_weak cax = u3j_find(tab);
if ( u3_none == cax ) {
fprintf(stderr, "fund: in %s, parent %x not found at %d\r\n",
@ -772,7 +754,7 @@ u3j_mine(u3_noun clu, u3_noun cor)
if ( !_(u3du(cor)) ) {
u3z(clu);
}
else if ( u3_none != (cax = _cj_warm_fend(bat)) ) {
else if ( u3_none != (cax = u3j_find(bat)) ) {
u3z(cax); u3z(clu);
}
else {

13
n/m.c
View File

@ -204,7 +204,7 @@ _cm_signal_recover(c3_l sig_l, u3_noun arg)
// A top-level crash - rather odd. We should GC.
//
_cm_emergency("recover: top", sig_l);
u3H->rod_u.how.fag_w |= u3a_flag_gc;
u3C.wag_w |= u3o_check_corrupt;
// Reset the top road - the problem could be a fat cap.
//
@ -447,10 +447,6 @@ _cm_pave(c3_o nuu_o, c3_o bug_o)
u3a_words - 1);
u3R = &u3H->rod_u;
}
if ( _(bug_o) ) {
u3R->how.fag_w |= u3a_flag_debug;
}
}
#if 0
@ -677,9 +673,6 @@ u3m_leap(c3_w pad_w)
/* Set up the new road.
*/
{
if ( u3R->how.fag_w & u3a_flag_debug ) {
rod_u->how.fag_w |= u3a_flag_debug;
}
u3R = rod_u;
_pave_parts();
}
@ -826,7 +819,7 @@ u3m_soft_top(c3_w sec_w, // timer seconds
/* Make sure the inner routine did not create garbage.
*/
if ( u3R->how.fag_w & u3a_flag_debug ) {
if ( u3C.wag_w & u3o_debug_ram ) {
u3m_grab(pro, u3_none);
}
@ -916,7 +909,7 @@ u3m_soft_run(u3_noun fly,
if ( 0 == (why = (u3_noun)setjmp(u3R->esc.buf)) ) {
pro = fun_f(aga, agb);
if ( u3R->how.fag_w & u3a_flag_debug ) {
if ( u3C.wag_w & u3o_debug_ram ) {
u3m_grab(pro, u3_none);
}

154
n/t.c
View File

@ -60,11 +60,105 @@ u3t_slog(u3_noun hod)
void
u3t_heck(u3_atom cog)
{
printf("ct: heck %s\r\n", u3r_string(cog));
// Profile sampling, because it allocates on the home road,
// only works on when we're not at home.
//
if ( &(u3H->rod_u) != u3R ) {
u3a_road* rod_u;
if ( 0 == u3R->pro.day ) { u3R->pro.day = u3v_do("doss", 0); }
rod_u = u3R;
u3R = &(u3H->rod_u);
{
if ( 0 == u3R->pro.day ) {
u3R->pro.day = u3v_do("doss", 0);
}
u3R->pro.day = u3dc("pi-heck", cog, u3R->pro.day);
}
u3R = rod_u;
}
}
/* _t_samp_process(): process raw sample data from live road.
*/
static u3_noun
_t_samp_process(u3_road* rod_u)
{
u3_noun pef = u3_nul; // (list (pair path (map path ,@ud)))
u3_noun muf = u3_nul; // (map path ,@ud)
c3_w len_w = 0;
// Accumulate a label/map stack which collapses recursive segments.
//
while ( rod_u ) {
u3_noun don = rod_u->pro.don;
while ( u3_nul != don ) {
u3_noun bat = u3h(don);
u3_noun lab;
// Find the label from this battery, surface allocated.
//
{
u3R = rod_u;
{
u3_noun cax;
if ( u3_none == (cax = u3j_find(bat)) ) {
abort(); // probably a little drastic
}
lab = u3h(u3t(u3t(cax)));
}
u3R = &u3H->rod_u;
lab = u3a_take(lab);
}
// Add the label to the traced label stack, trimming recursion.
//
{
u3_noun old;
if ( u3_none == (old = u3kdb_get(u3k(muf), u3k(lab))) ) {
muf = u3kdb_put(muf, u3k(lab), len_w);
pef = u3nc(u3nc(lab, u3k(muf)), pef);
len_w += 1;
}
else {
u3_assure(u3a_is_cat(old));
u3z(muf);
while ( len_w > (old + 1) ) {
u3_noun t_pef = u3k(u3t(pef));
len_w -= 1;
u3z(pef);
pef = t_pef;
}
muf = u3k(u3t(u3h(pef)));
}
}
don = u3t(don);
}
}
// Lose the maps and save a pure label stack in original order.
//
{
u3_noun pal = u3_nul;
while ( u3_nul != pef ) {
u3_noun h_pef = u3h(pef);
u3_noun t_pef = u3k(u3t(pef));
pal = u3nc(u3k(u3h(h_pef)), pal);
u3z(pef);
pef = t_pef;
}
return pal;
}
}
/* u3t_samp(): sample.
@ -72,19 +166,37 @@ u3t_heck(u3_atom cog)
void
u3t_samp(void)
{
if ( 0 == u3R->pro.day ) { u3R->pro.day = u3v_do("doss", 0); }
// Profile sampling, because it allocates on the home road,
// only works on when we're not at home.
//
if ( &(u3H->rod_u) != u3R ) {
u3a_road* rod_u;
u3R->pro.day = u3dc("pi-noon", u3k(u3R->pro.don), u3R->pro.day);
rod_u = u3R;
u3R = &(u3H->rod_u);
{
u3_noun lab = _t_samp_process(rod_u);
c3_assert(u3R == &u3H->rod_u);
if ( 0 == u3R->pro.day ) {
u3R->pro.day = u3v_do("doss", 0);
}
u3R->pro.day = u3dc("pi-noon", lab, u3R->pro.day);
}
u3R = rod_u;
}
}
/* u3t_come(): push on profile stack.
/* u3t_come(): push on profile stack; return yes if active push. RETAIN.
*/
void
u3t_come(u3_atom cog)
c3_o
u3t_come(u3_noun bat)
{
printf("ct: come %s\r\n", u3r_string(cog));
u3R->pro.don = u3nc(cog, u3R->pro.don);
if ( (u3_nul == u3R->pro.don) || !_(u3r_sing(bat, u3h(u3R->pro.don))) ) {
u3R->pro.don = u3nc(u3k(bat), u3R->pro.don);
return c3y;
}
else return c3n;
}
/* u3t_flee(): pop off profile stack.
@ -92,13 +204,10 @@ u3t_come(u3_atom cog)
void
u3t_flee(void)
{
c3_assert(_(u3du(u3R->pro.don)));
{
u3_noun tax = u3R->bug.tax;
u3_noun t_don = u3k(u3t(u3R->pro.don));
u3R->bug.tax = u3k(u3t(tax));
u3z(tax);
}
u3z(u3R->pro.don);
u3R->pro.don = t_don;
}
/* u3t_damp(): print and clear profile data.
@ -128,13 +237,14 @@ void _ct_sigaction(c3_i x_i) { u3t_samp(); }
void
u3t_boot(void)
{
if ( u3C.wag_w & u3o_debug_cpu ) {
printf("ct: now profiling.\r\n");
printf("knox: %llu\r\n", (u3R->pro.nox_d / 1000ULL));
u3R->pro.nox_d = 0;
#if defined(U3_OS_osx)
#if 0
#if 1
{
struct itimerval itm_v;
struct sigaction sig_s;
@ -145,7 +255,8 @@ u3t_boot(void)
sigaction(SIGPROF, &sig_s, 0);
itm_v.it_interval.tv_sec = 0;
itm_v.it_interval.tv_usec = 10000;
// itm_v.it_interval.tv_usec = 10000;
itm_v.it_interval.tv_usec = 100000;
itm_v.it_value = itm_v.it_interval;
setitimer(ITIMER_PROF, &itm_v, 0);
@ -156,8 +267,9 @@ u3t_boot(void)
#elif defined(U3_OS_bsd)
// TODO: support profiling on bsd
#else
#error "port: profiling"
# error "port: profiling"
#endif
}
}
/* u3t_boff(): turn profile sampling off.
@ -165,6 +277,7 @@ u3t_boot(void)
void
u3t_boff(void)
{
if ( u3C.wag_w & u3o_debug_cpu ) {
#if defined(U3_OS_osx)
struct sigaction sig_s;
struct itimerval itm_v;
@ -184,6 +297,7 @@ u3t_boff(void)
#elif defined(U3_OS_bsd)
// TODO: support profiling on bsd
#else
#error "port: profiling"
# error "port: profiling"
#endif
}
}

View File

@ -417,9 +417,10 @@ _lo_time(void)
void
u3_lo_open(void)
{
if ( (u3H->rod_u.how.fag_w & u3a_flag_gc) ||
(u3H->rod_u.how.fag_w & u3a_flag_debug) )
{
if ( u3C.wag_w & (u3o_debug_cpu | u3o_check_corrupt) ) {
//
// Assumption: there are no noun roots outside u3A.
//
u3m_grab(u3_none);
}
_lo_time();
@ -461,7 +462,7 @@ u3_lo_shut(c3_o inn)
// u3_lo_grab("lo_exit", u3_none);
// u3_loom_save(u3A->ent_d);
// u3_loom_exit();
// u3t_boff();
u3t_boff();
u3_lo_exit();
exit(u3_Host.xit_i);
@ -629,7 +630,8 @@ u3_lo_loop()
_lo_init();
u3_raft_init();
// u3t_boot(); // activate profiling
u3t_boot(); // activate profiling
if ( c3n == u3_Host.ops_u.bat ) {
uv_run(u3L, UV_RUN_DEFAULT);

View File

@ -62,7 +62,7 @@ _main_getopt(c3_i argc, c3_c** argv)
u3_Host.ops_u.mem = c3n;
u3_Host.ops_u.kno_w = DefaultKernel;
while ( (ch_i = getopt(argc, argv, "I:X:f:k:l:n:p:r:LabcdgqvFM")) != -1 ) {
while ( (ch_i = getopt(argc, argv, "I:X:f:k:l:n:p:r:LabcdgqvFMP")) != -1 ) {
switch ( ch_i ) {
case 'M': {
u3_Host.ops_u.mem = c3y;
@ -121,6 +121,7 @@ _main_getopt(c3_i argc, c3_c** argv)
case 'c': { u3_Host.ops_u.nuu = c3y; break; }
case 'd': { u3_Host.ops_u.dem = c3y; break; }
case 'g': { u3_Host.ops_u.gab = c3y; break; }
case 'P': { u3_Host.ops_u.pro = c3y; break; }
case 'q': { u3_Host.ops_u.veb = c3n; break; }
case 'v': { u3_Host.ops_u.veb = c3y; break; }
case '?': default: {
@ -197,10 +198,6 @@ u3_ve_sysopt()
{
u3_Local = strdup(u3_Host.dir_c);
u3_System = U3_LIB;
u3_Flag_Abort = u3_Host.ops_u.abo;
u3_Flag_Garbage = u3_Host.ops_u.gab;
u3_Flag_Profile = u3_Host.ops_u.pro;
u3_Flag_Verbose = u3_Host.ops_u.veb;
}
#if 0
@ -292,6 +289,7 @@ main(c3_i argc,
u3_ve_sysopt();
c3_assert(!(u3C.wag_w & u3o_debug_cpu));
printf("~\n");
printf("welcome.\n");
printf("vere: urbit home is %s\n", u3_Host.dir_c);
@ -305,10 +303,34 @@ main(c3_i argc,
//
srand(getpid());
c3_assert(!(u3C.wag_w & u3o_debug_cpu));
// Instantiate process globals.
{
/* Boot the image and checkpoint.
/* Boot the image and checkpoint. Set flags.
*/
{
/* Set pier directory.
*/
u3C.dir_c = u3_Host.dir_c;
/* Set GC flag.
*/
if ( _(u3_Host.ops_u.gab) ) {
u3C.wag_w |= u3o_debug_ram;
}
/* Set profile flag.
*/
if ( _(u3_Host.ops_u.pro) ) {
u3C.wag_w |= u3o_debug_cpu;
}
/* Set verbose flag.
*/
if ( _(u3_Host.ops_u.veb) ) {
u3C.wag_w |= u3o_verbose;
}
}
u3m_boot(u3_Host.ops_u.nuu, u3_Host.ops_u.gab, u3_Host.dir_c);
/* Start Arvo.