Будет ли компилятор оптимизировать создание этого списка дважды? - PullRequest
4 голосов
/ 08 ноября 2010
public SharpQuery Add(params HtmlNode[] elements)
{
    var nodes = new List<HtmlNode>(_context.Count + elements.Length);
    nodes.AddRange(_context);
    nodes.AddRange(elements);
    return new SharpQuery(nodes, this);
}

public SharpQuery(IEnumerable<HtmlNode> nodes, SharpQuery previous = null)
{
    if (nodes == null) throw new ArgumentNullException("nodes");
    _previous = previous;
    _context = new List<HtmlNode>(nodes);
}

У меня есть целая куча функций, которые создают новую List<T>, добавляют к ней кучу узлов, затем передают ее этому конструктору, который берет список и создает еще один новый списокс ним.

Достаточно ли умен компилятор, чтобы понять, что ему не нужно создавать список дважды?

Ответы [ 4 ]

5 голосов
/ 08 ноября 2010

Дело не в том, чтобы быть «достаточно умным» - компилятор делает то, что ему говорят;вы говорите ему создать несколько списков: он создаст несколько списков.

Однако, поскольку вы немедленно освобождаете их, они должны собираться довольно чисто, надеюсь, gen-0.Поэтому, если вы не делаете это в тесном цикле, я бы не слишком обрадовался этому.

Если вы хотите избежать списков, вы можете рассмотреть LINQ Concat, чтопозволяет добавлять последовательности без каких-либо дополнительных списков / коллекций / и т. д.

2 голосов
/ 08 ноября 2010

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

Технически, вы можете сделать это сами - _context = (List<HtmlNode>)nodes; - это то, что вы хотите, чтобы компилятор делал. Или лучше _context = nodes as List<HtmlNode> ?? new List<HtmlNode>(nodes).
Но в любом случае список может быть изменен за пределами вашего класса, поэтому вы должны быть уверены, что он не вызовет неожиданного поведения.

Пока пахнет преждевременной оптимизацией. Ваш код выглядит хорошо, и я бы ничего не изменил, пока не увидел бы здесь реальную проблему производительности.

2 голосов
/ 08 ноября 2010

Нет, компилятор не может выполнять такие оптимизации.

Поскольку конструктор принимает IEnumerable, вы можете создать выражение вместо списка:

public SharpQuery Add(params HtmlNode[] elements) {
  return new SharpQuery(_context.Concat(elements), this);
}

Concat метод создаст выражение, которое сначала возвращает элементы _context, затем элементы elements.Когда список создается в конструкторе, он будет использовать выражение, которое читает непосредственно из _context и elements, поэтому коллекция создается только один раз.

1 голос
/ 08 ноября 2010

Компилятор (из JIT) не может оптимизировать это.Он создает два списка для вас.Вопрос, однако, в том, вызывает ли это проблему с производительностью для вас.С производительностью у вас есть мера, мера и мера.Я думаю, что в 98% случаев этот код не доставит никаких проблем.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...