mirror of
https://github.com/facebook/sapling.git
synced 2024-10-09 16:31:02 +03:00
b75516fcff
Summary: This diff removes `self.ui = ui` in metricscollector to address stale ui issues with chg. Also clean up unnecessary sample merges since there is only one collector per process. Test Plan: Run with `fastmanifest.debugmetrics=1` and confirm see lines like: [FM-METRICS] Begin metrics [FM-METRICS] kind: cachehitratio, kwargs: [('ratio', 100.0)] [FM-METRICS] kind: diffcachehitratio, kwargs: [('ratio', -1)] [FM-METRICS] kind: filesnotincachehitratio, kwargs: [('ratio', 0.0)] [FM-METRICS] End metrics Reviewers: #mercurial, ttung, lcharignon Reviewed By: lcharignon Subscribers: mjpieters Differential Revision: https://phabricator.intern.facebook.com/D3504442 Signature: t1:3504442:1467311563:5904bd06b210fa8550b2e1f7e85c2133ad7a1a0e
137 lines
5.0 KiB
Python
137 lines
5.0 KiB
Python
# metrics.py
|
|
#
|
|
# Copyright 2016 Facebook, Inc.
|
|
#
|
|
# This software may be used and distributed according to the terms of the
|
|
# GNU General Public License version 2 or any later version.
|
|
#
|
|
# To log a new metric, add it to the list FASTMANIFEST_METRICS
|
|
# Then from the code, use metrics.metricscollector.get(repo) or
|
|
# metrics.metricscollector.getfromui(ui) to get a metrics `collector`.
|
|
# call collector.recordsample(metricsname, key=value, key2=value2, ...) to
|
|
# record a samples.
|
|
#
|
|
# When the command ends the sample will be relayed with ui.log unless
|
|
# it is in the list FASTMANIFEST_DONOTREPORT_METRICS.
|
|
# You would put a metrics in that list if you do some computation with hit
|
|
# and are not interested in the individual sample but only their aggregation.
|
|
# For example, if you want to record the cache hit ratio, you can record
|
|
# all the cache hit and cache miss, not report them but compute and report their
|
|
# ratio.
|
|
#
|
|
# To debug metrics use fastmanifest.debugmetrics = True, this will print
|
|
# the metrics collected for each command with ui.status at the end of each
|
|
# command.
|
|
|
|
from mercurial import util
|
|
|
|
FASTMANIFEST_DONOTREPORT_METRICS = set([
|
|
"cachehit",
|
|
"diffcachehit",
|
|
"filesnotincachehit"
|
|
])
|
|
|
|
FASTMANIFEST_METRICS = set([
|
|
## Individual Metrics
|
|
# ondiskcachestats has information about the cache on disk
|
|
# => keys are "bytes", "entries", "limit" and "freespace", all numbers,
|
|
# freespace and limit are in MB
|
|
"ondiskcachestats",
|
|
# revsetsize is the number of revisions in the 'fastmanifesttocache()'
|
|
# => key is "size", a number
|
|
"revsetsize",
|
|
# trigger is what caused caching to trigger
|
|
# => keys is "source", one of ("commit", "remotenames", "bookmark")
|
|
"trigger",
|
|
# cacheoverflow, logs cache overflow event: not enough space in the
|
|
# cache to store revisions, it will inform us on how to resize the
|
|
# cache if needed
|
|
# => key is "hit", always True
|
|
"cacheoverflow",
|
|
# The three followings are metrics that will be aggregated as ratio
|
|
# they register cache hit and miss at different level: global, diff and
|
|
# during filesnotin operations
|
|
# => key is "hit", True or False, True is a cache hit, False a cache miss
|
|
"cachehit",
|
|
"diffcachehit",
|
|
"filesnotincachehit",
|
|
## Aggregate Metrics
|
|
# Cache hit ratio (global, diff and filesnotin), expressed as a percentage
|
|
# so between 0 and 100. -1 means no operations.
|
|
# => keys is "ratio", a number
|
|
# examples:
|
|
# -1 for cachehitratio => we never accessed a manifest for the command
|
|
# 30 for cachehitratio => 30% of manifest access hit the cache
|
|
# 45 for diffcachehitratio => 45% of manifest diffs hit the cache
|
|
"cachehitratio",
|
|
"diffcachehitratio",
|
|
"filesnotincachehitratio",
|
|
])
|
|
|
|
class metricscollector(object):
|
|
_instance = None
|
|
|
|
@classmethod
|
|
def get(cls):
|
|
if not cls._instance:
|
|
cls._instance = metricscollector()
|
|
return cls._instance
|
|
|
|
def __init__(self):
|
|
self.samples = []
|
|
|
|
def recordsample(self, kind, **kwargs):
|
|
assert kind in FASTMANIFEST_METRICS
|
|
self.samples.append((kind, kwargs))
|
|
|
|
def mergesamples(self, collector):
|
|
if collector is not self:
|
|
self.samples.extend(collector.samples)
|
|
return self
|
|
|
|
def _addaggregatesamples(self):
|
|
def _addhitratio(key, aggkey):
|
|
# Aggregate the cache hit and miss to build a hit ratio
|
|
# store the ratio as aggkey : {ratio: ratio} in self.samples
|
|
hit = len([s for s in self.samples
|
|
if s[0] == key and s[1]["hit"]])
|
|
miss = len([s for s in self.samples
|
|
if s[0] == key and not s[1]["hit"]])
|
|
if miss + hit == 0:
|
|
ratio = -1
|
|
else:
|
|
ratio=float(hit) * 100 / (miss + hit)
|
|
|
|
self.recordsample(aggkey, ratio=ratio)
|
|
|
|
_addhitratio("cachehit", "cachehitratio")
|
|
_addhitratio("diffcachehit", "diffcachehitratio")
|
|
_addhitratio("filesnotincachehit", "filesnotincachehitratio")
|
|
|
|
def logsamples(self, ui):
|
|
self._addaggregatesamples()
|
|
debug = ui.config("fastmanifest", "debugmetrics", False)
|
|
if debug:
|
|
ui.status(("[FM-METRICS] Begin metrics\n"))
|
|
|
|
for kind, kwargs in self.samples:
|
|
if kind in FASTMANIFEST_DONOTREPORT_METRICS:
|
|
continue
|
|
|
|
if debug:
|
|
dispkw = kwargs
|
|
# Not removing freespace and limit would make the output of
|
|
# test machine dependant
|
|
if "freespace" in kwargs:
|
|
del dispkw["freespace"]
|
|
if "limit" in kwargs:
|
|
del dispkw["limit"]
|
|
# Here we sort to make test output stable
|
|
ui.status(("[FM-METRICS] kind: %s, kwargs: %s\n"
|
|
% (kind, sorted(dispkw.items()))))
|
|
ui.log('fastmanifest-%s' % kind,
|
|
"", # ui.log requires a format string as args[0].
|
|
**kwargs)
|
|
if debug:
|
|
ui.status(("[FM-METRICS] End metrics\n"))
|