예제 #1
0
        /// <summary>
        /// Analyzes counts and churn of fingerprints, input lists, and optionally
        /// content sizes of sessions in the cache.
        /// </summary>
        /// <param name="sessionNameRegex">Acts as a filter for which sessions to include in the analysis.</param>
        /// <param name="analyzeContent">When true, analysis will include content sizing for each session.</param>
        /// <returns>SessionChurnInfo object for every session analyzed</returns>
        public IEnumerable <SessionChurnInfo> Analyze(Regex sessionNameRegex, bool analyzeContent)
        {
            Contract.Assume(sessionNameRegex != null);

            m_numSessions         = 0;
            m_numSessionsAnalyzed = 0;

            // Used to store every unique strong fingerprint for all sessions
            HashSet <StrongFingerprint> allStrongFingerprints = new HashSet <StrongFingerprint>();

            // Used to store strong fingerprints for a given session
            HashSet <StrongFingerprint> sessionStrongFingerprints = new HashSet <StrongFingerprint>();

            HashSet <WeakFingerprintHash> allWeakFingerprints = new HashSet <WeakFingerprintHash>();

            // Used to store every unique cas element for all sessions
            HashSet <CasHash> allCasHashes = new HashSet <CasHash>();

            // Used to store every unique cas entry for all sessions
            HashSet <CasHash> allCasEntries = new HashSet <CasHash>();

            IEnumerable <Task <string> > unorderedSessionNames = m_cache.EnumerateCompletedSessions();

            IOrderedEnumerable <string> orderedSessionNames = unorderedSessionNames.Select(stringTask => stringTask.Result)
                                                              .Where((sessionName) =>
            {
                m_numSessions++;
                if (sessionNameRegex.IsMatch(sessionName))
                {
                    m_numSessionsAnalyzed++;
                    return(true);
                }
                else
                {
                    return(false);
                }
            })
                                                              .OrderBy(sessionName => sessionName);

            // Dictionary of CAS entry sizes
            Dictionary <CasHash, long> contentSizeTable = new Dictionary <CasHash, long>();

            // Analyze each session in order
            foreach (string sessionName in orderedSessionNames)
            {
                Console.Error.WriteLine("Analyzing session {0}", sessionName);

                // Initialize counters for the current session
                int totalNumberStrongFingerprints  = 0;
                int numberUniqueWeakFingerprints   = 0;
                int numberUniqueStrongFingerprints = 0;
                int numberUniqueCasHashesOverTime  = 0;
                int numberCasHashNoItemsForSession = 0;
                int contentErrors = 0;

                // Clear the set of strong fingerprints in this next session.
                sessionStrongFingerprints.Clear();

                // Contains every unique cas hash for the current session
                HashSet <CasHash> sessionCasHashes = new HashSet <CasHash>();

                IEnumerable <Task <StrongFingerprint> > strongFingerprints = m_cache.EnumerateSessionStrongFingerprints(sessionName).Result;

                // Analyze each strong fingerprint
                foreach (Task <StrongFingerprint> strongFingerprintTask in strongFingerprints.OutOfOrderTasks())
                {
                    totalNumberStrongFingerprints++;

                    StrongFingerprint strongFingerprint = strongFingerprintTask.Result;

                    sessionStrongFingerprints.Add(strongFingerprint);

                    // Check if strong fingerprint has never been seen before
                    if (allStrongFingerprints.Add(strongFingerprint))
                    {
                        // New strong fingerprint so increment counter and add to collection
                        numberUniqueStrongFingerprints++;
                    }

                    if (allWeakFingerprints.Add(strongFingerprint.WeakFingerprint))
                    {
                        numberUniqueWeakFingerprints++;
                    }

                    CasHash casElement = strongFingerprint.CasElement;

                    // Check if the cas hash is the special no item value
                    if (casElement.Equals(CasHash.NoItem))
                    {
                        numberCasHashNoItemsForSession++;
                    }

                    // Collect unique CAS elements in the session
                    sessionCasHashes.Add(casElement);

                    // Check if cas hash has never been seen before for the whole cache
                    if (allCasHashes.Add(casElement))
                    {
                        numberUniqueCasHashesOverTime++;
                    }
                }

                SessionContentInfo sessionContentInfo = null;

                if (analyzeContent)
                {
                    // Contains every unique cash entry hash for the current session
                    var sessionCasEntries = new HashSet <CasHash>();

                    // Accumulate all the CasEntries for the session
                    foreach (var task in m_session.GetCacheEntries(sessionStrongFingerprints).OutOfOrderTasks(32))
                    {
                        var possibleCasEntries = task.Result;
                        if (possibleCasEntries.Succeeded)
                        {
                            var casEntries = possibleCasEntries.Result;
                            sessionCasEntries.UnionWith(casEntries);
                        }
                        else
                        {
                            Console.Error.WriteLine("Unable to get CasEntries: {0}", possibleCasEntries.Failure.DescribeIncludingInnerFailures());
                            ++contentErrors;
                        }
                    }

                    // Retrieve the content size for each new CasEntry.
                    foreach (var task in m_session.GetContentSizes(sessionCasEntries.Except(allCasEntries)).OutOfOrderTasks(32))
                    {
                        var tuple = task.Result;
                        contentSizeTable[tuple.Item1] = tuple.Item2;
                    }

                    // Accumulate the size of content we've already seen.
                    long totalContentSize = 0;
                    long newContentSize   = 0;
                    var  newContentCount  = 0;

                    foreach (var e in sessionCasEntries)
                    {
                        long length;

                        if (contentSizeTable.TryGetValue(e, out length))
                        {
                            if (ValidContentSize(length))
                            {
                                totalContentSize += length;

                                if (!allCasEntries.Contains(e))
                                {
                                    newContentSize  += length;
                                    newContentCount += 1;
                                    allCasEntries.Add(e);
                                }
                            }
                            else
                            {
                                Console.Error.WriteLine("Unable to find content length ({0}) for {1}", (ContentError)length, e);
                                ++contentErrors;
                            }
                        }
                        else
                        {
#pragma warning disable CA2201 // Do not raise reserved exception types
                            throw new ApplicationException($"No content length for {e}");
#pragma warning restore CA2201 // Do not raise reserved exception types
                        }
                    }

                    sessionContentInfo = new SessionContentInfo(
                        sessionCasEntries.Count,
                        totalContentSize,
                        newContentCount,
                        newContentSize,
                        contentErrors);
                }

                // Aggregate the counters and return the session's data
                SessionStrongFingerprintChurnInfo sessionStrongFingerprintChurnInfo =
                    new SessionStrongFingerprintChurnInfo(totalNumberStrongFingerprints, numberUniqueStrongFingerprints, numberUniqueWeakFingerprints);

                SessionInputListChurnInfo sessionInputListChurnInfo =
                    new SessionInputListChurnInfo(totalNumberStrongFingerprints, sessionCasHashes.Count, numberUniqueCasHashesOverTime, numberCasHashNoItemsForSession);

                yield return(new SessionChurnInfo(sessionName, sessionStrongFingerprintChurnInfo, sessionInputListChurnInfo, sessionContentInfo));
            }
        }
