Skip to content

Profile and debug code

This page describes two in-process code-inspection tools in KX Sensors: profiler, for benchmarking function execution time, and ws, for inspecting tables, variables, and functions.

KX Sensors provides two in-process tools for inspecting and troubleshooting your code: profiler, a line-level code profiler for benchmarking function execution time, and ws, a set of workspace summary functions for inspecting the tables, variables, and functions defined in a running process.

Profile code with profiler

profiler is a line-level code profiler that outputs the run time for all lines of a function, the number of times that the line was run and the total time a function takes to be executed. This information is output in report form within a Console window.

The report shows the following information:

Column Description
Name the name of the function
Line the line number of the function
Stmt statement showing the first n number of characters of the line (n is configurable)
Count the number of times that the line was run
Total the total time that the line took including all child functions within the line
Own the total time that the line took excluding all child functions
Pct the percentage of the total time a function takes to be executed that the Own time represents (that is, the total function time minus the child functions time)
Name        Line Stmt                                                              Count Total    Own      Pct
-----------------------------------------------------------------------------------------------------------------
.ws.dpy     5    -1 h,/{[fn;p]fn,"\n",@[#[1+last p]" ";p;:;"^"]}'[f                 80    00:00.960 00:00.960 90.82%
.ws.expns   0    $[type key x;$[ns value x;f[j where not i],getn[f;                28    00:00.040 00:00.035 3.31%
.ws.shw     0    fn:first a:fnd nm;dpy[nm;fn;where last a;(,/)f1[;f                 220   00:01.013 00:00.008 0.75%
.ws.cm      0    i:first[b]=(=\)q;j:first where[i<c],n:count q;(i[j                 433   00:00.006 00:00.006 0.56%
.ws.cmm     0    $[1b in c:(fn in" \n")&1_(fn="/"),0b;[j:(cm\). 0b,                 110   00:00.011 00:00.005 0.47%
.ws.se      3    i:q&fn in CH;se:(<>\)i:i<>-1_0b,i;                                 110   00:00.005 00:00.005 0.47%
.ws.fnd     0    x:"\n",last value value x;(x;"\n"=x:@[x;where x in                 220   00:00.004 00:00.004 0.37%
.ws.se      2    q:j&q<=(=\)q>=j;                                                   110   00:00.004 00:00.004 0.37%
.ws.se      8    se&-1_0b,se:se>=q                                                  110   00:00.004 00:00.004 0.37%
.ws.se      0    j:cmm[fn;where last fl;q:qtm fn:first fl];                         110   00:00.014 00:00.003 0.28%
.ws.se      5    j:q&i<fn="-";se|:j&1_b,0b;                                         110   00:00.003 00:00.003 0.28%
.ws.fnf     0    $[count s;fn ss s;()]                                             220   00:00.002 00:00.002 0.18%
.ws.fnshow  0    shw[;s;::;fnf]each gfns nm;                                        1     00:00.868 00:00.002 0.18%
.ws.se      4    b:fn in -11#CH;                                                    110   00:00.002 00:00.002 0.18%
.ws.se      6    j:i&(fn="_")|u:fn=" ";se|:u<expand[j;not t:b[(0,k                  110   00:00.003 00:00.002 0.18%

Run the profiler

  1. To profile a specific function or list of functions, use .prof.prof <function name(s)> to apply the profiling code to your functions. You can also put in a namespace to profile all code under that namespace in your process. To check if the profiler code has been applied properly, you can check the process logs or look at the code definition to see many instances of .prof.mon in the code.
  2. Run the function.
  3. Look up the results by running .prof.report <function name(s)> or .prof.report for all profiled functions. You can also see the raw time data with .prof.data <function name(s)> or .prof.data for all profiled functions, which will show the time down to nanoseconds.
  4. You can remove the profiling code by using .prof.unprof <function names>.

Debug code with WS

You can use the ws (workspace) summary functions to find out information about objects within a process. The three summary functions are: .ws.tblsum, .ws.varsum and .ws.fnsum.

Note

Summary functions use the internal function -22! to calculate the size. If you run this function on a very large table, it could negatively affect system performance.

.ws.tblsum

This helper function shows all your table details for all tables used in a particular process. For each table reported on, .ws.tblsum shows the table name, type (memory, partitioned, etc.), keys, number of rows, number of columns and total size in bytes.

q)t:.ws.tblsum`
Invalid name: .rgx.yyyy.MM.dd
q)setc[]
q)t
Table                     | Type Keys            Rows Cols Size
--------------------------|-------------------------------------
.af.affunctions           | M    ::              47   7    6369
.af.ccypips               | M    `sym            43   2    688
.af.tradingsessions       | M    ::              20   5    707
.af.tradingsessionscont   | M    ::              21   4    631
.af.tradingweek           | M    ::              1    6    144
.ag.alert                 | M    ::              0    9    139
.ag.alertcurrent          | M    `sym`alertkey   0    9    139
.ag.failure               | M    ::              0    5    92
.ag.keyedalert            | M    `alertinstance  0    19   330
.ag.topublish             | M    ::              0    9    139
.al.analytic              | M    `analytic       141  2    40705
.alertfilter.fired        | M    ::              0    2    48
.alertfilter.timechecks   | M    `sym`alertkey   0    3    64
.alertfilter.timechecksold| M    `sym`alertkey   0    3    64
.alerttimer.T             | M    ::              0    4    59
.axchild.i.table          | M    `handle         0    3    57
.axq.i.DATA_MAP           | M    ::              19   5    480
.ch.c                     | M    ::              8    1    162
.ch.cp                    | M    `handle         7    15   978
.ch.exit                  | M    ::              1    1    48
.ch.o                     | M    ::              1    1    42
.cx.class.details         | M    `class          39   4    889
.d.debug                  | M    `table`handle   0    7    115
.d.prcl.timerFunct        | M    `actID          7    8    578
.da.R                     | M    `t              1    5    83
.db.p.tbls                | M    `table          149  6    42422
.db.stbls                 | M    `table          0    2    48
.db.tbls                  | M    `table          72   56   52113
.db.tcats                 | M    `cat            15   10   411
.db.tfans                 | M    `fam            19   2    509
.dm.component             | M    `id             1    2    59

If you wish to restrict your report to an individual table, the following command can be used:

.ws.tblsum`tablename

Inputting a null symbol will calculate the information for every table in the process and the result table can be sorted by size of object using the following command:

`Size xdesc .ws.tblsum`

.ws.varsum

This helper function shows your variable details including the size and shape (the length of a list) for either a specific variable or all variables (if a null symbol is specified).

q)v
Variable        | Type Rank Size Shape
-----------------|-----------------------
.AC.ALIGN        | h    0    11   1
.AC.ARG          | h    0    11   1
.AC.AUTH         | h    0    11   1
.AC.BIND         | h    0    11   1
.AC.CHANNEL      | h    0    11   1
.AC.COLUMN       | h    0    11   1
.AC.CONTINUE     | h    0    11   1
.AC.DB           | h    0    11   1
.AC.DOMAIN       | h    0    11   1
.AC.DUP_KEY      | h    0    11   1
.AC.DUP_REQUEST  | h    0    11   1
.AC.ERR          | h    0    11   1
.AC.EXPIRED      | h    0    11   1
.AC.FILE         | h    0    11   1
.AC.FILE_ACCESS  | h    0    11   1
.AC.FILE_COPY    | h    0    11   1
.AC.FILE_DAMAGED | h    0    11   1
.AC.FILE_IO      | h    0    11   1
.AC.FILE_MODE    | h    0    11   1
.AC.FILE_MOVE    | h    0    11   1
.AC.FILE_NAME    | h    0    11   1
.AC.FILE_NF      | h    0    11   1
.AC.FILE_PATH    | h    0    11   1
.AC.FILE_RENAME  | h    0    11   1
.AC.ILG          | h    0    11   1
.AC.INPUT        | h    0    11   1
.AC.LIMIT        | h    0    11   1
.AC.LOCK         | h    0    11   1
.AC.MEMORY       | h    0    11   1
.AC.MISMATCH     | h    0    11   1
.AC.MODE         | h    0    11   1
v:`Size xdesc .ws.varsum`

.ws.fnsum

This helper function shows your function details including the input parameters and size for either a specific function or all functions (if a null symbol is specified).

Function                       | Params                                                      Lines Size
-------------------------------|------------------------------------------------------------------------
.AC.like                       | [s]                                                         1     382
.AC.map                        | [s]                                                         1     552
.RC.like                       | [s]                                                         1     382
.RC.map                        | [s]                                                         1     554
.af.addAjKey                   | [keycols;tab]                                               ~     110
.af.alignTables                | [keycols;timecol;tabs]                                      ~     160
.af.applyFunctionToColumns     | [tab;columns;func;applyeach;outputcolnames]                 ~     159
.af.applyFunctionToColumnsLike | [tab;columnpatterns;func;applyeach;outputcolnames]          ~     197
.af.bucketedSamples            | [tab;timeparams;syms;columns]                               ~     327
.af.bucketedSamplesWeekly      | [tab;timeparams;syms;columns]                               ~     172
.af.buildBy                    | [byparam;tablecols]                                         ~     179
.af.buildByFromPattern         | [colnames;pattern;suffix;f;applyeach]                       ~     172
.af.buildColumn                | [colparam;tablecols]                                        ~     152
.af.buildTimestampRack         | [sts;ets;bucket;timecol;tab]                                ~     197
.af.buildWhere                 | [starttimestamp;endtimestamp;whereparam;timecol]            ~     178
.af.buildWhereFromDict         | [startdatetime;enddatetime;dict;timestampcol]               ~     259
.af.buildWhereFromDictOther    | [otherdict]                                                 ~     140
.af.buildWhereFromDictTime     | [startdatetime;enddatetime;dict;timestampcol]               ~     240
.af.checkType                  | [data;expectedtypes;errorprefix;param]                      ~     153
.af.collapseOverlaps           | [x]                                                         ~     122
.af.columnNames                | [colnames;offset]                                           ~     116
.af.contiguousTimeseries       | [sts;ets;bucket]                                            ~     129
.af.contiguousTimeseriesTime   | [st;et;bucket]                                              ~     146
.af.convertToCCY               | [data;quotes;ccy;ccyfrom;columns;ratecol;sidecol;timecol]   ~     194
.af.convertToCCYOneCCY         | [data;quotes;ccy;ccyfrom;columns;ratecol;sidecol;timecol]   ~     204
.af.dxA                        | [table;timeparams;symbols;coldict;bydict;wheredict;maxrows] ~     239
.af.events                     | [st;et;eventflag;params]                                    ~     202
f:`Size xdesc .ws.fnsum`

.ws.rcalls

This helper function lists all the functions invoked directly or indirectly by the specified function. For example, if A calls functions B, C, and D, then .ws.rcalls will list B, C, D and all the functions called in B, C, and D.

.ws.rcalls`fn

Next steps