Frage

Ist es möglich, einzelne Methoden über Attribute in .NET zu profilieren?

Ich versuche zur Zeit einige der Flaschenhälse in einer großen Legacy-Anwendung zu lokalisieren, die starke Nutzung von statischen Methoden macht. einen Rahmen zu integrieren, ist einfach keine Option im Moment. Da die meisten der Anrufe statische Methoden, Schnittstellen und Dependency Injection sind nicht verfügbar. die Code-Hacking-Diagnose zu protokollieren ist keine gangbare Lösung entweder.

Ich weiß, dass einige Profilierwerkzeuge auf dem Markt gibt es, aber sie sind derzeit außerhalb des Haushalts. Im Idealfall würde ich in der Lage sein, mein eigenes benutzerdefiniertes Attribut zu erstellen, das einige grundlegenden Informationen über Methodeneintrag und Verfahren Ausfahrt würde loggt sein. Ich habe nie wirklich mit benutzerdefinierten gearbeitet Attribute so nicht nur die Einsicht in, wenn dies überhaupt möglich ist geschätzt würde.

Wenn möglich, würde Ich mag die Profilierung über eine Konfigurationsdatei aktivieren. Dies würde Profilierung über Modul- und Integrationstests unterstützen.

War es hilfreich?

Lösung

Sie können keine Attribute für verwenden, was Sie tun. Allerdings müssen Sie einige Möglichkeiten:

Erstens gibt viele der Profiler Tools aus (wie RedGate ANTS ) sind relativ billig ($ 200- $ 300), einfach zu bedienen und die meisten kostenlose Testzeiten von ein paar Wochen bieten - so können Sie sehen, ob sie Sie geben den Lift Sie jetzt brauchen, bevor Sie sich entscheiden, ob sie kaufen . Auch die .NET CLR Profiler ist kostenlos zum Download bereit.

Wenn das nicht möglich ist, ist Postsharp wahrscheinlich der einfachste Weg, eine solche Logik in den Code zu weben.

Schließlich, wenn Sie nicht Postsharp aus irgendeinem Grund verwenden können und Sie bereit sind Attribute, um Ihren Code zu gehen und hinzufügen, können Sie auch eine einfache Instrumentierung Block zu jeder Methode in Form eines mit Block hinzufügen:

public void SomeMethodToProfile()
{
    // following line collects information about current executing method
    // and logs it when the metric tracker is disposed of
    using(MetricTracker.Track(MethodBase.GetCurrentMethod()))
    { 
        // original code here...
    }
}

Eine typische MetricTracker Implementierung sieht wie folgt aus:

public sealed class MetricTracker : IDisposable
{
    private readonly string m_MethodName;
    private readonly Stopwatch m_Stopwatch;

    private MetricTracker( string methodName ) 
       { m_MethodName = methodName; m_Stopwatch = Stopwatch.StartNew(); }

    void IDisposable.Dispose()
       { m_Stopwatch.Stop(); LogToSomewhere(); }

    private void LogToSomewhere()
       { /* supply your own implementation here...*/ }

    public static MetricTracker Track( MethodBase mb )
       { return new MetricTracker( mb.Name ); }
}

Andere Tipps

Sie könnten verwenden Postsharp etwas Weberei zu tun, im Grunde drehen:

[Profiled]
public void Foo()
{
     DoSomeStuff();
}

in

public void Foo()
{
    Stopwatch sw = Stopwatch.StartNew();
    try
    {
        DoSomeStuff();
    }
    finally
    {
        sw.Stop();
        ProfileData.AddSample("Foo", sw.Elapsed);
    }
}

Tatsächlich an der Postsharp Dokumentation suchen, sollten Sie in der Lage sein verwenden Gibraltar (mit Postsharp) für diese, wenn Sie es sich leisten können. Ansonsten können Sie auch einen Tag am Ende verbringen oder so den Dreh Postsharp bekommen, aber es könnte noch gut sein lohnt sich.

Beachten Sie, dass ich weiß, Sie sagten, Sie nicht, einen Rahmen in die Code-Basis integrieren konnte es sich leisten, aber es ist nicht wie werden Sie wirklich sein „Integration“ so viel wie immer einige Postsharp post-kompilieren Transformationen auf Ihrem Code auszuführen.

Ich war auf der Suche nach etwas sehr ähnlich zu dem, was Sie beschrieben. Ich konnte nicht einen solchen Rahmen finden, so rollte ich meine eigenen. Ich sollte anmerken, dass dies sehr einfach , aber manchmal einfach gut!

