Самый быстрый Способ сделать Мелкую Копию в C#

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

Более подробную информацию можно найти в Спецификации реального времени для Java об одном из подходов для достижения поведения в реальном времени с использованием Java. Идея RTSJ очень проста - не использовать кучу. RTSJ предоставляет новые разновидности объектов Runnable, которые гарантируют, что потоки не получат доступ к памяти кучи любого вида. Потоки могут получать доступ к памяти с областью действия (ничего необычного; значения уничтожаются при закрытии области действия) или к бессмертной памяти (которая существует в течение всего времени жизни приложения). Переменные в бессмертной памяти записываются снова и снова с новыми значениями.

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

Более подробная информация доступна в статье «Проект Золотые Ворота: на пути к Java в реальном времени в космических полетах», опубликованной JPL и Sun .

54
задан Chi 9 November 2012 в 05:44
поделиться

4 ответа

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

  1. Клонировать вручную
    Утомительный, но высокий уровень контроля.

  2. Клонирование с помощью MemberwiseClone
    Создает только поверхностную копию, т.е. для полей ссылочного типа исходный объект и его клон относятся к одному и тому же объекту.

  3. Клонировать с отражением
    По умолчанию неглубокая копия, может быть переписана для создания глубокой копии. Преимущество: автоматизированный. Недостаток: медленное отражение.

  4. Клонирование с сериализацией
    Легко, автоматизировано. Откажитесь от некоторого контроля, и сериализация будет медленнее всего.

  5. Клонирование с использованием IL, клонирование с использованием методов расширения
    Более продвинутые решения, не такие распространенные.

72
ответ дан 7 November 2019 в 07:40
поделиться

Это способ сделать это с помощью динамической генерации IL. Я нашел его где-то в Интернете:

public static class Cloner
{
    static Dictionary<Type, Delegate> _cachedIL = new Dictionary<Type, Delegate>();

    public static T Clone<T>(T myObject)
    {
        Delegate myExec = null;

        if (!_cachedIL.TryGetValue(typeof(T), out myExec))
        {
            var dymMethod = new DynamicMethod("DoClone", typeof(T), new Type[] { typeof(T) }, true);
            var cInfo = myObject.GetType().GetConstructor(new Type[] { });

            var generator = dymMethod.GetILGenerator();

            var lbf = generator.DeclareLocal(typeof(T));

            generator.Emit(OpCodes.Newobj, cInfo);
            generator.Emit(OpCodes.Stloc_0);

            foreach (var field in myObject.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))
            {
                // Load the new object on the eval stack... (currently 1 item on eval stack)
                generator.Emit(OpCodes.Ldloc_0);
                // Load initial object (parameter)          (currently 2 items on eval stack)
                generator.Emit(OpCodes.Ldarg_0);
                // Replace value by field value             (still currently 2 items on eval stack)
                generator.Emit(OpCodes.Ldfld, field);
                // Store the value of the top on the eval stack into the object underneath that value on the value stack.
                //  (0 items on eval stack)
                generator.Emit(OpCodes.Stfld, field);
            }

            // Load new constructed obj on eval stack -> 1 item on stack
            generator.Emit(OpCodes.Ldloc_0);
            // Return constructed object.   --> 0 items on stack
            generator.Emit(OpCodes.Ret);

            myExec = dymMethod.CreateDelegate(typeof(Func<T, T>));

            _cachedIL.Add(typeof(T), myExec);
        }

        return ((Func<T, T>)myExec)(myObject);
    }
}
8
ответ дан 7 November 2019 в 07:40
поделиться

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

4
ответ дан 7 November 2019 в 07:40
поделиться

Я запуталась. MemberwiseClone () должен аннигилировать производительность чего-либо еще для неглубокой копии. В CLI любой тип, отличный от RCW, должен иметь возможность поверхностного копирования с помощью следующей последовательности:

  • Выделить память в детской для типа.
  • memcpy данные из оригинала в новый . Поскольку цель находится в питомнике, никаких барьеров записи не требуется.
  • Если объект имеет определяемый пользователем финализатор, добавьте его в список GC элементов, ожидающих завершения.
    • Если для исходного объекта был вызван SuppressFinalize , и такой флаг хранится в заголовке объекта, снимите его в клоне.

Может ли кто-нибудь из команды разработчиков CLR объяснить, почему это не так. случай?

28
ответ дан 7 November 2019 в 07:40
поделиться
Другие вопросы по тегам:

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