Вопрос по performance, list, arrays, c# – Что лучше? массив, ArrayList или List <T> (с точки зрения производительности и скорости)

17

Мне требуется высокая скорость обработки моей страницы. Количество добавляемых значений будет динамическим.

Какой из перечисленных выше предпочтительнее? Поддержка с уважительной причиной.

Редактировать: Например:

string str = "a,b,c"; //Count of the number of elements in str is not fixed
string[] arr = str.Split(',');

или же,

ArrayList al = new ArrayList();
al.Add(str.Split(','));
попробуйте каждый в вашей конкретной ситуации, профиль и посмотреть, какой из них лучше всего соответствует вашим потребностям. Каждый из них служит разным целям. Нет универсального ответа «это лучше», подходящего для всех ситуаций. Sam Holder
List<T> а такжеArrayList использовать массивы для их резервного хранения. Они могут быть такими же быстрыми, как массивы (и они есть), но они не могут быть быстрее. dasblinkenlight
Мне нравится запах [преждевременной оптимизации] по утрам. Jamiec
похожий на / Stackoverflow.com вопросы / 128636 / ... Tilak
Почему бы не попробовать это для себя? Кроме того, все зависит от того, что вы хотите сделать с Array, ArrayList или List <T>. Я бы выбрал тот, с которым легче всего работать, и беспокоюсь о производительности только тогда, когда это действительно нужно. Kristof Claes

Ваш Ответ

3   ответа
20

List<T> обычно следует отдавать предпочтение передArrayList

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

Если вы хотите, чтобы списки, которые вы предоставляете абонентам, были неизменяемыми, это поддерживается b, y обаList<T> а такжеArrayList:

List<T>.AsReadOnly()
ArrayList.ReadOnly(ArrayList list);

Твой вопрос касается выбора междуArrayList а такжеList<T>, но ваш пример показывает массив, который не является ни.

Так когда же выбор ArrayList будет лучшим вариантом, чем List? eaglei22
17

List<T> для изменяемых коллекций.

«Неизменяемая» коллекция - изменена только при создании, а многие читаются позже. Переменная коллекция - много изменений все время

Статистика производительности (Array vs List vs ReadonlyCollection):

       Array                List        ReadOnlyCollection         Penalties      Method
00:00:01.3932446    00:00:01.6677450    00:00:06.2444633    1 vs  1,2  vs  4,5   Generate
00:00:00.1856069    00:00:01.0291365    00:00:02.0674881    1 vs  5,5  vs 11,1   Sum
00:00:00.4350745    00:00:00.9422126    00:00:04.5994937    1 vs  2,2  vs 10,6   BlockCopy
00:00:00.2029309    00:00:00.4272936    00:00:02.2941122    1 vs  2,1  vs 11,3   Sort

Исходный код

interface IMethods<T>
{
  T Generate(int size, Func<int, int> generator);
   int Sum(T items);
   T BlockCopy(T items);
   T Sort(T items);
}

class ArrayMethods:IMethods<int[]>
{
  public int[] Generate(int size, Func<int, int> generator)
  {
    var items = new int[size];
    for (var i = 0; i < items.Length; ++i)
      items[i] = generator(i);
    return items;
  }
  public int Sum(int[] items)
  {
    int sum = 0;
    foreach (var item in items)
      sum += item;
    return sum;
  }
  public int[] BlockCopy(int[] items)
  {
    var res = new int[items.Length / 2];
    Buffer.BlockCopy(items, items.Length / 4 * sizeof(int), res, 0, res.Length * sizeof(int));
    return res;
  }
  public int[] Sort(int[] items)
  {
    var res = new int[items.Length];
    Buffer.BlockCopy(items, 0, res, 0, items.Length * sizeof(int));
    return res;
  }
}
class ListMethods : IMethods<List<int>>
{
  public List<int> Generate(int size, Func<int, int> generator)
  {
    var items = new List<int>(size);
    for (var i = 0; i < size; ++i)
      items.Add(generator(i));
    return items;
  }
  public int Sum(List<int> items)
  {
    int sum = 0;
    foreach (var item in items)
      sum += item;
    return sum;
  }
  public List<int> BlockCopy(List<int> items)
  {
    var count = items.Count / 2;
    var res = new List<int>(count);
    var start = items.Count / 4;
    for (var i = 0; i < count; ++i)
      res.Add(items[start + i]);
    return res;
  }
  public List<int> Sort(List<int> items)
  {
    var res = new List<int>(items);
    res.Sort();
    return res;
  }
}
class ReadOnlyCollectionMethods:IMethods<ReadOnlyCollection<int>>
{
  public ReadOnlyCollection<int> Generate(int size, Func<int, int> generator)
  {
    return new ReadOnlyCollection<int>(Enumerable.Range(0, size).Select(generator).ToList());
  }