Ich würde es beschreiben als Benchmarking-Unit-Tests erfüllt. Das Konzept ist Codeabschnitte zu isolieren, um Geschwindigkeit zu messen oder zu vergleichen.

Ein typisches Beispiel für das Attribut Verwendung als würde aussehen folgt:

[ProfileClass]
public class ForEachLoopBenchmarks
{
    [ProfileMethod]
    public void ForLoopBenchmark()
    {
        List<int> list = GetNumberList();

        for (int i = 0; i < list.Count; i++)
        {
        }
    }

    [ProfileMethod]
    public void ForEachLoopBenchmark()
    {
        List<int> list = GetNumberList();

        foreach (int i in list)
        {
        }
    }

    private List<int> GetNumberList()
    {
        List<int> list = new List<int>();
        for (int i = 0; i < 1000; i++)
        {
            list.Add(i);
        }
        return list;
    }
}

Sie dann eine Konsole app erstellen und den folgenden Code in die Haupt Methode einfügen und einen Verweis auf die Assembly hinzufügen, die die zuvor beschriebene Klasse enthalten, die mit den Attributen geschmückt ist. Die Ausführungszeit für jede Methode (run 1000 mal) wird dann auf die Konsole werden.

class Program
{
    static void Main(string[] args)
    {
        ProfileRunner rp = new ProfileRunner();
        rp.Run();
    }
}

Die Konsolenausgabe würde wie folgt aussehen:

Konsolenausgabe

Sie müssen anhand der pUnit.dll auf die Konsolenanwendung und die Klassenbibliothek hinzufügen, die die Methoden mit den Attributen markiert enthalten.

Sie können als Paket erhalten diese von Nuget hier .

Nuget Befehl: PM> Install-Package Punit

Wenn Sie lieber die vollständigen Quellcode, können Sie es finden auf Github hier .

I basiert die Methode, die die Ausführungszeit auf diese Frage tatsächlich misst: https://stackoverflow.com/a/1048708/1139752

ich die Umsetzung im Detail in dem folgenden Blog-Post .

Es gibt auch einige free-Profiler-Tools, die es bei der Suche wert sein könnte.

ich Performance-Tuning in C #. Alles was ich brauche ist diese Technik. Es ist keine große Sache.

Es basiert auf einer einfachen Idee. Wenn Sie sich für viel länger als nötig warten, das bedeutet, dass ein Teil des Programms auch viel länger als nötig wartet, für etwas, das nicht wirklich braucht getan werden.

Und wie ist es warten? Fast immer, in einer Call-Website, auf dem Call-Stack.

Also, wenn Sie es nur anhalten, während Sie warten, und Blick auf den Call-Stack, werden Sie sehen, was es wartet darauf, und wenn es nicht wirklich notwendig ist (was es in der Regel nicht), werden Sie sehen, warum sofort.

Sie nur eine Probe nicht vertrauen - tut es ein paar Mal. Alles, was auf mehr als einen Stapel Probe zeigt nach oben ist etwas, das, wenn man etwas dagegen tun kann, wird eine Menge Zeit sparen.

Sie sehen also, es geht nicht um Timing-Funktionen oder zu zählen, wie oft sie aufgerufen werden. Es geht darum, auf dem Programm unangemeldet ein paar Mal fallen in, und fragen sie, was sie tut und warum. Wenn etwas verschwendet 80% (oder 20% oder was auch immer) der Zeit, dann 80% der Zyklen in dem Zustand sein, der nicht wirklich notwendig ist, so fällt in nur auf sie und einen Blick darauf werfen. Sie haben keine Präzisionsmessung benötigen.

Es funktioniert mit großen Problemen. Es funktioniert auch mit kleinen Problemen. Und wenn Sie das Ganze mehr als einmal tun, da das Programm schnell bekommt, werden die kleinen Probleme relativ größer und leichter zu finden.

Sie können dies über Attribute nicht umsetzen, es sei denn, Sie Aspect Oriented Programming über so etwas wie Postsharp dies zu erreichen.

Sie könnten bedingte Logik setzen es in, basierend auf einer define (möglicherweise in einer Build-Konfiguration festgelegt), jedoch. Diese ein- oder ausschalten Ihre Protokollierung aktivieren könnte mit Timings auf Ihren aktuelle Kompilierung Einstellungen abhängig.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top