diff --git a/Trigger/TrigCost/TrigCostAnalysis/python/CostMetadataUtil.py b/Trigger/TrigCost/TrigCostAnalysis/python/CostMetadataUtil.py
new file mode 100644
index 0000000000000000000000000000000000000000..b30ad08d4adc9de81a7438417174b2535dafb5e8
--- /dev/null
+++ b/Trigger/TrigCost/TrigCostAnalysis/python/CostMetadataUtil.py
@@ -0,0 +1,96 @@
+#!/usr/bin/env python
+#
+#  Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
+#
+
+'''
+@file CostMetadataUtil.py
+@brief Helper functions to create cost metadata json file based on input ntuple
+        and histogram under/overflows
+'''
+
+from AthenaCommon.Logging import logging
+log = logging.getLogger('CostAnalysisPostProcessing')
+
+
+def saveMetadata(inputFile, userDetails, processingWarnings=[]):
+    ''' @brief Save metadata from ntuple to json file
+    '''
+    import json
+
+    metatree = inputFile.Get("metadata")
+    if metatree is None:
+        return None
+
+    metatree.GetEntry(0)
+    metadata = []
+
+    metadata.append({'runNumber' : metatree.runNumber})
+    metadata.append({'AtlasProject' : str(metatree.AtlasProject)})
+    metadata.append({'AtlasVersion' : str(metatree.AtlasVersion)})
+
+    metadata.append({'ChainMonitor' : metatree.ChainMonitor})
+    metadata.append({'AlgorithmMonitor' : metatree.AlgorithmMonitor})
+    metadata.append({'AlgorithmClassMonitor' : metatree.AlgorithmClassMonitor})
+    metadata.append({'ROSMonitor' : metatree.ROSMonitor})
+    metadata.append({'GlobalsMonitor' : metatree.GlobalsMonitor})
+    metadata.append({'ThreadMonitor' : metatree.ThreadMonitor})
+
+    metadata.append({'AdditionalHashMap' : str(metatree.AdditionalHashMap)})
+    metadata.append({'DoEBWeighting' : metatree.DoEBWeighting})
+    metadata.append({'BaseEventWeight' : metatree.BaseEventWeight})
+
+    metadata.append({'HLTMenu' : json.loads(str(metatree.HLTMenu))})
+
+    metadata.append({'Details' : userDetails})
+
+    metadata.append({'Histogram under/overflows' : processingWarnings})
+
+    with open('metadata.json', 'w') as outMetaFile:
+        metafile = {}
+        metafile['text'] = 'metadata'
+        metafile['children'] = metadata
+        json.dump(obj=metafile, fp=outMetaFile, indent=2, sort_keys=True)
+
+
+def createOverflowSummary(warnings):
+    ''' @brief Create summery of under/overflows based on passed warnings
+    '''
+    histogramStats = {}
+    log.debug("Received %s warnings", len(warnings))
+    for entry in warnings:
+        histFullName = entry.split(" ")[-1]
+        histType = histFullName.split("_")[-2] + "_" + histFullName.split("_")[-1]
+        summary = entry.split(" ")[-1].split("HLT")[0] + "HLT"
+
+        if "LumiBlock" in summary:
+            # format LumiBlock_000XX_SummaryName...
+            summary = summary.split('_', 1)[1]
+            summary = summary.split('_', 1)[1]
+        elif "All" in summary:
+            # format All_SummaryName...
+            summary = summary.split('_', 1)[1]
+
+        entryName = summary + "_" + histType
+        if entryName in histogramStats:
+            histogramStats[entryName] += 1
+        else:
+            histogramStats[entryName] = 1
+
+    histogramStatsStr = []
+    for name, value in histogramStats.items():
+        histogramStatsStr.append("{0}: {1} histograms with over/underflows".format(name, value))
+
+    return {"Summary": histogramStatsStr}
+
+
+def ignoreUnderflow(histogramName):
+    ''' @brief Filter out the histograms to ignore in underflow check
+    '''
+
+    # Ignore time histograms for filters
+    if "FStep" in histogramName and "Time" in histogramName:
+        log.debug("Filter %s underflow will be ignored", histogramName)
+        return True
+
+    return False
diff --git a/Trigger/TrigCost/TrigCostAnalysis/python/TableConstructorBase.py b/Trigger/TrigCost/TrigCostAnalysis/python/TableConstructorBase.py
index f56ae8eec038445945928bc1299aa6c85c2612f4..e8d9c851a966f9954fa6353399ece6a14751a5b7 100644
--- a/Trigger/TrigCost/TrigCostAnalysis/python/TableConstructorBase.py
+++ b/Trigger/TrigCost/TrigCostAnalysis/python/TableConstructorBase.py
@@ -10,7 +10,7 @@
 
 from math import fabs
 from collections import OrderedDict
