2009-06-08 6 views
9

Просмотрев код, я наткнулся на ряд новых частных общих переменных (типа Hashtables (Of String), инициализированных в объявлении), добавленных в частичный класс для очень большого (DataContext-производного) класса. Это кажется мне разумным в некотором смысле, потому что они никогда не меняются, и эти общие переменные гарантируют, что они не будут повторно инициализироваться каждый раз, когда вызывается функция. Однако эти переменные являются, которые используются только в пределах одной функции класса, и я боюсь, что частное пространство имен этого производного класса DataContext становится довольно загрязненным, и такие вещи, которые подвергаются на таком высоком уровне, могут быть смущая других, читающих код в будущем. Было ли отрицательное влияние на производительность этих локальных переменных внутри функции, где они используются, или есть ли лучший способ справиться с этим? В основном мы используем эти 3 хэш-таблицы для определения того, изменилось ли что-либо внутри определенных подмножеств свойств (с использованием GetModifiedMembers, а затем с помощью функции Overlaps хешета, чтобы увидеть, соответствуют ли какие-либо из измененных членов членам, которых мы заботимся).Частные общие переменные против локальных переменных/Замедление пространства имен и производительность?

Редактировать: Я сбежал и нашел время, чтобы написать собственную тестовую программу, в которой подтверждается, что существует стоимость использования локальных переменных (которые, как я полагаю, применяется в целом ко всем случаям), я сомневаюсь, что есть случай, когда общий переменная будет медленнее, если с помощью общей переменной не требует некоторой дополнительной логики, чтобы сделать это правильно):

Sub Main() 
    Dim st As New Stopwatch() 
    Dim specialCount As Integer = 0 
    Dim r As New Random() 
    Dim params As Integer() 
    ReDim params(0 To 9) 
    st.Start() 
    For i As Integer = 1 To 100000 
    For j As Integer = 0 To 9 
     params(j) = r.Next(100) 
    Next 
    If IsSpecialShare(params) Then specialCount += 1 
    Next 
    st.Stop() 

    Console.WriteLine("Shared: " & specialCount) 
    Console.WriteLine(st.Elapsed.ToString()) 

    st.Reset() 
    specialCount = 0 

    st.Start() 
    For i As Integer = 1 To 100000 
    For j As Integer = 0 To 9 
     params(j) = r.Next(100) 
    Next 
    If IsSpecialLocal(params) Then specialCount += 1 
    Next 
    st.Stop() 

    Console.WriteLine("Local: " & specialCount) 
    Console.WriteLine(st.Elapsed.ToString()) 

End Sub 

Dim specialListShared As New HashSet(Of Integer)(New Integer() {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41}) 

Private Function IsSpecialLocal(ByVal paramList As IEnumerable(Of Integer)) As Boolean 
    Dim specialListLocal As New HashSet(Of Integer)(New Integer() {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41}) 
    Return specialListLocal.Overlaps(paramList) 
End Function 

Private Function IsSpecialShare(ByVal paramList As IEnumerable(Of Integer)) As Boolean 
    Return specialListShared.Overlaps(paramList) 
End Function 

Пример вывода:

Shared: 75232 
00:00:00.0408223 
Local: 75018 
00:00:00.1344628 

таким образом, в данном конкретном случае, используя локальную переменную стоит около 200% , Но в большинстве случаев (включая мое собственное) время, вероятно, незначительно по сравнению с общей задачей. Поэтому, я думаю, теперь возникает вопрос, как люди обычно чувствуют себя в улучшении обслуживания кода за счет незначительных, но известных эффектов производительности?

ответ

6

Я бы сказал, что вам нужно определить, действительно ли эти статические переменные принадлежат пространству имен, классу или функции. Если они действительно специфичны для функции, я бы включил их в функцию.

Если вам нужны переменные, которые сохраняют состояние даже после того, как функция выходит за пределы области видимости, вы можете объявить их как Static. Это исключает проблему наличия этих переменных в области класса.

разница между общей переменной класса, статической переменной функции и локальной переменной функции:

Shared: Там будет только одна копия переменной среди всех экземпляров класса.

Статический: в экземпляре вашего экземпляра будет одна копия переменной.

Local: копия переменной будет создаваться каждый раз, когда функция вызывается (но освобождается после того, как функция выходит за пределы области видимости).

Используйте тот, который имеет смысл в вашей ситуации.

+0

Я не думаю, что меня беспокоит реальная измеримая производительность здесь, поскольку разница, вероятно, будет невыяснимо малой. И есть рекомендации, основанные на производительности, независимо от необходимости профилировать отдельные случаи. Вот что я здесь делаю. Например, вы обычно должны использовать строго типизированные переменные вместо ссылок на объекты, где это возможно, из-за стоимости бокса и бокса. Мой вопрос, аналогичный тому, заключается в том, есть ли значительная стоимость для рассмотрения при использовании локальных переменных, а не общих переменных. Выгод/затрат? – BlueMonkMN

