Ich habe einige Themen zu diesem Thema gefunden. Die meisten Leute scheinen die Verwendung von int in ihrem C # -Code auf der ganzen Linie zu bevorzugen, selbst wenn ein Byte oder Smallint die Daten verarbeiten würde, es sei denn, es handelt sich um eine mobile App. Ich verstehe nicht warum. Ist es nicht sinnvoller, Ihren C # -Datentyp als denselben Datentyp zu definieren, der in Ihrer Datenspeicherlösung enthalten wäre?
Meine Prämisse: Wenn ich ein typisiertes Dataset, Linq2SQL-Klassen, POCO auf die eine oder andere Weise verwende, treten Probleme bei der Konvertierung von Compiler-Datentypen auf, wenn ich meine Datentypen nicht über meine Ebenen hinweg synchron halte. Ich mache System.Convert nicht immer gerne, nur weil es einfacher war, int auf der ganzen Linie in C # -Code zu verwenden. Ich habe immer den kleinsten Datentyp verwendet, der benötigt wird, um die Daten in der Datenbank sowie im Code zu verarbeiten und meine Schnittstelle zur Datenbank sauber zu halten. Ich würde also wetten, dass 75% meines C # -Codes im Gegensatz zu int Byte oder Short verwenden, da dies in der Datenbank enthalten ist.
Möglichkeiten: Bedeutet dies, dass die meisten Benutzer, die nur int für alles im Code verwenden, auch den Datentyp int für ihre SQL-Speicherdatentypen verwenden und sich möglicherweise weniger um die Gesamtgröße ihrer Datenbank kümmern, oder ob sie system.convertieren, wo immer dies möglich ist?
Warum es mich interessiert: Ich habe für immer alleine gearbeitet und möchte nur mit Best Practices und Standardcodierungskonventionen vertraut sein.
quelle
Antworten:
In Bezug auf die Leistung ist ein Int in fast allen Fällen schneller. Die CPU arbeitet effizient mit 32-Bit-Werten.
Kürzere Werte sind kompliziert zu handhaben. Um beispielsweise ein einzelnes Byte zu lesen, muss die CPU den 32-Bit-Block lesen, der es enthält, und dann die oberen 24 Bits ausblenden.
Um ein Byte zu schreiben, muss es den 32-Bit-Zielblock lesen, die unteren 8 Bits mit dem gewünschten Bytewert überschreiben und den gesamten 32-Bit-Block erneut zurückschreiben.
In Bezug auf den Speicherplatz sparen Sie natürlich einige Bytes, indem Sie kleinere Datentypen verwenden. Wenn Sie also eine Tabelle mit einigen Millionen Zeilen erstellen, sollten kürzere Datentypen in Betracht gezogen werden. (Und das gleiche könnte ein guter Grund sein, warum Sie kleinere Datentypen in Ihrer Datenbank verwenden sollten)
Und was die Korrektheit betrifft, läuft ein Int nicht leicht über. Was ist, wenn Sie glauben, dass Ihr Wert in ein Byte passt und dann irgendwann in der Zukunft eine harmlos aussehende Änderung des Codes dazu führt, dass größere Werte darin gespeichert werden?
Dies sind einige der Gründe, warum int Ihr Standarddatentyp für alle integralen Daten sein sollte. Verwenden Sie Byte nur, wenn Sie tatsächlich Maschinenbytes speichern möchten. Verwenden Sie Shorts nur, wenn Sie mit einem Dateiformat oder Protokoll oder ähnlichem arbeiten, das tatsächlich 16-Bit-Ganzzahlwerte angibt. Wenn Sie im Allgemeinen nur mit ganzen Zahlen arbeiten, machen Sie sie zu Ints.
quelle
long
standardmäßig auf 64-Bit-Computern verwenden? (Wenn Sie interessiert sind, werfen Sie bitte einen Blick auf diese Frage )long
überall zu verwenden . Es schadet nichts. Dies ist jedoch nicht konsequent möglich , da die meisten .NET- (oder Java-) APIsint
fast überall verwendet werden. Sie müssen Ihren Code also wahrscheinlich mit mehr Casts verunreinigen, als Sie es sonst hätten.Ich bin nur 6 Jahre zu spät, aber vielleicht kann ich jemand anderem helfen.
Hier sind einige Richtlinien, die ich verwenden würde:
Ein Thema, das niemand angesprochen hat, ist der begrenzte CPU-Cache. Kleinere Programme werden schneller ausgeführt als größere, da die CPU mehr Programme in die schnelleren L1 / L2 / L3-Caches einpassen kann.
Die Verwendung des int-Typs kann zu weniger CPU-Anweisungen führen, erzwingt jedoch auch, dass ein höherer Prozentsatz des Datenspeichers nicht in den CPU-Cache passt. Anweisungen sind billig auszuführen. Moderne CPU-Kerne können 3-7 Befehle pro Taktzyklus ausführen, ein einzelner Cache-Fehler kann jedoch 1000-2000 Taktzyklen kosten, da er bis zum RAM reichen muss.
Wenn Speicherplatz gespart wird, führt dies auch dazu, dass der Rest der Anwendung eine bessere Leistung erbringt, da er nicht aus dem Cache herausgedrückt wird.
Ich habe einen schnellen Summentest mit Zugriff auf zufällige Daten in zufälliger Reihenfolge durchgeführt, wobei sowohl ein Byte-Array als auch ein Int-Array verwendet wurden.
const int SIZE = 10000000, LOOPS = 80000; byte[] array = Enumerable.Repeat(0, SIZE).Select(i => (byte)r.Next(10)).ToArray(); int[] visitOrder = Enumerable.Repeat(0, LOOPS).Select(i => r.Next(SIZE)).ToArray(); System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch(); sw.Start(); int sum = 0; foreach (int v in visitOrder) sum += array[v]; sw.Stop();
Hier sind die Ergebnisse in der Zeit (Ticks): (x86, Release-Modus, ohne Debugger, .NET 4.5, I7-3930k) (kleiner ist besser)
________________ Array Size __________________ 10 100 1K 10K 100K 1M 10M byte: 549 559 552 552 568 632 3041 int : 549 566 552 562 590 1803 4206
Ein letzter Hinweis: Manchmal schaue ich mir das jetzt Open-Source-.NET-Framework an, um zu sehen, was die Experten von Microsoft tun. Das .NET Framework verwendet überraschend wenig Byte / Int16. Ich konnte eigentlich keine finden.
quelle
Sie müssten sich mit einigen MILLIARDEN Zeilen befassen, bevor dies einen signifikanten Unterschied in Bezug auf die Speicherkapazität bewirkt. Nehmen wir an, Sie haben drei Spalten, und anstatt einen byteäquivalenten Datenbanktyp zu verwenden, verwenden Sie einen int-äquivalenten.
Das ergibt 3 (Spalten) x 3 (zusätzliche Bytes) pro Zeile oder 9 Bytes pro Zeile.
Dies bedeutet, dass Sie für "einige Millionen Zeilen" (sagen wir drei Millionen) zusätzliche 27 Megabyte Speicherplatz verbrauchen! Zum Glück sollten Sie sich darüber keine Sorgen machen müssen, da wir nicht mehr in den 1970ern leben :)
Wie oben erwähnt, beenden Sie die Mikrooptimierung - der Leistungseinbruch beim Konvertieren in / von verschiedenen ganzzahligen numerischen Typen wird Sie viel, viel schwerer treffen als die Bandbreiten- / Speicherplatzkosten, es sei denn, Sie haben es mit sehr, sehr, sehr großen Kosten zu tun Datensätze.
quelle
Zum größten Teil "Nein".
Wenn Sie nicht im Voraus wissen, dass Sie mit Hunderten von Millionen Zeilen zu tun haben, handelt es sich um eine Mikrooptimierung.
Tun Sie, was am besten zum Domain-Modell passt. Wenn Sie später Leistungsprobleme haben, können Sie anhand des Benchmarks und des Profils genau bestimmen, wo sie auftreten.
quelle
Nicht dass ich Jon Grant und anderen nicht geglaubt hätte, aber ich musste mich mit unserer "Million Row Table" selbst davon überzeugen. Die Tabelle hat 1.018.000. Ich habe 11 tinyint-Spalten und 6 smallint-Spalten in int konvertiert, es gab bereits 5 int & 3 smalldatetimes. 4 verschiedene Indizes verwendeten eine Kombination der verschiedenen Datentypen, aber offensichtlich verwenden die neuen Indizes jetzt alle int-Spalten.
Das Vornehmen der Änderungen kostete mich nur 40 MB bei der Berechnung der Festplattennutzung der Basistabelle ohne Indizes. Als ich die Indizes wieder in die Gesamtänderung einfügte, betrug der Unterschied insgesamt nur 30 MB. Ich war also überrascht, weil ich dachte, die Indexgröße wäre größer.
30 MB sind es also wert, all die verschiedenen Datentypen zu verwenden, No Way! Ich mache mich auf den Weg ins INT-Land. Vielen Dank an alle, die diesen anal-zurückhaltenden Programmierer wieder in das geradlinige und glückliche Leben ohne weitere ganzzahlige Konvertierungen zurückversetzt haben ... yippeee!
quelle
Wenn int überall verwendet wird, sind keine Castings oder Konvertierungen erforderlich. Das ist ein größerer Gewinn für den Geldbeutel als der Speicher, den Sie durch die Verwendung mehrerer ganzzahliger Größen sparen.
Es macht das Leben einfach einfacher.
quelle
Die .NET-Laufzeit ist für Int32 optimiert. Siehe vorherige Diskussion bei .NET Integer vs Int16?
quelle