2009-04-16 18 views
1

Ich zeichne einige Statistiken in meiner Anwendung auf. Eine der Statistiken ist die Größe von BigDataStructure. Ich habe zwei Möglichkeiten:Inkrementieren/Dekrementieren gegen Zuweisung?

  1. erstellen Zähler und Schritt/ Abnahme der Zähler jedes Mal gibt es ein Hinzufügen/Entfernen aus dem BigDataStructure.

  2. Jedes Mal, wenn eine von der BigDataStructure hinzugefügt/entfernt wird, setzen Sie den Zähler auf BigDataStructure.size().

Gibt es ein gutes Argument dafür, es auf die eine oder andere Weise zu tun? Das Inkrementieren/Dekrementieren des Zählers selbst vermeidet einen Aufruf von BigDataStructure.size(). Es bezieht auch nicht direkt den Zuweisungsoperator ein (obwohl es vielleicht unter der Haube tut?)

Angesichts dieser zwei Optionen, welche ist vorzuziehen?

Antwort

9

.size() wäre wahrscheinlich das weniger fehleranfällige der 2 Optionen, weil es idempotent ist. Wenn Sie Threading-/Synchronisationsprobleme haben möchten, ist .size() hier sicherer.

Außerdem haben Sie heute nur noch einen Platz, der Einträge hinzufügt, und einen Platz, der Einträge löscht. Aber vielleicht wird das in Zukunft nicht der Fall sein.

+0

+1, für ein gutes Wort des Tages;) – JaredPar

+0

+1, wenn Sie mir sagen, wie ausspricht ‚idempotent‘ :) –

+0

:) haha, Sie kann die Aussprache hier hören: http://dictionary.reference.com/browse/idempotent –

1

Inkrementieren/Dekrementieren sind wahrscheinlich schneller, da ein Funktionsaufruf vermieden wird. Es besteht jedoch die Gefahr, dass die aufgezeichnete Größe im Vergleich zur tatsächlichen Größe nicht mehr synchron ist. Wenn Sie sich sicher fühlen, dass sie nicht wollen, dann würde ich sagen, verwenden Sie nur inkrementieren/dekrementieren.

4

Es hängt ...

Wenn BigDataStructure.size() arbeiten, um die Größe zu berechnen erfordert, würde ich einen Zähler verwenden. Dies wäre in diesem Fall effizienter.

Wenn BigDataStructure.size() etwas ist, das automatisch von BigDataStructure bestimmt werden kann, also sehr wenig Berechnung erforderlich ist, würde ich diesen Ansatz bevorzugen. Es hat den Vorteil, die Logik an einem einzigen Ort zu halten, daher scheint es in dieser Hinsicht viel sauberer zu sein.

1

ich mit der Option gehen würde, 1.

AFAIK, x ++ und x + = 1 beide die gleiche wie x = x + 1 in jeder Hinsicht (andere als das, was Sie eingeben)

+0

Außer natürlich, dass die späteren mit Präzedenzproblemen enden können. (x ++), (x + = 1) und (x = x + 1) sind alle gleich. –

+0

@TonyF: Yep, aber es gibt wahrscheinlich eine Anweisung auf Ihrem Bügeleisen, die alle diese in einem Zyklus tut, was nicht unbedingt der Fall mit .size() ist, oder? Aber ich nehme an, dass der Unterschied in der Leistung, wenn überhaupt, hier nicht relevant ist. – Reunanen

3

Get Beste aus beiden Welten und mach sie beide. Sie könnten etwas seltsam finden, wenn Ihre Zahlen nicht übereinstimmen. Das ist ein guter Kandidat für Behauptungen.

1

Das Inkrementieren und Dekrementieren erfordert zusätzliche Vorsicht, wenn das Hinzufügen und Löschen aus mehreren Threads erfolgt. Auf der anderen Seite, wenn die Größe schnell berechnet werden kann, besteht nur ein geringes Risiko, dass sie nicht mit dem korrekten Wert übereinstimmt.

0

Wenn die Leistung von Bedeutung ist, hängt es davon ab, wie teuer der Aufruf von size() ist. Zum Beispiel kann ein Aufruf von size() für eine STL-Liste O (n) sein. Und selbst wenn der Aufruf O (1) ist, kann es schneller sein, die externen Zähler zu erhöhen oder zu verringern. Sie müssen wahrscheinlich eine Leistungsmessung durchführen, um herauszufinden, welche effektiver ist. Wenn Leistung keine Rolle spielt, dann geh mit dem Aufruf von size().

1

Warum behalten Sie die Zähler intern in BigDataStructure, und dann können Sie erhöhen oder verringern, wenn Sie innerhalb dieser Funktionen hinzufügen oder entfernen. Wenn Sie size() aufrufen, können Sie einfach den Wert des internen Zählers zurückgeben.

0

ich die erste benutzen würde, und dann assert(counter == BigDataStructure.size());