-
+from TrigCostAnalysis.CostMetadataUtil import ignoreUnderflow
 from AthenaCommon.Logging import logging
 log = logging.getLogger('TableConstructor')
 
@@ -136,7 +136,7 @@ class TableConstructorBase:
 
                 underflowThreshold = self.underflowThreshold * histIntegral
                 underflow = hist.GetBinContent(0)
-                if underflow > underflowThreshold:
+                if underflow > underflowThreshold and not ignoreUnderflow(fullHistName):
                     log.warning("Histogram {0} contains underflow of {1}".format(fullHistName, underflow))
                     self.warningMsg.append("Underflow of {0} ({1} histogram integral) in {2}".format(underflow, histIntegral, fullHistName))
 
diff --git a/Trigger/TrigCost/TrigCostAnalysis/python/Util.py b/Trigger/TrigCost/TrigCostAnalysis/python/Util.py
index 538362e2858f89900454e8f3e5c6990b57a1dfd4..ca2f22332f37faeaa8bed5046287544257ff6c8c 100644
--- a/Trigger/TrigCost/TrigCostAnalysis/python/Util.py
+++ b/Trigger/TrigCost/TrigCostAnalysis/python/Util.py
@@ -10,48 +10,11 @@
 
 import ROOT
 from math import fabs
+from TrigCostAnalysis.CostMetadataUtil import createOverflowSummary
 from AthenaCommon.Logging import logging
 log = logging.getLogger('CostAnalysisPostProcessing')
 
 
-def saveMetadata(inputFile, userDetails, processingWarnings=[]):
-    import json
-
-    metatree = inputFile.Get("metadata")
-    if metatree is None:
-        return None
-
-    metatree.GetEntry(0)
-    metadata = []
-
-    metadata.append({'runNumber' : metatree.runNumber})
-    metadata.append({'AtlasProject' : str(metatree.AtlasProject)})
-    metadata.append({'AtlasVersion' : str(metatree.AtlasVersion)})
-
-    metadata.append({'ChainMonitor' : metatree.ChainMonitor})
-    metadata.append({'AlgorithmMonitor' : metatree.AlgorithmMonitor})
-    metadata.append({'AlgorithmClassMonitor' : metatree.AlgorithmClassMonitor})
-    metadata.append({'ROSMonitor' : metatree.ROSMonitor})
-    metadata.append({'GlobalsMonitor' : metatree.GlobalsMonitor})
-    metadata.append({'ThreadMonitor' : metatree.ThreadMonitor})
-
-    metadata.append({'AdditionalHashMap' : str(metatree.AdditionalHashMap)})
-    metadata.append({'DoEBWeighting' : metatree.DoEBWeighting})
-    metadata.append({'BaseEventWeight' : metatree.BaseEventWeight})
-
-    metadata.append({'HLTMenu' : json.loads(str(metatree.HLTMenu))})
-
-    metadata.append({'Details' : userDetails})
-
-    metadata.append({'Histogram under/overflows' : processingWarnings})
-
-    with open('metadata.json', 'w') as outMetaFile:
-        metafile = {}
-        metafile['text'] = 'metadata'
-        metafile['children'] = metadata
-        json.dump(obj=metafile, fp=outMetaFile, indent=2, sort_keys=True)
-
-
 def exploreTree(inputFile, dumpSummary=False, underflowThreshold=0.1, overflowThreshold=0.1):
     ''' @brief Explore ROOT Tree to find tables with histograms to be saved in csv
 
@@ -117,35 +80,6 @@ def exploreTree(inputFile, dumpSummary=False, underflowThreshold=0.1, overflowTh
     return processingWarnings + [summary]
 
 
-def createOverflowSummary(warnings):
-    histogramStats = {}
-    for entry in warnings:
-        histFullName = entry.split(" ")[-1]
-        histType = histFullName.split("_")[-2] + "_" + histFullName.split("_")[-1]
-        summary = entry.split(" ")[-1].split("HLT")[0] + "HLT"
-
-        if "LumiBlock" in summary:
-            # format LumiBlock_000XX_SummaryName...
-            summary = summary.split('_', 1)[1]
-            summary = summary.split('_', 1)[1]
-        elif "All" in summary:
-            # format All_SummaryName...
-            summary = summary.split('_', 1)[1]
-
-        entryName = summary + "_" + histType
-        if entryName in histogramStats:
-            histogramStats[entryName] += 1
-        else:
-            histogramStats[entryName] = 1
-
-    histogramStatsStr = []
-    for name, value in histogramStats.items():
-        histogramStatsStr.append("{0}: {1} histograms with over/underflows".format(name, value))
-
-    return {"Summary": histogramStatsStr}
-
-
-
 def getWalltime(inputFile, rootName):
     ''' @brief Extract walltime value from histogram
     
