(.Net) Простой способ использовать файлы с отображением в памяти.Как переменная - PullRequest
0 голосов
/ 24 марта 2019

Я занимаюсь разработкой веб-приложения ASP.NET.Требуется много оперативной памяти.Поэтому я думаю о файлах с отображенной памятью.

Но реализация файлов с отображенной памятью очень утомительна.Нужно использовать эти адреса памяти, операторы SizeOf и т. Д. (У меня заканчивается время).

Текущая система использует большой словарь для хранения этих больших объемов данных.Все классы [Сериализуемые]. Есть ли способ обернуть доступ к файлам, отображенным в память, как этот ,

(C# Psedo-code)    
var WrittingObject = new blablabla;
SetMMFVariable(name: "var1", value : WrittingObject);
var ReadingObject = GetMMFVariable(name: "var1");

Есть ли какие-либо коды переноса для файлов, отображаемых в памяти, в .NET?где мне не нужно беспокоиться об этих адресах памяти и прочем.

Ответы [ 2 ]

1 голос
/ 27 апреля 2019

Это был бы отличный кандидат для базы данных! Проблема, с которой вы сталкиваетесь, заключается в одновременной сериализации / десериализации больших объемов информации. Если вам нужно прочитать или обновить небольшой фрагмент информации, вам необходимо отсканировать весь файл, чтобы обновить ОДНУ запись. Это безумно дорого!

Обходной путь должен иметь некоторую структурированную модель данных. Вы можете либо распространить модель для чтения / записи, чтобы использовать множество небольших файлов в ОС (подверженных повреждению, проблемам с DISK, проблемам с разрешениями, множественному доступу и блокировкам файлов), чтобы обойти вышеуказанную проблему сериализации, либо вы можете перейти к реальной базе данных, которая позволит вам запрашивать и обновлять / вставлять необходимую информацию.

Для структурированной модели (c # хорош в этом) посмотрите на Sql Server Express https://docs.microsoft.com/en-us/sql/database-engine/configure-windows/sql-server-express-localdb?view=sql-server-2017

Для неструктурированной информации (json) посмотрите на что-то нереляционное, например, на couchbase https://docs.couchbase.com/dotnet-sdk/2.7/start-using-sdk.html

0 голосов
/ 13 июля 2019

Я сделал решение.Это немного грязный код.Это было связано с другими частями проекта.Но вы можете легко переносить его.

(код Visual Basic .NET)

Imports System.IO
Imports System.Runtime.Serialization.Formatters.Binary
Imports System.Web.UI

Public Module UserStates

Public Property CurrSessionVariableIndex As Integer
    Get

        Dim I As Integer
        If LDB.CustomData.TryGetValue("CurrSessionIndex", I) Then
            Return I
        Else
            LDB.CustomData("CurrSessionIndex") = 1
            Return I
        End If

    End Get
    Set(value As Integer)
        LDB.CustomData("CurrSessionIndex") = value
    End Set
End Property

Public Function NewSessionVariableIndex() As Integer

    CurrSessionVariableIndex += 1
    Return CurrSessionVariableIndex

End Function


Public PreferMemoryMapFiles As Boolean = True




Public ViewStatusBags As New Dictionary(Of Integer, Dictionary(Of String, Object))(300)
Public ViewStatusTimes As New Dictionary(Of Integer, DateTime)(300)

Public Sub SetViewVarRAM(ViewStateID As Integer, key As String, Obj As Object)
    Dim Bag As Dictionary(Of String, Object) = Nothing
    If ViewStatusBags.TryGetValue(ViewStateID, Bag) Then
        Try
            Bag(key) = Obj
        Catch ex As Exception
            Log($"Added new ViewBag.Var {ViewStateID}.{key}")
            Bag.Add(key, Obj)
        End Try
        ViewStatusTimes(ViewStateID) = Now
    Else
        Log($"Added new ViewBag {ViewStateID}")
        Bag = New Dictionary(Of String, Object)
        ViewStatusBags.Add(ViewStateID, Bag)
        ViewStatusTimes.Add(ViewStateID, Now)
        Bag.Add(key, Obj)

    End If

End Sub

Public Function GetViewVarRAM(ViewStateID As Integer, key As String) As Object
    Dim Bag As Dictionary(Of String, Object) = Nothing
    If ViewStatusBags.TryGetValue(ViewStateID, Bag) Then
        ViewStatusTimes(ViewStateID) = Now
        Try
            Return Bag(key)
        Catch ex As Exception
            Log($"Added new ViewBag.Var {ViewStateID}.{key}")
            Bag.Add(key, Nothing)
            Return Bag(key)
        End Try
    Else
        Log($"Added new ViewBag {ViewStateID}")
        Bag = New Dictionary(Of String, Object)
        ViewStatusBags.Add(ViewStateID, Bag)
        ViewStatusTimes.Add(ViewStateID, Now)

        Bag.Add(key, Nothing)
        Return Bag(key)
    End If
End Function



Public Function GetViewMMF(ViewStateID As Integer) As Dictionary(Of String, Object)
    Dim FS As FileStream = Nothing
    Dim BF As New BinaryFormatter

    GetFileStream(ViewStateID, FS)



    Dim Bag As Dictionary(Of String, Object)

    Try
        Bag = BF.Deserialize(FS)
    Catch ex As Exception
        If Not ex.Message.StartsWith("Attempting to deserialize an empty stream") Then
            LogError(ex, $"@MMF.Get : cannot Deserialize FS {ViewStateID}")
        End If
        FS.Flush()
        Bag = New Dictionary(Of String, Object)
        SetViewMMF(ViewStateID, Bag)
    End Try

    Try
        FS.Flush()
    Catch ex As Exception

    End Try

    Return Bag

End Function

Public Sub SetViewMMF(ViewStateID As Integer, Bag As Dictionary(Of String, Object))

    Dim FS As FileStream = Nothing
    Dim BF As New BinaryFormatter


    GetFileStream(ViewStateID, FS)


    Try
        BF.Serialize(FS, Bag)
    Catch ex As Exception
        LogError(ex, $"@MMF.Set : cannot Serialize FS {ViewStateID}")
        FS.Flush()
    End Try

    Try
        FS.Flush()
    Catch ex As Exception

    End Try
End Sub



Public MMFStreams As New Dictionary(Of Integer, FileStream)(100)
Public MMFStreamsTimes As New Dictionary(Of Integer, Date)(100)
Public FilePathMMFs As String

Private Sub GetFileStream(ByRef ViewStateID As Integer, ByRef FS As FileStream)
    If MMFStreams.TryGetValue(ViewStateID, FS) Then
        Try
            FS.Seek(0, SeekOrigin.Begin)
        Catch ex As Exception
            LogError(ex, $"@MMF.Set : cannot restart FS {ViewStateID}")
            FS = New FileStream(FilePathMMFs & ViewStateID.ToString & "-" & Rand.Next(100, 1000).ToString, FileMode.OpenOrCreate)
            FS.Seek(0, SeekOrigin.Begin)
            MMFStreams(ViewStateID) = FS
        End Try

        MMFStreamsTimes(ViewStateID) = Now
    Else

        Try
            FS = New FileStream(FilePathMMFs & ViewStateID.ToString, FileMode.OpenOrCreate)
            FS.Seek(0, SeekOrigin.Begin)
            MMFStreams.Add(ViewStateID, FS)
        Catch ex As Exception
            LogError(ex, $"@MMF.Set : cannot OpenOrCreate new FS {ViewStateID}")
            FS = New FileStream(FilePathMMFs & ViewStateID.ToString & "-" & Rand.Next(100, 1000).ToString, FileMode.OpenOrCreate)
            FS.Seek(0, SeekOrigin.Begin)
            MMFStreams.Add(ViewStateID, FS)

        End Try

        MMFStreamsTimes(ViewStateID) = Now
    End If
End Sub








Public Sub SetViewVarMMF(ViewStateID As Integer, key As String, Obj As Object)
    Dim FS As FileStream = Nothing
    Dim BF As New BinaryFormatter

    GetFileStream(ViewStateID, FS)
    Dim Bag As Dictionary(Of String, Object)

    Try
        Bag = BF.Deserialize(FS)
    Catch ex As Exception
        'LogError(ex, $"@MMF.SetViewVarMMF : cannot Deserialize FS {ViewStateID}. saved new bag")
        Bag = New Dictionary(Of String, Object)
    End Try

    FS.Seek(0, SeekOrigin.Begin)

    If Bag.ContainsKey(key) Then
        Bag(key) = Obj
    Else
        Bag.Add(key, Obj)
    End If


    Try
        BF.Serialize(FS, Bag)
    Catch ex As Exception
        LogError(ex, $"@MMF.SetViewVarMMF : cannot Serialize FS {ViewStateID}")
        FS.Flush()
    End Try

    Try
        FS.Flush()
    Catch ex As Exception

    End Try
End Sub



Public Function GetViewVarMMF(ViewStateID As Integer, key As String) As Object

    Dim Bag = GetViewMMF(ViewStateID)

    Dim Obj As Object = Nothing
    If Bag.TryGetValue(key, Obj) Then
        Return Obj
    Else

        Return Nothing
    End If

    Bag = Nothing

End Function






Public AllUserContainer As New Dictionary(Of Integer, UserContainer)(50)



Public Sub SetUserContainer(Usr As Integer, Con As UserContainer)
    Con.UserID = Usr
    If AllUserContainer.ContainsKey(Usr) Then
        AllUserContainer(Usr) = Con
        Con.Time = Now
    Else
        Log($"Added new user {Usr}")
        AllUserContainer.Add(Usr, Con)
        Con.Time = Now
    End If

End Sub

Public Function GetUserContainer(Usr As Integer) As UserContainer
    Dim Con As UserContainer = Nothing

    If AllUserContainer.TryGetValue(Usr, Con) Then
        Con.Time = Now
        Return Con
    Else
        Log($"Added new user {Usr}")
        Con = New UserContainer(Usr)
        AllUserContainer.Add(Usr, Con)
        Con.Time = Now
        Return Con
    End If
End Function





'___________________________________________________'


Public Sub SetViewVar(ViewStateID As Integer, key As String, Obj As Object)
    If PreferMemoryMapFiles Then
        SetViewVarMMF(ViewStateID, key, Obj)
    Else
        SetViewVarRAM(ViewStateID, key, Obj)
    End If
End Sub




Public Function GetViewVar(ViewStateID As Integer, key As String) As Object
    If PreferMemoryMapFiles Then
        Return GetViewVarMMF(ViewStateID, key)
    Else
        Return GetViewVarRAM(ViewStateID, key)
    End If
End Function


Public Sub RemoveMMF(ViewStateID As Integer)

    Dim FS As FileStream = Nothing

    If MMFStreams.TryGetValue(ViewStateID, FS) Then
        Try
            FS.Close()
        Catch ex As Exception

        End Try

    End If

End Sub

Public Sub RemoveUserContainer(Usr As Integer)
    If AllUserContainer.ContainsKey(Usr) Then
        AllUserContainer(Usr).Dispose()
        AllUserContainer.Remove(Usr)
        Log($"Removed user {Usr}")
    End If

End Sub



Public Sub DeleteUnusedMMFs()

    Dim Files = Directory.GetFiles(FilePathMMFs)

    Dim nowTime As Date = Now

    Dim nOfFiles = 0I

    For Each FilePath In Files
        Dim FileID = Path.GetFileName(FilePath)

        Dim Time As Date = Date.MinValue
        If UserStates.MMFStreamsTimes.TryGetValue(FileID, Time) Then
            If Time.AddMinutes(5) < nowTime Then
                Try
                    UserStates.MMFStreams(FileID).Close()
                Catch ex As Exception
                End Try
                Try
                    File.Delete(FilePath)
                    nOfFiles += 1
                Catch ex As Exception

                End Try
            End If

        Else
            Try
                File.Delete(FilePath)
                nOfFiles += 1
            Catch ex As Exception

            End Try
        End If

    Next


    Log($"@ViewStates.DeleteUnusedMMFs : {nOfFiles} deleted")



End Sub


'___________________________________________________'


Public Sub ClearUnusedViewStates()

    Dim BeforeRAM = (My.Application.Info.WorkingSet / 1024) / 1024

    Dim CurrTime = Now

    Dim ToRemove As New List(Of Integer)
    Dim ViewEntries As Integer
    Dim UsrEntries As Integer

    If ViewStatusBags.Count = 0 Then
        GoTo RemoveusrsLbl
    End If

    For i = ViewStatusBags.Count - 1 To 0 Step -1
        Dim Time = ViewStatusTimes.ElementAt(i).Value

        If Time.AddMinutes(5) < CurrTime Then
            ToRemove.Add(ViewStatusBags.ElementAt(i).Key)
        End If
    Next

    ViewEntries = ToRemove.Count
    For Each i In ToRemove
        ViewStatusBags.Remove(i)
    Next


 RemoveusrsLbl:
    If AllUserContainer.Count = 0 Then
        GoTo Final
    End If

    For i = AllUserContainer.Count - 1 To 0 Step -1

        If AllUserContainer(i).Time.AddMinutes(15) < CurrTime Then
            AllUserContainer.Remove(AllUserContainer(i).UserID)
            UsrEntries += 1
        End If
    Next



Final:

    GC.Collect()


    Dim AfterRAM = (My.Application.Info.WorkingSet / 1024) / 1024


    Log($"@ViewStates : {ViewEntries} Unused ViewStates Cleared. {UsrEntries} inactive users cleared. {AfterRAM - BeforeRAM} MB Cleared. ")

End Sub

End Module

(код C #) (переведено)

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Security;
using System.Text;
using System.Threading.Tasks;
using Microsoft.VisualBasic;
using System.Runtime.Serialization.Formatters.Binary;
using System.Web.UI;

public static class UserStates
{
    public static int CurrSessionVariableIndex
    {
        get
        {
            int I;
            if (LDB.CustomData.TryGetValue("CurrSessionIndex", I))
                return I;
            else
            {
                LDB.CustomData("CurrSessionIndex") = 1;
                return I;
            }
        }
        set
        {
            LDB.CustomData("CurrSessionIndex") = value;
        }
    }

    public static int NewSessionVariableIndex()
    {
        CurrSessionVariableIndex += 1;
        return CurrSessionVariableIndex;
    }


    public static bool PreferMemoryMapFiles = true;




    public static Dictionary<int, Dictionary<string, object>> ViewStatusBags = new Dictionary<int, Dictionary<string, object>>(300);
    public static Dictionary<int, DateTime> ViewStatusTimes = new Dictionary<int, DateTime>(300);

    public static void SetViewVarRAM(int ViewStateID, string key, object Obj)
    {
        Dictionary<string, object> Bag = null;
        if (ViewStatusBags.TryGetValue(ViewStateID, out Bag))
        {
            try
            {
                Bag[key] = Obj;
            }
            catch (Exception ex)
            {
                Log($"Added new ViewBag.Var {ViewStateID}.{key}");
                Bag.Add(key, Obj);
            }
            ViewStatusTimes[ViewStateID] = DateTime.Now;
        }
        else
        {
            Log($"Added new ViewBag {ViewStateID}");
            Bag = new Dictionary<string, object>();
            ViewStatusBags.Add(ViewStateID, Bag);
            ViewStatusTimes.Add(ViewStateID, DateTime.Now);
            Bag.Add(key, Obj);
        }
    }

    public static object GetViewVarRAM(int ViewStateID, string key)
    {
        Dictionary<string, object> Bag = null;
        if (ViewStatusBags.TryGetValue(ViewStateID, out Bag))
        {
            ViewStatusTimes[ViewStateID] = DateTime.Now;
            try
            {
                return Bag[key];
            }
            catch (Exception ex)
            {
                Log($"Added new ViewBag.Var {ViewStateID}.{key}");
                Bag.Add(key, null);
                return Bag[key];
            }
        }
        else
        {
            Log($"Added new ViewBag {ViewStateID}");
            Bag = new Dictionary<string, object>();
            ViewStatusBags.Add(ViewStateID, Bag);
            ViewStatusTimes.Add(ViewStateID, DateTime.Now);

            Bag.Add(key, null);
            return Bag[key];
        }
    }



    public static Dictionary<string, object> GetViewMMF(int ViewStateID)
    {
        FileStream FS = null;
        BinaryFormatter BF = new BinaryFormatter();

        GetFileStream(ref ViewStateID, ref FS);



        Dictionary<string, object> Bag;

        try
        {
            Bag = BF.Deserialize(FS);
        }
        catch (Exception ex)
        {
            if (!ex.Message.StartsWith("Attempting to deserialize an empty stream"))
                LogError(ex, $"@MMF.Get : cannot Deserialize FS {ViewStateID}");
            FS.Flush();
            Bag = new Dictionary<string, object>();
            SetViewMMF(ViewStateID, Bag);
        }

        try
        {
            FS.Flush();
        }
        catch (Exception ex)
        {
        }

        return Bag;
    }

    public static void SetViewMMF(int ViewStateID, Dictionary<string, object> Bag)
    {
        FileStream FS = null;
        BinaryFormatter BF = new BinaryFormatter();


        GetFileStream(ref ViewStateID, ref FS);


        try
        {
            BF.Serialize(FS, Bag);
        }
        catch (Exception ex)
        {
            LogError(ex, $"@MMF.Set : cannot Serialize FS {ViewStateID}");
            FS.Flush();
        }

        try
        {
            FS.Flush();
        }
        catch (Exception ex)
        {
        }
    }



    public static Dictionary<int, FileStream> MMFStreams = new Dictionary<int, FileStream>(100);
    public static Dictionary<int, DateTime> MMFStreamsTimes = new Dictionary<int, DateTime>(100);
    public static string FilePathMMFs;

    private static void GetFileStream(ref int ViewStateID, ref FileStream FS)
    {
        if (MMFStreams.TryGetValue(ViewStateID, out FS))
        {
            try
            {
                FS.Seek(0, SeekOrigin.Begin);
            }
            catch (Exception ex)
            {
                LogError(ex, $"@MMF.Set : cannot restart FS {ViewStateID}");
                FS = new FileStream(FilePathMMFs + ViewStateID.ToString() + "-" + Rand.Next(100, 1000).ToString, FileMode.OpenOrCreate);
                FS.Seek(0, SeekOrigin.Begin);
                MMFStreams[ViewStateID] = FS;
            }

            MMFStreamsTimes[ViewStateID] = DateTime.Now;
        }
        else
        {
            try
            {
                FS = new FileStream(FilePathMMFs + ViewStateID.ToString(), FileMode.OpenOrCreate);
                FS.Seek(0, SeekOrigin.Begin);
                MMFStreams.Add(ViewStateID, FS);
            }
            catch (Exception ex)
            {
                LogError(ex, $"@MMF.Set : cannot OpenOrCreate new FS {ViewStateID}");
                FS = new FileStream(FilePathMMFs + ViewStateID.ToString() + "-" + Rand.Next(100, 1000).ToString, FileMode.OpenOrCreate);
                FS.Seek(0, SeekOrigin.Begin);
                MMFStreams.Add(ViewStateID, FS);
            }

            MMFStreamsTimes[ViewStateID] = DateTime.Now;
        }
    }








    public static void SetViewVarMMF(int ViewStateID, string key, object Obj)
    {
        FileStream FS = null;
        BinaryFormatter BF = new BinaryFormatter();

        GetFileStream(ref ViewStateID, ref FS);
        Dictionary<string, object> Bag;

        try
        {
            Bag = BF.Deserialize(FS);
        }
        catch (Exception ex)
        {
            // LogError(ex, $"@MMF.SetViewVarMMF : cannot Deserialize FS {ViewStateID}. saved new bag")
            Bag = new Dictionary<string, object>();
        }

        FS.Seek(0, SeekOrigin.Begin);

        if (Bag.ContainsKey(key))
            Bag[key] = Obj;
        else
            Bag.Add(key, Obj);


        try
        {
            BF.Serialize(FS, Bag);
        }
        catch (Exception ex)
        {
            LogError(ex, $"@MMF.SetViewVarMMF : cannot Serialize FS {ViewStateID}");
            FS.Flush();
        }

        try
        {
            FS.Flush();
        }
        catch (Exception ex)
        {
        }
    }



    public static object GetViewVarMMF(int ViewStateID, string key)
    {
        var Bag = GetViewMMF(ViewStateID);

        object Obj = null;
        if (Bag.TryGetValue(key, out Obj))
            return Obj;
        else
            return null;

        Bag = null;
    }






    public static Dictionary<int, UserContainer> AllUserContainer = new Dictionary<int, UserContainer>(50);



    public static void SetUserContainer(int Usr, UserContainer Con)
    {
        Con.UserID = Usr;
        if (AllUserContainer.ContainsKey(Usr))
        {
            AllUserContainer[Usr] = Con;
            Con.Time = DateTime.Now;
        }
        else
        {
            Log($"Added new user {Usr}");
            AllUserContainer.Add(Usr, Con);
            Con.Time = DateTime.Now;
        }
    }

    public static UserContainer GetUserContainer(int Usr)
    {
        UserContainer Con = null/* TODO Change to default(_) if this is not a reference type */;

        if (AllUserContainer.TryGetValue(Usr, out Con))
        {
            Con.Time = DateTime.Now;
            return Con;
        }
        else
        {
            Log($"Added new user {Usr}");
            Con = new UserContainer(Usr);
            AllUserContainer.Add(Usr, Con);
            Con.Time = DateTime.Now;
            return Con;
        }
    }





    // ___________________________________________________'


    public static void SetViewVar(int ViewStateID, string key, object Obj)
    {
        if (PreferMemoryMapFiles)
            SetViewVarMMF(ViewStateID, key, Obj);
        else
            SetViewVarRAM(ViewStateID, key, Obj);
    }




    public static object GetViewVar(int ViewStateID, string key)
    {
        if (PreferMemoryMapFiles)
            return GetViewVarMMF(ViewStateID, key);
        else
            return GetViewVarRAM(ViewStateID, key);
    }


    public static void RemoveMMF(int ViewStateID)
    {
        FileStream FS = null;

        if (MMFStreams.TryGetValue(ViewStateID, out FS))
        {
            try
            {
                FS.Close();
            }
            catch (Exception ex)
            {
            }
        }
    }

    public static void RemoveUserContainer(int Usr)
    {
        if (AllUserContainer.ContainsKey(Usr))
        {
            AllUserContainer[Usr].Dispose();
            AllUserContainer.Remove(Usr);
            Log($"Removed user {Usr}");
        }
    }



    public static void DeleteUnusedMMFs()
    {
        var Files = Directory.GetFiles(FilePathMMFs);

        DateTime nowTime = DateTime.Now;

        var nOfFiles = 0;

        foreach (var FilePath in Files)
        {
            var FileID = Path.GetFileName(FilePath);

            DateTime Time = DateTime.MinValue;
            if (UserStates.MMFStreamsTimes.TryGetValue(FileID, out Time))
            {
                if (Time.AddMinutes(5) < nowTime)
                {
                    try
                    {
                        UserStates.MMFStreams[FileID].Close();
                    }
                    catch (Exception ex)
                    {
                    }
                    try
                    {
                        File.Delete(FilePath);
                        nOfFiles += 1;
                    }
                    catch (Exception ex)
                    {
                    }
                }
            }
            else
                try
                {
                    File.Delete(FilePath);
                    nOfFiles += 1;
                }
                catch (Exception ex)
                {
                }
        }


        Log($"@ViewStates.DeleteUnusedMMFs : {nOfFiles} deleted");
    }


    // ___________________________________________________'


    public static void ClearUnusedViewStates()
    {
        var BeforeRAM = (My.Application.Info.WorkingSet / (double)1024) / (double)1024;

        var CurrTime = DateTime.Now;

        List<int> ToRemove = new List<int>();
        int ViewEntries;
        int UsrEntries;

        if (ViewStatusBags.Count == 0)
            goto RemoveusrsLbl;

        for (var i = ViewStatusBags.Count - 1; i >= 0; i += -1)
        {
            var Time = ViewStatusTimes.ElementAt(i).Value;

            if (Time.AddMinutes(5) < CurrTime)
                ToRemove.Add(ViewStatusBags.ElementAt(i).Key);
        }

        ViewEntries = ToRemove.Count;
        foreach (var i in ToRemove)
            ViewStatusBags.Remove(i);


        RemoveusrsLbl:
        ;
        if (AllUserContainer.Count == 0)
            goto Final;

        for (var i = AllUserContainer.Count - 1; i >= 0; i += -1)
        {
            if (AllUserContainer[i].Time.AddMinutes(15) < CurrTime)
            {
                AllUserContainer.Remove(AllUserContainer[i].UserID);
                UsrEntries += 1;
            }
        }



    Final:
        ;
        GC.Collect();


        var AfterRAM = (My.Application.Info.WorkingSet / (double)1024) / (double)1024;


        Log($"@ViewStates : {ViewEntries} Unused ViewStates Cleared. {UsrEntries} inactive users cleared. {AfterRAM - BeforeRAM} MB Cleared. ");
    }
}
...