Ruby On Rails ist langsam ...?

7

Ich schreibe eine Webanwendung, um den Produktionsfluss einer Möbelfabrik zu überwachen. Es müssen tausend Daten verarbeitet werden. Bis jetzt habe ich RoR auf Mongrel + MySQL und es ist wirklich sehr langsam (2-4 Minuten für einige Ansichten). Wenn ich mir RoR-Logs ansehe, scheint es, dass Datenbankabfragen nicht langsam sind (0-10ms).

Ist RoR langsam, wenn Datenbankdaten in Objekte konvertiert werden? Ist Mongrel langsam?

Bearbeiten : Das erste war: Ich war im Entwickler. env. In der Produktionsumgebung dauert die langsamste Ansicht 2 Minuten (was bei einem guten Computer weniger als 1 Minute beträgt, meine ist 5 Jahre alt). Mit Ruby-prof und ein bisschen gesunden Menschenverstand habe ich herausgefunden, welche Methoden die Anwendung verlangsamen. Das Problem ist, dass einzelne SQL-Abfragen in Schleifen in großen Datensätzen aufgerufen werden:

%Vor%

Hier sind Ruby-prof Ergebnisse zu diesen Methoden:

%Vor%

Problem ist: Ich kann diese einzelnen Abfragen nicht wirklich vermeiden. Ich habe tausend Ereignisse, aus denen ich komplexe Daten berechnen muss. Im Moment verwende ich memcached für diese Methoden, die OK ist, es sei denn, Sie sind der erste, der die Seite anfordert.

    
Giann 19.02.2009, 17:48
quelle

11 Antworten

17

Ich stimme allen anderen zu. Sie müssen profilieren. Es hat keinen Sinn, etwas an Ihrem Code zu tun, bis Sie wissen, was die Langsamkeit verursacht. Der Versuch, ein Problem zu lösen, ohne die Ursache zu verstehen, ist so, als ob man sich krank fühlt und sich dazu entschließt, viel zu operieren, bis man sich besser fühlt. Diagnostizieren Sie zuerst Ihr Problem. Es kann sich um eine kleine Netzwerkeinstellung oder um eine fehlerhafte Zeile in Ihrem Code handeln.

Einige Tipps zum Profiling:

Profil Ihrer Rails-Anwendung

>

Performance Testing Rails-Anwendungen

In der Forge - Profiling Rails-Anwendungen

Sobald Sie den Flaschenhals gefunden haben, können Sie herausfinden, was zu tun ist.

Ich empfehle diese Videos: Railslab Scaling Rails

Überarbeitet jetzt basierend auf prof-Ergebnissen:

OK. Jetzt, wo Sie sehen, dass Ihr Problem ist, dass Sie eine Art von Berechnung mit einer Abfrage basierend auf dem Durchlaufen der Ergebnisse einer anderen aktiven Datensatzabfrage tun, rate ich Ihnen, eine benutzerdefinierte SQL-Anweisung zu erstellen, die Ihre anfänglichen Auswahlkriterien und kombiniert die Schleife Berechnung, um zu bekommen, was Sie brauchen. Sie können dies definitiv beschleunigen, indem Sie das SQL optimieren.

    
srboisvert 20.02.2009, 09:38
quelle
5

Wie viele dieser 0-10ms-Abfragen werden pro Sichtzugriff ausgeführt? Auf welche Teile Ihres Datenmodells wird verwiesen? Verwenden Sie: include, um auf Ihre Assoziationen geladen zu werden?

Rails ist so langsam, wie Sie es machen. Mit Verständnis kommt Geschwindigkeit (normalerweise!)

Haben Sie auf der oben genannten Ebene has_many-Verknüpfungen, bei denen Ihre Ansicht insbesondere die Seite "many" ohne :include referenziert? Dies führt dazu, dass Ihr find(:all) in der Master-Tabelle mit einer Verknüpfung zum Detail ausgeführt wird. Wenn Sie eine große Anzahl von Detailsätzen haben und alle einzeln verarbeiten, kann dies teuer werden.

In etwa so:

%Vor%

... könnte helfen. Erraten Sie immer noch von spärlichen Informationen.

Es gibt einen alten Railscast zum Thema hier

    
Mike Woodhouse 19.02.2009 18:01
quelle
5

Während RnR den Ruf hat, langsam zu sein , klingt das zu extrem, um es zu sein einfaches Problem mit der Sprache.

Sie sollten einen Profiler ausführen, um genau zu bestimmen, welche Funktionen langsam sind und warum. Die gebräuchlichste Sache, die eine Webanwendung verlangsamt, ist das "n +" 1 Problem ". Das heißt, wenn Sie n Datenelemente in Ihrer Datenbank haben, macht die App n separate Abfragen an die Datenbank statt eine Abfrage, die sie erhält. Aber Sie können nicht wissen , bis Sie den Profiler ausführen. ruby-prof ist ein Profiler, den ich benutzt habe.

Bearbeiten basierend auf Profilergebnissen bearbeiten:

Ich glaube fest daran, dass Sie immer eine Abfrage-Schleife entfernen können. Wie Mike Woodhouse sagt, besteht die Methode von Rails darin, die Beziehungen zwischen Ihren Tabellen mit zu spezifizieren has_many oder eine andere Assoziation und dann lassen Rails automatisch die Tabelle beitreten, das ist klar, schnell und "der Weg Rails". Aber wenn Sie mit bloßem SQL beginnen oder wenn die Assoziationen in diesem Fall nicht funktionieren, können Sie einfach die passenden Verknüpfungen selbst erzeugen. Und wenn alles andere fehlschlägt, können Sie eine Ansicht oder denormalisierte Tabelle erstellen, die die Ergebnisse enthält, die zuvor durch eine Schleife gefunden wurden. Tatsächlich ist die Tatsache, dass Sie durch generierte Abfragen iterieren müssen könnte ein Zeichen dafür sein, dass Ihr Tabellendesign selbst einige Fehler aufweist.