  public int Sum(ReadOnlyCollection<int> items)
  {
    int sum = 0;
    foreach (var item in items)
      sum += item;
    return sum;
  }


  public ReadOnlyCollection<int> BlockCopy(ReadOnlyCollection<int> items)
  {
    return new ReadOnlyCollection<int>(items.Skip(items.Count / 4).Take(items.Count / 2).ToArray());
  }
  public ReadOnlyCollection<int> Sort(ReadOnlyCollection<int> items)
  {
    return new ReadOnlyCollection<int>(items.OrderBy(s => s).ToList());
  }
}

static class Program
{
  static Tuple<string, TimeSpan>[] CheckPerformance<T>(IMethods<T> methods) where T:class
  {
    var stats = new List<Tuple<string, TimeSpan>>();

    T source = null;
    foreach (var info in new[] 
      { 
        new {Name = "Generate", Method = new Func<T, T>(items => methods.Generate(10000000, i => i % 2 == 0 ? -i : i))}, 
        new {Name = "Sum", Method =  new Func<T, T>(items => {Console.WriteLine(methods.Sum(items));return items;})}, 
        new {Name = "BlockCopy", Method = new Func<T, T>(items => methods.BlockCopy(items))}, 
        new {Name = "Sort", Method = new Func<T, T>(items => methods.BlockCopy(items))}, 
        new {Name = "Sum", Method =  new Func<T, T>(items => {Console.WriteLine(methods.Sum(items));return items;})}, 
      }
     )
    {
      int count = 10;
      var stopwatch = new Stopwatch();
      stopwatch.Start();
      T res = null;
      for (var i = 0; i < count; ++i)
        res = info.Method(source);
      stopwatch.Stop();
      source = res;
      stats.Add(new Tuple<string, TimeSpan>(info.Name, stopwatch.Elapsed));
    }
    return stats.ToArray();
  }

  static void Main()
  {
    var arrayStats = CheckPerformance(new ArrayMethods());
    var listStats = CheckPerformance(new ListMethods());
    var rcStats = CheckPerformance(new ReadOnlyCollectionMethods());

    Console.WriteLine("       Array                List        ReadOnlyCollection         Penalties      Method");
    for(var i = 0; i < arrayStats.Length; ++i)
    {
      Console.WriteLine("{0}    {1}    {2}    1 vs {3,4:f1}  vs {4,4:f1}   {5}", arrayStats[i].Item2, listStats[i].Item2, rcStats[i].Item2, 
        listStats[i].Item2.TotalSeconds / arrayStats[i].Item2.TotalSeconds,
        rcStats[i].Item2.TotalSeconds / arrayStats[i].Item2.TotalSeconds, arrayStats[i].Item1);
    }
  }
За исключением того, что массив не является неизменным,IEnumerable<T> илиIReadOnlyList<T> (новое в .Net 4.5) - это. svick
Array не является неизменным. Вместо этого используйтеReadOnlyCollection<T> для неизменной обертки вокругList<T> - обычно звонитList<T>.AsReadOnly(). Joe
Массивы изменчивы, и их следует избегать, когда требуется неизменяемость: Blogs.msdn.com / б / ericlippert / Архив / 2008/09/22 / ... Joshua
@ DarkGray, факт в том, что массив не является неизменным, то есть его можно изменить после создания (например,myArray[i] = newValue). Что касается производительности, ваша статистика не имеет смысла, так как она не показывает, как они проводят измерения. Быть фиксированным размером (т.е. не может добавлять / удалять элементы) - это не то же самое, что неизменяемый (что означает, что существующие элементы также не могут быть заменены). Joe
Некоторые из этих тестов ошибочны. Например, ваша функция Generate для Array использует тот факт, что ее размер известен заранее. Но вы не делаете ничего подобного в своем генерации списка (например, используете аргумент Capacity вList<T> конструктор). Joe
6

List <T> всегда будет быстрее, чем arrayList.List <T>'s не нужно ставить в ячейку добавленные значения.

ArrayList только «принимать» объекты, поэтому это означает, что хотя вы можете добавить любой объект в список, он должен быть помещен в коробку (неявно CLR), а затем снова распакован (явно вами), когда вы нужны значения.

редактировать: есть хорошая ссылка

Разница в боксе относится только к типам значений. Для ссылочных типов оба будут равны. Servy

Похожие вопросы