@@ -2597,7 +2597,10 @@ ExecHashInitializeDSM(HashState *node, ParallelContext *pcxt)
2597
2597
size = offsetof(SharedHashInfo , hinstrument ) +
2598
2598
pcxt -> nworkers * sizeof (HashInstrumentation );
2599
2599
node -> shared_info = (SharedHashInfo * ) shm_toc_allocate (pcxt -> toc , size );
2600
+
2601
+ /* Each per-worker area must start out as zeroes. */
2600
2602
memset (node -> shared_info , 0 , size );
2603
+
2601
2604
node -> shared_info -> num_workers = pcxt -> nworkers ;
2602
2605
shm_toc_insert (pcxt -> toc , node -> ps .plan -> plan_node_id ,
2603
2606
node -> shared_info );
@@ -2616,22 +2619,33 @@ ExecHashInitializeWorker(HashState *node, ParallelWorkerContext *pwcxt)
2616
2619
if (!node -> ps .instrument )
2617
2620
return ;
2618
2621
2622
+ /*
2623
+ * Find our entry in the shared area, and set up a pointer to it so that
2624
+ * we'll accumulate stats there when shutting down or rebuilding the hash
2625
+ * table.
2626
+ */
2619
2627
shared_info = (SharedHashInfo * )
2620
2628
shm_toc_lookup (pwcxt -> toc , node -> ps .plan -> plan_node_id , false);
2621
2629
node -> hinstrument = & shared_info -> hinstrument [ParallelWorkerNumber ];
2622
2630
}
2623
2631
2624
2632
/*
2625
- * Copy instrumentation data from this worker's hash table (if it built one)
2626
- * to DSM memory so the leader can retrieve it. This must be done in an
2627
- * ExecShutdownHash() rather than ExecEndHash() because the latter runs after
2628
- * we've detached from the DSM segment.
2633
+ * Collect EXPLAIN stats if needed, saving them into DSM memory if
2634
+ * ExecHashInitializeWorker was called, or local storage if not. In the
2635
+ * parallel case, this must be done in ExecShutdownHash() rather than
2636
+ * ExecEndHash() because the latter runs after we've detached from the DSM
2637
+ * segment.
2629
2638
*/
2630
2639
void
2631
2640
ExecShutdownHash (HashState * node )
2632
2641
{
2642
+ /* Allocate save space if EXPLAIN'ing and we didn't do so already */
2643
+ if (node -> ps .instrument && !node -> hinstrument )
2644
+ node -> hinstrument = (HashInstrumentation * )
2645
+ palloc0 (sizeof (HashInstrumentation ));
2646
+ /* Now accumulate data for the current (final) hash table */
2633
2647
if (node -> hinstrument && node -> hashtable )
2634
- ExecHashGetInstrumentation (node -> hinstrument , node -> hashtable );
2648
+ ExecHashAccumInstrumentation (node -> hinstrument , node -> hashtable );
2635
2649
}
2636
2650
2637
2651
/*
@@ -2655,18 +2669,34 @@ ExecHashRetrieveInstrumentation(HashState *node)
2655
2669
}
2656
2670
2657
2671
/*
2658
- * Copy the instrumentation data from 'hashtable' into a HashInstrumentation
2659
- * struct.
2672
+ * Accumulate instrumentation data from 'hashtable' into an
2673
+ * initially-zeroed HashInstrumentation struct.
2674
+ *
2675
+ * This is used to merge information across successive hash table instances
2676
+ * within a single plan node. We take the maximum values of each interesting
2677
+ * number. The largest nbuckets and largest nbatch values might have occurred
2678
+ * in different instances, so there's some risk of confusion from reporting
2679
+ * unrelated numbers; but there's a bigger risk of misdiagnosing a performance
2680
+ * issue if we don't report the largest values. Similarly, we want to report
2681
+ * the largest spacePeak regardless of whether it happened in the same
2682
+ * instance as the largest nbuckets or nbatch. All the instances should have
2683
+ * the same nbuckets_original and nbatch_original; but there's little value
2684
+ * in depending on that here, so handle them the same way.
2660
2685
*/
2661
2686
void
2662
- ExecHashGetInstrumentation (HashInstrumentation * instrument ,
2663
- HashJoinTable hashtable )
2687
+ ExecHashAccumInstrumentation (HashInstrumentation * instrument ,
2688
+ HashJoinTable hashtable )
2664
2689
{
2665
- instrument -> nbuckets = hashtable -> nbuckets ;
2666
- instrument -> nbuckets_original = hashtable -> nbuckets_original ;
2667
- instrument -> nbatch = hashtable -> nbatch ;
2668
- instrument -> nbatch_original = hashtable -> nbatch_original ;
2669
- instrument -> space_peak = hashtable -> spacePeak ;
2690
+ instrument -> nbuckets = Max (instrument -> nbuckets ,
2691
+ hashtable -> nbuckets );
2692
+ instrument -> nbuckets_original = Max (instrument -> nbuckets_original ,
2693
+ hashtable -> nbuckets_original );
2694
+ instrument -> nbatch = Max (instrument -> nbatch ,
2695
+ hashtable -> nbatch );
2696
+ instrument -> nbatch_original = Max (instrument -> nbatch_original ,
2697
+ hashtable -> nbatch_original );
2698
+ instrument -> space_peak = Max (instrument -> space_peak ,
2699
+ hashtable -> spacePeak );
2670
2700
}
2671
2701
2672
2702
/*
0 commit comments