@@ -183,6 +117,7 @@ def getAlgorithmTotalTime(inputFile, rootName):
 
     return totalTime * 1e-3
 
+
 def convert(entry):
     ''' @brief Save entry number in scientific notation'''
     if type(entry) is float or type(entry) is int:
diff --git a/Trigger/TrigCost/TrigCostAnalysis/share/CostAnalysisPostProcessing.py b/Trigger/TrigCost/TrigCostAnalysis/share/CostAnalysisPostProcessing.py
index 9585448fa5757e69d614cbc307ddd0740f0c5c17..b7be6496d015d34c8ce832e104023087da9d6be6 100755
--- a/Trigger/TrigCost/TrigCostAnalysis/share/CostAnalysisPostProcessing.py
+++ b/Trigger/TrigCost/TrigCostAnalysis/share/CostAnalysisPostProcessing.py
@@ -10,7 +10,8 @@
 '''
 
 import ROOT
-from TrigCostAnalysis.Util import exploreTree, saveMetadata
+from TrigCostAnalysis.Util import exploreTree
+from TrigCostAnalysis.CostMetadataUtil import saveMetadata
 from AthenaCommon.Logging import logging
 log = logging.getLogger('CostAnalysisPostProcessing')
 
@@ -19,8 +20,8 @@ def main():
     parser = ArgumentParser()
     parser.add_argument('--file', default='TrigCostRoot_Results.root', help='Input ROOT file to generate output from')
     parser.add_argument('--userDetails', help='User supplied metadata string giving any extra details about this run.')
-    parser.add_argument('--underflowThreshold', default=0.5, help='Proportion of underflow entries to all entries (weighted) to save warning in metadata tree.')
-    parser.add_argument('--overflowThreshold', default=0.1, help='Proportion of overflow entries to all entries (weighted) to save warning in metadata tree.')
+    parser.add_argument('--underflowThreshold', default=0.5, help='Threshold of underflow percent value to save warning in metadata tree.')
+    parser.add_argument('--overflowThreshold', default=0.1, help='Threshold of underflow percent value to save warning in metadata tree.')
     parser.add_argument('--dumpAlgorithmSummary', action='store_true', help='Print algorithm\'s mean time of execution to the log file')     
     args = parser.parse_args()
     
@@ -32,6 +33,10 @@ def main():
     else:
         log.error("File %s not found", args.file)
 
+    # to speed up closing the ROOT file
+    ROOT.gROOT.GetListOfFiles().Remove(inputFile)
+    inputFile.Close()
+
 
 if __name__== "__main__":
-    main()
\ No newline at end of file
+    main()