예제 #2
0
        private ContentBreakdownInfo AnalyzeSession(string name)
        {
            var casEntries          = new HashSet <CasHash>();
            var casElements         = new HashSet <CasHash>();
            var sfpSet              = new HashSet <StrongFingerprint>();
            var casElementSizeTable = new Dictionary <CasHash, long>();
            var casEntrySizeTable   = new Dictionary <CasHash, long>();
            int countSFP            = 0;
            int contentErrors       = 0;

            // Enumerate strong fingerprints for the session...
            IEnumerable <Task <StrongFingerprint> > strongFingerprints = m_cache.EnumerateSessionStrongFingerprints(name).Result;

            // ...and for each, accumulate the input lists as part of the info we'll report.
            foreach (Task <StrongFingerprint> strongFingerprintTask in strongFingerprints.OutOfOrderTasks())
            {
                ++countSFP;
                StrongFingerprint sfp = strongFingerprintTask.Result;

                // Grab the observed input list.
                CasHash casElement = sfp.CasElement;
                if (!casElement.Equals(CasHash.NoItem))
                {
                    casElements.Add(casElement);
                }

                // Remember the SFP for the content scan below, so we're not doing this enumeration twice.
                sfpSet.Add(sfp);
            }

            // Now query the content for the SFPs in the session
            foreach (var task in m_session.GetCacheEntries(sfpSet).OutOfOrderTasks())
            {
                var possibleCasEntries = task.Result;
                if (possibleCasEntries.Succeeded)
                {
                    casEntries.UnionWith(possibleCasEntries.Result);
                }
                else
                {
                    Console.Error.WriteLine("Unable to get CasEntries: {0}", possibleCasEntries.Failure.DescribeIncludingInnerFailures());
                    ++contentErrors;
                }
            }

            // With all the CAS entries in hand, get the sizes...
            foreach (var task in m_session.GetContentSizes(casEntries.Except(casEntrySizeTable.Keys)).OutOfOrderTasks())
            {
                var tuple = task.Result;
                casEntrySizeTable[tuple.Item1] = tuple.Item2;
            }

            // Get the sizes of the input lists.
            foreach (var task in m_session.GetContentSizes(casElements.Except(casElementSizeTable.Keys)).OutOfOrderTasks())
            {
                var tuple = task.Result;
                casElementSizeTable[tuple.Item1] = tuple.Item2;
            }

            return(new ContentBreakdownInfo(name, casElementSizeTable, casEntrySizeTable));
        }