LCOV - differential code coverage report
Current view: top level - src/backend/executor - instrument.c (source / functions) Coverage Total Hit UBC CBC
Current: Differential Code Coverage HEAD vs 15 Lines: 92.3 % 142 131 11 131
Current Date: 2023-04-08 15:15:32 Functions: 92.9 % 14 13 1 13
Baseline: 15
Baseline Date: 2023-04-08 15:09:40
Legend: Lines: hit not hit

           TLA  Line data    Source code
       1                 : /*-------------------------------------------------------------------------
       2                 :  *
       3                 :  * instrument.c
       4                 :  *   functions for instrumentation of plan execution
       5                 :  *
       6                 :  *
       7                 :  * Copyright (c) 2001-2023, PostgreSQL Global Development Group
       8                 :  *
       9                 :  * IDENTIFICATION
      10                 :  *    src/backend/executor/instrument.c
      11                 :  *
      12                 :  *-------------------------------------------------------------------------
      13                 :  */
      14                 : #include "postgres.h"
      15                 : 
      16                 : #include <unistd.h>
      17                 : 
      18                 : #include "executor/instrument.h"
      19                 : 
      20                 : BufferUsage pgBufferUsage;
      21                 : static BufferUsage save_pgBufferUsage;
      22                 : WalUsage    pgWalUsage;
      23                 : static WalUsage save_pgWalUsage;
      24                 : 
      25                 : static void BufferUsageAdd(BufferUsage *dst, const BufferUsage *add);
      26                 : static void WalUsageAdd(WalUsage *dst, WalUsage *add);
      27                 : 
      28                 : 
      29                 : /* Allocate new instrumentation structure(s) */
      30                 : Instrumentation *
      31 CBC       31709 : InstrAlloc(int n, int instrument_options, bool async_mode)
      32                 : {
      33                 :     Instrumentation *instr;
      34                 : 
      35                 :     /* initialize all fields to zeroes, then modify as needed */
      36           31709 :     instr = palloc0(n * sizeof(Instrumentation));
      37           31709 :     if (instrument_options & (INSTRUMENT_BUFFERS | INSTRUMENT_TIMER | INSTRUMENT_WAL))
      38                 :     {
      39           29490 :         bool        need_buffers = (instrument_options & INSTRUMENT_BUFFERS) != 0;
      40           29490 :         bool        need_wal = (instrument_options & INSTRUMENT_WAL) != 0;
      41           29490 :         bool        need_timer = (instrument_options & INSTRUMENT_TIMER) != 0;
      42                 :         int         i;
      43                 : 
      44           58980 :         for (i = 0; i < n; i++)
      45                 :         {
      46           29490 :             instr[i].need_bufusage = need_buffers;
      47           29490 :             instr[i].need_walusage = need_wal;
      48           29490 :             instr[i].need_timer = need_timer;
      49           29490 :             instr[i].async_mode = async_mode;
      50                 :         }
      51                 :     }
      52                 : 
      53           31709 :     return instr;
      54                 : }
      55                 : 
      56                 : /* Initialize a pre-allocated instrumentation structure. */
      57                 : void
      58             825 : InstrInit(Instrumentation *instr, int instrument_options)
      59                 : {
      60             825 :     memset(instr, 0, sizeof(Instrumentation));
      61             825 :     instr->need_bufusage = (instrument_options & INSTRUMENT_BUFFERS) != 0;
      62             825 :     instr->need_walusage = (instrument_options & INSTRUMENT_WAL) != 0;
      63             825 :     instr->need_timer = (instrument_options & INSTRUMENT_TIMER) != 0;
      64             825 : }
      65                 : 
      66                 : /* Entry to a plan node */
      67                 : void
      68         6657992 : InstrStartNode(Instrumentation *instr)
      69                 : {
      70        11922874 :     if (instr->need_timer &&
      71         5264882 :         !INSTR_TIME_SET_CURRENT_LAZY(instr->starttime))
      72 UBC           0 :         elog(ERROR, "InstrStartNode called twice in a row");
      73                 : 
      74                 :     /* save buffer usage totals at node entry, if needed */
      75 CBC     6657992 :     if (instr->need_bufusage)
      76          142804 :         instr->bufusage_start = pgBufferUsage;
      77                 : 
      78         6657992 :     if (instr->need_walusage)
      79           52594 :         instr->walusage_start = pgWalUsage;
      80         6657992 : }
      81                 : 
      82                 : /* Exit from a plan node */
      83                 : void
      84         6656902 : InstrStopNode(Instrumentation *instr, double nTuples)
      85                 : {
      86         6656902 :     double      save_tuplecount = instr->tuplecount;
      87                 :     instr_time  endtime;
      88                 : 
      89                 :     /* count the returned tuples */
      90         6656902 :     instr->tuplecount += nTuples;
      91                 : 
      92                 :     /* let's update the time only if the timer was requested */
      93         6656902 :     if (instr->need_timer)
      94                 :     {
      95         5263798 :         if (INSTR_TIME_IS_ZERO(instr->starttime))
      96 UBC           0 :             elog(ERROR, "InstrStopNode called without start");
      97                 : 
      98 CBC     5263798 :         INSTR_TIME_SET_CURRENT(endtime);
      99         5263798 :         INSTR_TIME_ACCUM_DIFF(instr->counter, endtime, instr->starttime);
     100                 : 
     101         5263798 :         INSTR_TIME_SET_ZERO(instr->starttime);
     102                 :     }
     103                 : 
     104                 :     /* Add delta of buffer usage since entry to node's totals */
     105         6656902 :     if (instr->need_bufusage)
     106          141720 :         BufferUsageAccumDiff(&instr->bufusage,
     107          141720 :                              &pgBufferUsage, &instr->bufusage_start);
     108                 : 
     109         6656902 :     if (instr->need_walusage)
     110           51510 :         WalUsageAccumDiff(&instr->walusage,
     111           51510 :                           &pgWalUsage, &instr->walusage_start);
     112                 : 
     113                 :     /* Is this the first tuple of this cycle? */
     114         6656902 :     if (!instr->running)
     115                 :     {
     116           44601 :         instr->running = true;
     117           44601 :         instr->firsttuple = INSTR_TIME_GET_DOUBLE(instr->counter);
     118                 :     }
     119                 :     else
     120                 :     {
     121                 :         /*
     122                 :          * In async mode, if the plan node hadn't emitted any tuples before,
     123                 :          * this might be the first tuple
     124                 :          */
     125         6612301 :         if (instr->async_mode && save_tuplecount < 1.0)
     126 UBC           0 :             instr->firsttuple = INSTR_TIME_GET_DOUBLE(instr->counter);
     127                 :     }
     128 CBC     6656902 : }
     129                 : 
     130                 : /* Update tuple count */
     131                 : void
     132 UBC           0 : InstrUpdateTupleCount(Instrumentation *instr, double nTuples)
     133                 : {
     134                 :     /* count the returned tuples */
     135               0 :     instr->tuplecount += nTuples;
     136               0 : }
     137                 : 
     138                 : /* Finish a run cycle for a plan node */
     139                 : void
     140 CBC       45444 : InstrEndLoop(Instrumentation *instr)
     141                 : {
     142                 :     double      totaltime;
     143                 : 
     144                 :     /* Skip if nothing has happened, or already shut down */
     145           45444 :     if (!instr->running)
     146             971 :         return;
     147                 : 
     148           44473 :     if (!INSTR_TIME_IS_ZERO(instr->starttime))
     149 UBC           0 :         elog(ERROR, "InstrEndLoop called on running node");
     150                 : 
     151                 :     /* Accumulate per-cycle statistics into totals */
     152 CBC       44473 :     totaltime = INSTR_TIME_GET_DOUBLE(instr->counter);
     153                 : 
     154           44473 :     instr->startup += instr->firsttuple;
     155           44473 :     instr->total += totaltime;
     156           44473 :     instr->ntuples += instr->tuplecount;
     157           44473 :     instr->nloops += 1;
     158                 : 
     159                 :     /* Reset for next cycle (if any) */
     160           44473 :     instr->running = false;
     161           44473 :     INSTR_TIME_SET_ZERO(instr->starttime);
     162           44473 :     INSTR_TIME_SET_ZERO(instr->counter);
     163           44473 :     instr->firsttuple = 0;
     164           44473 :     instr->tuplecount = 0;
     165                 : }
     166                 : 
     167                 : /* aggregate instrumentation information */
     168                 : void
     169            1994 : InstrAggNode(Instrumentation *dst, Instrumentation *add)
     170                 : {
     171            1994 :     if (!dst->running && add->running)
     172                 :     {
     173 UBC           0 :         dst->running = true;
     174               0 :         dst->firsttuple = add->firsttuple;
     175                 :     }
     176 CBC        1994 :     else if (dst->running && add->running && dst->firsttuple > add->firsttuple)
     177 UBC           0 :         dst->firsttuple = add->firsttuple;
     178                 : 
     179 CBC        1994 :     INSTR_TIME_ADD(dst->counter, add->counter);
     180                 : 
     181            1994 :     dst->tuplecount += add->tuplecount;
     182            1994 :     dst->startup += add->startup;
     183            1994 :     dst->total += add->total;
     184            1994 :     dst->ntuples += add->ntuples;
     185            1994 :     dst->ntuples2 += add->ntuples2;
     186            1994 :     dst->nloops += add->nloops;
     187            1994 :     dst->nfiltered1 += add->nfiltered1;
     188            1994 :     dst->nfiltered2 += add->nfiltered2;
     189                 : 
     190                 :     /* Add delta of buffer usage since entry to node's totals */
     191            1994 :     if (dst->need_bufusage)
     192              48 :         BufferUsageAdd(&dst->bufusage, &add->bufusage);
     193                 : 
     194            1994 :     if (dst->need_walusage)
     195 UBC           0 :         WalUsageAdd(&dst->walusage, &add->walusage);
     196 CBC        1994 : }
     197                 : 
     198                 : /* note current values during parallel executor startup */
     199                 : void
     200            1298 : InstrStartParallelQuery(void)
     201                 : {
     202            1298 :     save_pgBufferUsage = pgBufferUsage;
     203            1298 :     save_pgWalUsage = pgWalUsage;
     204            1298 : }
     205                 : 
     206                 : /* report usage after parallel executor shutdown */
     207                 : void
     208            1295 : InstrEndParallelQuery(BufferUsage *bufusage, WalUsage *walusage)
     209                 : {
     210            1295 :     memset(bufusage, 0, sizeof(BufferUsage));
     211            1295 :     BufferUsageAccumDiff(bufusage, &pgBufferUsage, &save_pgBufferUsage);
     212            1295 :     memset(walusage, 0, sizeof(WalUsage));
     213            1295 :     WalUsageAccumDiff(walusage, &pgWalUsage, &save_pgWalUsage);
     214            1295 : }
     215                 : 
     216                 : /* accumulate work done by workers in leader's stats */
     217                 : void
     218            1295 : InstrAccumParallelQuery(BufferUsage *bufusage, WalUsage *walusage)
     219                 : {
     220            1295 :     BufferUsageAdd(&pgBufferUsage, bufusage);
     221            1295 :     WalUsageAdd(&pgWalUsage, walusage);
     222            1295 : }
     223                 : 
     224                 : /* dst += add */
     225                 : static void
     226            1343 : BufferUsageAdd(BufferUsage *dst, const BufferUsage *add)
     227                 : {
     228            1343 :     dst->shared_blks_hit += add->shared_blks_hit;
     229            1343 :     dst->shared_blks_read += add->shared_blks_read;
     230            1343 :     dst->shared_blks_dirtied += add->shared_blks_dirtied;
     231            1343 :     dst->shared_blks_written += add->shared_blks_written;
     232            1343 :     dst->local_blks_hit += add->local_blks_hit;
     233            1343 :     dst->local_blks_read += add->local_blks_read;
     234            1343 :     dst->local_blks_dirtied += add->local_blks_dirtied;
     235            1343 :     dst->local_blks_written += add->local_blks_written;
     236            1343 :     dst->temp_blks_read += add->temp_blks_read;
     237            1343 :     dst->temp_blks_written += add->temp_blks_written;
     238            1343 :     INSTR_TIME_ADD(dst->blk_read_time, add->blk_read_time);
     239            1343 :     INSTR_TIME_ADD(dst->blk_write_time, add->blk_write_time);
     240            1343 :     INSTR_TIME_ADD(dst->temp_blk_read_time, add->temp_blk_read_time);
     241            1343 :     INSTR_TIME_ADD(dst->temp_blk_write_time, add->temp_blk_write_time);
     242            1343 : }
     243                 : 
     244                 : /* dst += add - sub */
     245                 : void
     246          162610 : BufferUsageAccumDiff(BufferUsage *dst,
     247                 :                      const BufferUsage *add,
     248                 :                      const BufferUsage *sub)
     249                 : {
     250          162610 :     dst->shared_blks_hit += add->shared_blks_hit - sub->shared_blks_hit;
     251          162610 :     dst->shared_blks_read += add->shared_blks_read - sub->shared_blks_read;
     252          162610 :     dst->shared_blks_dirtied += add->shared_blks_dirtied - sub->shared_blks_dirtied;
     253          162610 :     dst->shared_blks_written += add->shared_blks_written - sub->shared_blks_written;
     254          162610 :     dst->local_blks_hit += add->local_blks_hit - sub->local_blks_hit;
     255          162610 :     dst->local_blks_read += add->local_blks_read - sub->local_blks_read;
     256          162610 :     dst->local_blks_dirtied += add->local_blks_dirtied - sub->local_blks_dirtied;
     257          162610 :     dst->local_blks_written += add->local_blks_written - sub->local_blks_written;
     258          162610 :     dst->temp_blks_read += add->temp_blks_read - sub->temp_blks_read;
     259          162610 :     dst->temp_blks_written += add->temp_blks_written - sub->temp_blks_written;
     260          162610 :     INSTR_TIME_ACCUM_DIFF(dst->blk_read_time,
     261                 :                           add->blk_read_time, sub->blk_read_time);
     262          162610 :     INSTR_TIME_ACCUM_DIFF(dst->blk_write_time,
     263                 :                           add->blk_write_time, sub->blk_write_time);
     264          162610 :     INSTR_TIME_ACCUM_DIFF(dst->temp_blk_read_time,
     265                 :                           add->temp_blk_read_time, sub->temp_blk_read_time);
     266          162610 :     INSTR_TIME_ACCUM_DIFF(dst->temp_blk_write_time,
     267                 :                           add->temp_blk_write_time, sub->temp_blk_write_time);
     268          162610 : }
     269                 : 
     270                 : /* helper functions for WAL usage accumulation */
     271                 : static void
     272            1295 : WalUsageAdd(WalUsage *dst, WalUsage *add)
     273                 : {
     274            1295 :     dst->wal_bytes += add->wal_bytes;
     275            1295 :     dst->wal_records += add->wal_records;
     276            1295 :     dst->wal_fpi += add->wal_fpi;
     277            1295 : }
     278                 : 
     279                 : void
     280           86216 : WalUsageAccumDiff(WalUsage *dst, const WalUsage *add, const WalUsage *sub)
     281                 : {
     282           86216 :     dst->wal_bytes += add->wal_bytes - sub->wal_bytes;
     283           86216 :     dst->wal_records += add->wal_records - sub->wal_records;
     284           86216 :     dst->wal_fpi += add->wal_fpi - sub->wal_fpi;
     285           86216 : }
        

Generated by: LCOV version v1.16-55-g56c0a2a