Уменьшение накладных расходов на замыкание в Task.Run/Factory.StartNew с помощью предопределенного объекта.C#

Место общения программистов C#
Ответить Пред. темаСлед. тема
Anonymous
 Уменьшение накладных расходов на замыкание в Task.Run/Factory.StartNew с помощью предопределенного объекта.

Сообщение Anonymous »

Это сделано исключительно в экспериментальных целях и/или в качестве обучающего упражнения. По сути, я хотел бы посмотреть, смогу ли я уменьшить объем замыкания, создаваемого при использовании Task.Run(()=>Func()), создав класс, который я инициализирую только один раз. Во-первых, цель состоит в том, чтобы избежать создания «нового» экземпляра этого каждый раз, когда мы запускаем, что, вероятно, будет менее эффективным, чем само замыкание, которое я себе представляю (но я знаю, что это всего лишь предположение). Таким образом, создать для этого базовый класс довольно просто, поскольку вы можете найти примеры этого здесь, в стеке.
Однако я столкнулся с проблемой: может показаться, что мне, что если я хочу использовать члены и функции из другого класса, то мне придется инкапсулировать их или внедрить в класс, который мы собираемся запускать, хотя в нем может быть меньше данных, чем в самом исходном классе , вероятно, это не будет таким уж большим улучшением.
Скажем, у меня есть что-то вроде:

Код: Выделить всё

internal async Task
 PopulatePathObjectAsync(Vector3Int origin, Vector3Int destination, PathObject path)
{
return await Task.Factory.StartNew(() => PopulatePathObject(origin, destination, path));
}

/// Not sure if we want to make this a task or not because we may just parallelize and await the outer task.
/// We'll have to decide when we get down to finalization of the architecture and how it's used.
internal PathObject PopulatePathObject(Vector3Int origin, Vector3Int destination, PathObject path)
{
Debug.Log($"Pathfinding Search On Thread: ({System.Threading.Thread.CurrentThread.ManagedThreadId})");

if (!TryVerifyPath(origin, destination, ref path, out PathingNode currentNode))
return path;

var openNodes = m_OpenNodeHeap;

m_ClosedNodes.Clear();

openNodes.ClearAndReset();
openNodes.AddNode(currentNode);

for (int i = CollectionBufferSize; openNodes.Count > 0 && i >= 0; i--)
{
currentNode = ProcessNextOpenNode(openNodes);

if (NodePositionMatchesVector(currentNode, destination))
{
return path.PopulatePathBufferFromOriginToDestination(currentNode, origin, PathState.CompletePath);
}

ProcessNeighboringNodes(currentNode, destination);
}

return path.PopulatePathBufferFromOriginToDestination(currentNode, origin, PathState.IncompletePath);
}
Чтобы отказаться от лямбды, замыкания и создания (или, возможно, приведения?) делегата, мне понадобится класс, который фактически инкапсулирует эту функцию PopulatePathObject в его полноту, либо буквально копируя необходимые члены, либо передавая их в качестве аргументов. Кажется, что все это, вероятно, принесет какую-либо выгоду. Итак, могу ли я получить что-то вроде...

Код: Выделить всё

private class PopulatePathObjectTask
{
private readonly Vector2Int m_Origin;
private readonly Vector3Int m_Destination;
private readonly PathObject m_Path;

public PopulatePathObjectTask(Vector2Int origin, Vector3Int destination, PathObject path)
{
m_Origin = origin;
m_Destination = destination;
m_Path = path;
}

public PathObject PopulatePathObject(Vector3Int origin, Vector3Int destination, PathObject path)
{
///Obviously here, without access to the actual AStar class responsible for the search,
///I don't have access to the functions or the class members such as the heap or the hashset
///that represents the closed nodes as well as the calculated buffer size based on the space-state
///dimensions. With that, I'd just be recreating the class and not avoiding much, if any,
///of the overhead created by the closure capturing the class in the first place.
}
}
Что я мог бы использовать для доступа к уже существующей функции? Я подумывал о создании статического члена и использовании внедрения зависимостей для коллекций открытых/закрытых узлов, но я думал или, скорее, надеялся, что кто-нибудь может получить больше информации об этом, кроме того, что это бессмысленно и даже < em>возможное сокращение накладных расходов или прирост производительности будут настолько минимальными, что это будет бессмысленно. Что, возможно, вы и правы, но я делаю это в качестве упражнения и хотел бы иметь возможность реально измерить различия. Я, вероятно, даже не собираюсь его использовать, возможно, даже вместо этого заменю AStar на JPS, но мне хотелось бы знать, прежде чем двигаться дальше. Я не совсем уверен, но кажется, что замыкание должно захватывать весь объект AStar во времени, можно надеяться, по ссылке.

Подробнее здесь: https://stackoverflow.com/questions/779 ... ned-object
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение
  • Разное поведение между Factory.StartNew и Task.Run?
    Anonymous » » в форуме C#
    0 Ответы
    22 Просмотры
    Последнее сообщение Anonymous
  • Почему вызов неоднозначен между Task.Run(Func) и Task.Run(Func) при передаче имени метода
    Anonymous » » в форуме C#
    0 Ответы
    93 Просмотры
    Последнее сообщение Anonymous
  • Разница в производительности между ThreadPool.QueueUserWorkItem и Task.Factory.StartNew
    Anonymous » » в форуме C#
    0 Ответы
    17 Просмотры
    Последнее сообщение Anonymous
  • Многопоточный Task.factory.startnew
    Anonymous » » в форуме C#
    0 Ответы
    13 Просмотры
    Последнее сообщение Anonymous
  • Многопоточный Task.Factory.StartNew вызывает утечку памяти [закрыто]
    Anonymous » » в форуме C#
    0 Ответы
    15 Просмотры
    Последнее сообщение Anonymous

Вернуться в «C#»