2015-05-06 2 views
0

массива В последнее время я работал в оптимизации производительности/памяти и stucked в пустой инициализации массива, который использует универсальный метод для инициализации пустого массива:Разница в производительности в пустой инициализации

выполнение кода родового пустого класса массива :

public static class EmptyArray<T> 
    { 
     public static readonly T[] Instance; 

     static EmptyArray() 
     { 
      Instance = new T[0]; 
     } 
    } 

Таким образом, всякий раз, когда создание пустого массива любого типа, он был назван так, как:

var emptyStringArray = EmptyArray<string>.Instance; 

Такое объявление пустого массива было сделано во многих местах кодовой базы. Я смущен, как бы это отличается в производительности при использовании:

var emptyStringArray = new string[0]; 

Я попросил кода выше автора, и он ответил мне:

В основном, все пустые массивы предназначены только для чтения, и равным одному другому, что означает, что вы можете использовать тот же экземпляр (который будет , созданный лениво по требованию во время выполнения) ... Это должно уменьшить общее количество распределений, уменьшить использование памяти и давление в ГК, а должно приводят к некоторому улучшению

Тем не менее, я не могу понять, как бы EmptyArrayInstance повысить производительность в объявлении массива.

Есть ли разница в производительности в коде, используя следующий подход:

1-й подход:

var emptyStrArr = EmptyArray<string>.Instance; 
var emptyFooArr = EmptyArray<Foo>.Instance; 
var emptyBarArr = EmptyArray<Bar>.Instance; 

2-й подход:

var emptyStrArr = new string[0]; 
var emptyFooArr = new Foo[0]; 
var emptyBarArr = new Bar[0]; 
+0

Просто обратите внимание, что с .NET 4.6 вы можете использовать Array.Empty () - см. https://msdn.microsoft.com/en-us/library/dn906179 (v = vs.110) .aspx –

ответ

1

В первом коде в static конструктор выполняется только один раз. Так вы просто создаете на e и использовать его все время. Во втором коде вы каждый раз создаете экземпляр массива. В этом разница.

Вы можете увидеть его более Клири, изменяя конструктор:

static EmptyArray() 
{ 
    Instance = new T[0]; 
    Console.WriteLine("Array of "+ typeof(T) + " is created."); 
} 

var s = EmptyArray<string>.Instance; 
s = EmptyArray<string>.Instance; 
s = EmptyArray<string>.Instance; 

var i = EmptyArray<int>.Instance; 
i = EmptyArray<int>.Instance; 

// output: 
// Array of System.String is created. 
// Array of System.Int32 is created. 
+3

Хотя это может быть сделано даже * более * эффективным без статического конструктора ... просто с 'public static r eadonly T [] Instance = new T [0]; '. Существует меньше гарантий времени, но это будет немного более эффективно. (Я бы, вероятно, использовал свойство самостоятельно, но это не должно влиять на вещи.) –

+0

Это не только создание пустого массива строк, но и пустого массива другого типа. Что будет в случае создания другого массива следующим образом: var emptyStrArr = EmptyArray .Instance; var emptyFooArr = EmptyArray .Instance; var emptyBarArr = EmptyArray .Instance; –

+0

@JonSkeet: Можете ли вы уточнить «меньше гарантий времени»? –

0

Это:

var emptyStringArray = new string[0]; 

Создает новый экземпляр пустого массива строк каждый раз, когда его называют, со всей соответствующей памятью а это:

public static class EmptyArray<T> 
    { 
     public static readonly T[] Instance; 

     static EmptyArray() 
     { 
      Instance = new T[0]; 
     } 
    } 

Только когда-либо создаётся один экземпляр из пустого массива строк, независимо от того, сколько раз вы вызываете поле Instance.

+0

Не означает ли это var emptyStrArr = EmptyArray .Instance; var emptyFooArr = EmptyArray .Instance; var emptyBarArr = EmptyArray .Instance; такое же, как var emptyStrArr = новая строка [0]; var emptyFooArr = new Foo [0]; var emptyBarArr = new Bar [0]; –

+0

Короче говоря, да ... – richzilla

0

Jus, чтобы проиллюстрировать немного, как это может повысить производительность и память, вы можете попробовать это

using System; 

namespace ConsoleApplication11 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      var str = EmptyArray<string>.Instance; 
      var intTest = EmptyArray<int>.Instance; 
      var intTest1 = EmptyArray<int>.Instance; 
      var str1 = EmptyArray<string>.Instance; 
      Console.WriteLine(str.GetType()); 
      Console.WriteLine(intTest.GetType()); 
      if (ReferenceEquals(str,str1)) 
      { 
       Console.WriteLine("References are equals"); 
      } 
      if (ReferenceEquals(intTest,intTest1))    
      { 
       Console.WriteLine("References are equals"); 
      } 

     } 
    } 

    public static class EmptyArray<T> 
    { 
     public static readonly T[] Instance; 

     static EmptyArray() 
     { 
      Instance = new T[0]; 
     } 
    } 
} 

вы можете увидеть, что никакое другое распределение не требуется даже для типа значения и при условии, что распределение и уничтожение объектов это время и потребляя память, вы можете улучшить свой код, делая это

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