Alles, was gesagt wurde, wenn Ihre Abfrageergebnisse gut genug für Sie gespeichert werden, bleiben Sie dabei. Bei Bedarf optimieren.

    
Joe Soul-bringer 19.02.2009 18:08
quelle
4

Das ist nicht normal. Du hast eine Logik, die dich verlangsamt. Versuche, Teile deines Codes zu kommentieren, von denen du glaubst, dass sie lange dauern und um zu sehen, ob das hilft. Wenn dies der Fall ist, müssen Sie herausfinden, wie Sie diese Logik optimieren können.

Von Ihnen wird viel über eine Schleife, die durch eine sehr große Anzahl von Objekten iteriert, gemacht, dann wird es natürlich langsam sein.

Diese Art von Problemen kann in jeder Sprache oder in jedem Framework auftreten. Während Ruby nicht so schnell ist wie andere Sprachen, ist es die meiste Zeit schnell genug. Wenn Sie ständig mit großen Datensätzen rechnen müssen, ist Ruby möglicherweise nicht die richtige Sprache für Sie. Sehen Sie sich eine Ruby-C-Erweiterung an, die den Code für die Leistungsentnahme verarbeitet. Aber zuerst versuchen Sie einfach zu diagnostizieren und zu refaktorieren.

Schauen Sie sich zuletzt RubyProf an, um zu sehen, ob es Ihnen hilft, den Engpass zu finden.

    
Alex Wayne 19.02.2009 17:56
quelle
3

Die beiden vorherigen Antworten sind hilfreich, insbesondere bei der Verwendung von Leistungsüberwachungstools. Ich benutze New Relic RPM und es hat mir in der Vergangenheit sehr geholfen.

Diese Tools sind jedoch am besten, wenn Sie versuchen, beispielsweise von 3 Sekunden auf unter 1 Sekunde zu beschleunigen.

2-4 Minuten, damit eine Ansicht wiedergegeben wird, ist unter normalen Umständen absolut nicht normal.

Können Sie uns einige Ihrer Entwicklungsprotokolle zeigen, um herauszufinden, wo Engpässe liegen?

Nehmen Sie Zeit mit, die der Browser benötigt, um Bilder, Javascripts oder andere Dateien in diese Gesamtmessung zu laden?

    
btw 19.02.2009 18:07
quelle
0

Bei so langen Ausführungszeiten würde ich ein Netzwerkproblem vermuten - vielleicht läuft eine DNS-Anfrage auf einem primären DNS-Server ab?

    
Ori Pessach 19.02.2009 18:13
quelle
0

Sie könnten versuchen, JRuby zu verwenden oder zu Ruby 1.9 zu wechseln.
Beide sollten zu massiven Leistungssteigerungen führen.
Das Problem mit JRuby ist, dass Edelsteine, die C benutzen, nicht kompilieren / arbeiten. Es gibt Java-Entsprechungen, die von jrubis "gem" App installiert werden, aber einige der Edelsteine ​​funktionieren einfach nicht

Sie werden grundsätzlich das gleiche Problem mit Ruby 1.9 haben. Ein bisschen Syntax hat sich geändert, aber das Hauptproblem ist, dass eine große Menge an Edelsteinen nicht mehr funktioniert. Die Leute sind jedoch dabei, die Aktualisierung zu aktualisieren (überprüfen Sie den Fortschritt bei Ссылка )

    
Marc Seeger 19.02.2009 20:18
quelle
0

Warum nicht alle Daten vorab abrufen und Ihre for-Schleife lokal im Speicher finden lassen, anstatt die Datenbank jedes Mal abzufragen? Tausende von Abfragen für eine einzelne Ansicht zeigen an, dass etwas ernsthaft mit Ihrem Design nicht stimmt.

    
Beep beep 20.02.2009 20:18
quelle
0

Es gibt einige gute Bildschirmdarstellungen zu diesem Thema Ссылка

Dinge wie fragmet caching und using: include (um n + 1 zu vermeiden) können helfen. Es klingt wie Sie bereits Memcached verwenden, also warum nicht die URL zum Vorabholen des Caches Curl?

    
MatthewFord 25.02.2009 11:19
quelle
0

Wenn ich den Server an die IP-Adresse der Box statt an 0.0.0.0 gebunden habe, hat sich das für mich beschleunigt.

    
hforbess 11.11.2010 17:52
quelle
0

Sie können den Code zuerst profilieren, bevor Sie etwas tun. Abfragen innerhalb von for loops sind jedoch eine häufige Ursache für Leistungsprobleme, und auf den ersten Blick scheint dies Ihr Problem zu sein. Vielleicht finden Sie hier trotzdem einen praktischen Profiler :

Wie bereits in den anderen Antworten erwähnt, sollten Sie, wenn beide Modelle verwandt sind, die Verknüpfungen mit hoher Wahrscheinlichkeit laden, was bedeutet, dass Active Record angewiesen wird, Join-Abfragen auszuführen:

%Vor%

Wenn Sie nicht die OFKBs, sondern nur die Operationen benötigen, können Sie einen inneren Join durchführen

%Vor%

Diese Lösung erzeugt nur eine Abfrage und ermöglicht Ihnen, die Daten, die bereits aus der DB gesammelt wurden, anschließend zu durchlaufen:

%Vor%

Wenn die Abfragen sehr kompliziert sind, sollten Sie stattdessen arel verwenden.

    
Pedro Morte Rolo 23.07.2014 10:33
quelle

Tags und Links