+0

На самом деле это константа, но (хотя VB.NET допускает локальные константы), невозможно объявить константу с таким значением, поэтому мы должны объявить переменную. И тогда мы сталкиваемся с аналогичным вопросом: стоит ли накладные расходы на наличие дополнительных экземпляров, которые стоят того, чтобы не загрязнять пространство имен класса. Это действительно постоянная, применимая только к этой конкретной функции. Это всего лишь список имен свойств для свойств, значения которых обрабатываются внутри этой функции. – BlueMonkMN

+0

Тогда я бы объявил его как статическую локальную переменную. Накладные расходы, вероятно, очень малы, поэтому стоит не загрязнять пространство имен класса, если только не создаются миллионы объектов этого типа. (1 миллион объектов = 1 миллион копий вашей статической переменной) –

0

Когда вы говорите «общий» - это VB-talk для static? Если это так, обратите внимание, что вы можете быть немного подвержены потоковому риску, если не будете осторожны ... и учитывая описание, похоже, эти данные могут быть изменчивыми? Может быть ... «интересно», если у вас есть несколько экземпляров/потоков.

Возможно, я слишком параноидально - трудно сказать, без иллюстративного кода ...

Instance поля (а не общие/статические поля) будет мое предположение по умолчанию - но опять же, без контекста не могу быть на 100% уверенным.

+0

Да, VB.Net Shared = C# Static – Pondidum

+3

или == должен ли я говорить? – Pondidum

+0

Они не должны меняться. См. Мой комментарий «Это кажется мне разумным в одном смысле, потому что они никогда не меняются». – BlueMonkMN

0

Я почти забыл, что VB.NET поддерживает статические локальные переменные. Следующий тест показывает, что я могу получить производительность так же хорошо, используя статическую локальную переменную:

Sub Main() 
    Dim st As New Stopwatch() 
    Dim specialCount As Integer = 0 
    Dim r As New Random() 
    Dim params As Integer() 
    ReDim params(0 To 9) 
    st.Start() 
    For i As Integer = 1 To 100000 
    For j As Integer = 0 To 9 
     params(j) = r.Next(100) 
    Next 
    If IsSpecialShare(params) Then specialCount += 1 
    Next 
    st.Stop() 

    Console.WriteLine("Shared: " & specialCount) 
    Console.WriteLine(st.Elapsed.ToString()) 

    st.Reset() 
    specialCount = 0 

    st.Start() 
    For i As Integer = 1 To 100000 
    For j As Integer = 0 To 9 
     params(j) = r.Next(100) 
    Next 
    If IsSpecialLocal(params) Then specialCount += 1 
    Next 
    st.Stop() 

    Console.WriteLine("Local: " & specialCount) 
    Console.WriteLine(st.Elapsed.ToString()) 

    st.Reset() 
    specialCount = 0 

    st.Start() 
    For i As Integer = 1 To 100000 
    For j As Integer = 0 To 9 
     params(j) = r.Next(100) 
    Next 
    If IsSpecialStatic(params) Then specialCount += 1 
    Next 
    st.Stop() 

    Console.WriteLine("Static: " & specialCount) 
    Console.WriteLine(st.Elapsed.ToString()) 

End Sub 

Dim specialListShared As New HashSet(Of Integer)(New Integer() {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41}) 

Private Function IsSpecialLocal(ByVal paramList As IEnumerable(Of Integer)) As Boolean 
    Dim specialListLocal As New HashSet(Of Integer)(New Integer() {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41}) 
    Return specialListLocal.Overlaps(paramList) 
End Function 

Private Function IsSpecialShare(ByVal paramList As IEnumerable(Of Integer)) As Boolean 
    Return specialListShared.Overlaps(paramList) 
End Function 

Private Function IsSpecialStatic(ByVal paramList As IEnumerable(Of Integer)) As Boolean 
    Static specialListLocal As New HashSet(Of Integer)(New Integer() {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41}) 
    Return specialListLocal.Overlaps(paramList) 
End Function 

Пример вывода:

Shared: 74836 
00:00:00.0498081 
Local: 75205 
00:00:00.1317149 
Static: 74862 
00:00:00.0469154 

Кстати, я всегда задавался вопросом, если C# поддерживает статические локальные переменные, И если нет, то почему? В C# есть несколько раздражающих недостающих функций, которые поддерживает VB.NET.

+0

Это нехорошо. Статические переменные не разделяемых функций распределяют хранилище на каждом экземпляре, что (в нашей ситуации) наихудшая из всех. Я полагаю, что мы могли бы создать еще одну общую функцию, которая выполняет работу со статическими переменными, но эта функция все равно будет «загрязнением пространства имен». Наверное, сейчас нам придется придерживаться общего класса. – BlueMonkMN

 Смежные вопросы

  • Нет связанных вопросов^_^