Я делаю простую систему частиц в C#/XNA, и поскольку в каждую секунду потенциально может быть большой объем вызовов методов, я хотел бы убедиться, что я точно понял, как все работает.Оптимизация с использованием типов значений и вызовов методов с использованием ref
У меня есть частица и класс эмиттер, что:
public sealed class Emitter
{
private struct Particle
{
public Vector2 Position;
public Vector2 Velocity;
public ushort Life;
public bool Alive { get { return (Life > 0); } }
}
private readonly Particle[] _particles;
public Emitter(ushort maxParticles)
{
_particles = new Particle[maxParticles];
}
}
Излучатель имеет другую логику, которая будет создавать, обновлять и визуализировать частицы, но это не имеет значения. Тем не менее, я понимаю, что если бы я вызвать метод, он будет копировать значение при каждом вызове:
public static void UpdateParticle(Particle p)
{
p.Position += p.Velocity;
}
Если бы я сделал Emitter
с 100000 частиц (как маловероятно, так как это было бы), копирование частицы просто для обновления кажется, что это будет делать много ненужной работы. Если метод использовал ref вместо UpdateParticle(ref Particle p) { ... }
, то он просто получил бы доступ к данным напрямую и обновил его там, не так ли?
Однако, по отношению к ответу Джона Скита на this вопрос, он пишет:
Вы почти никогда не нужно использовать реф/из. Это в основном способ получить другое возвращаемое значение и обычно следует избегать именно потому, что это означает, что метод, вероятно, пытается сделать слишком много. Это не всегда так (
TryParse
и т. Д. Являются каноническими примерами разумного использования out), но использование ref/out должно быть относительной редкостью.
Является ли это одним из тех «относительно редких» случаев, когда это правильный выбор для его использования?
Что касается моего выбора дизайна для этого класса:
Я сделал некоторые исследования в системе частиц некоторое время назад. Я не могу вспомнить точные аргументы в пользу создания структуры - что-то о доступе к непрерывному фрагменту памяти быстрее или не так много ссылок на объекты, но бенчмаркинг доказывает, что он работает лучше, чем класс.
Particle
- частный тип, потому что классEmitter
- это единственное, что когда-либо заботится об этом. Когда-либо. Клиентский код никогда не должен заботиться о отдельных частицах, только то, чтоEmitter
делает блеск и рендеринг._particles
- фиксированный размер, действующий как пул объектов, поскольку повторная утилизация выделенной памяти должна быть более эффективной, чем при вызовеnew()
.