C# 中的深度克隆每次调用需要更长的时间执行

发布于 2024-11-02 08:55:17 字数 2434 浏览 0 评论 0原文

我正在尝试深度克隆 100 个多属性对象的列表,我使用下面的代码来执行深度克隆。列表创建和列表克隆发生在循环中,因此每次循环时列表都会更改其内容,但保持固定为 100 个对象。

问题是每次循环时,克隆列表所花费的时间似乎都比上次执行时呈指数级增长。

public static Main ()
{

List<Chromosome<Gene>> population = Population.randomHalfAndHalf(rand, data, 100, opset);

        for (int i = 0; i < numOfGenerations; i++)
        {
                   offSpring = epoch.runEpoch(rand, population, SelectionMethod.Tournament, opset);
                    clone = DeepClone<List<Chromosome<Gene>>>(population);
                    clone.AddRange(offSpring);
                    population = fixPopulation(rand, clone, SelectionMethod.Tournament, 100);
        }

//....REST OF CODE....

}


public static T DeepClone<T>(T obj)
    {
        object result = null;

        using (var ms = new MemoryStream())
        {
            var formatter = new BinaryFormatter();
            formatter.Serialize(ms, obj);
            ms.Position = 0;

            result = (T)formatter.Deserialize(ms);
            ms.Close();
        }
        return (T)result;
    }

你们中的一些人可能会想,如果我可以覆盖原始群体,为什么我还要克隆该对象。这是一个有效的观点,也是我已经探索过的观点,但是当我这样做时会发生什么,第一次运行循环时它完美地执行了大约 8 次迭代,然后它闲置并且不执行任何操作,因此我停止了它。下次我执行它时,它会进行 9 次迭代,每次循环都会停止、理想、不执行任何操作等。如果有人对为什么会发生这种情况有任何想法,也请分享,因为我真的不明白为什么会发生这种情况。

但我的主要问题是,每次围绕上述循环克隆对象的时间都明显更长,首先是几秒钟,然后最终达到 5 分钟等。

任何人都知道为什么会发生这种情况吗?

编辑我已经对应用程序运行时的情况进行了分析,超过 90% 的大部分工作是由 BinaryFormatter.Deserialize(memoryStream) 完成的,这里是修复人口,它没有做任何过于复杂的事情,这将有助于此问题。

private static List<Chromosome<Gene>> fixPopulation(Random rand, List<Chromosome<Gene>> oldPopulation, SelectionMethod selectionMethod, int populationSize)
    {
        if (selectionMethod == SelectionMethod.Tournament)
        {
            oldPopulation.Sort();
        }
        else
        {
            //NSGAII sorting method
        }

        oldPopulation.RemoveRange(populationSize, (oldPopulation.Count - populationSize));

        for (int i = 0, n = populationSize / 2; i < n; i++)
        {
            int c1 = rand.Next(populationSize);
            int c2 = rand.Next(populationSize);

            // swap two chromosomes
            Chromosome<Gene> temp = oldPopulation[c1];
            oldPopulation[c1] = oldPopulation[c2];
            oldPopulation[c2] = temp;
        }

        return oldPopulation;
    }

I am trying to deep clone a list of 100 multi-property objects, I am using the code below to perform the deep clone. The list creation and the list cloning happen in a loop so each time around the loop the list changes its contents but remains fixed at 100 objects.

The problem is each time around the loop, cloning the list takes what seems to be exponentially longer than the last time it executed.

public static Main ()
{

List<Chromosome<Gene>> population = Population.randomHalfAndHalf(rand, data, 100, opset);

        for (int i = 0; i < numOfGenerations; i++)
        {
                   offSpring = epoch.runEpoch(rand, population, SelectionMethod.Tournament, opset);
                    clone = DeepClone<List<Chromosome<Gene>>>(population);
                    clone.AddRange(offSpring);
                    population = fixPopulation(rand, clone, SelectionMethod.Tournament, 100);
        }

//....REST OF CODE....

}


public static T DeepClone<T>(T obj)
    {
        object result = null;

        using (var ms = new MemoryStream())
        {
            var formatter = new BinaryFormatter();
            formatter.Serialize(ms, obj);
            ms.Position = 0;

            result = (T)formatter.Deserialize(ms);
            ms.Close();
        }
        return (T)result;
    }

Some of you may be thinking why am I even cloning the object if I can write over the original population. This is a valid point and one that I have explored but what happens when I do that is that loop executes perfectly for about 8 iterations the first time I run it, then it idles and does nothing so I stop it. The the next time I execute it it goes to 9 iterations and stops, ideals, does nothing etc etc each time around the loop. If any one has any ideas as to why this is happening also please share as I really dont get why that is happening.

But my main problem is that the time to clone the object takes notablely longer each time around the above loop first by a few seconds then eventually up to 5 mins etc.

Any body have any ideas as to why this is happening?

EDIT I have profiled the application while it was running the majority of the work over 90% is being done by BinaryFormatter.Deserialize(memoryStream) and here is fix population its doing nothing overly complex that would contribute to this problem.

private static List<Chromosome<Gene>> fixPopulation(Random rand, List<Chromosome<Gene>> oldPopulation, SelectionMethod selectionMethod, int populationSize)
    {
        if (selectionMethod == SelectionMethod.Tournament)
        {
            oldPopulation.Sort();
        }
        else
        {
            //NSGAII sorting method
        }

        oldPopulation.RemoveRange(populationSize, (oldPopulation.Count - populationSize));

        for (int i = 0, n = populationSize / 2; i < n; i++)
        {
            int c1 = rand.Next(populationSize);
            int c2 = rand.Next(populationSize);

            // swap two chromosomes
            Chromosome<Gene> temp = oldPopulation[c1];
            oldPopulation[c1] = oldPopulation[c2];
            oldPopulation[c2] = temp;
        }

        return oldPopulation;
    }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

陪我终i 2024-11-09 08:55:17

您可以使用二进制序列化来创建对象的快速克隆:

看看这个:

public Entity Copy()
        {
            System.IO.MemoryStream memoryStream = new System.IO.MemoryStream();

            System.Runtime.Serialization.Formatters.Binary.BinaryFormatter bFormatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
            bFormatter.Serialize(memoryStream, this);
            memoryStream.Seek(0, System.IO.SeekOrigin.Begin);
            IEntityForm entity= (IEntityForm)bFormatter.Deserialize(memoryStream);
            return entity;
        }

非常简单且有效!

You can use binary serialization to create a fast clone of your objects:

look at this :

public Entity Copy()
        {
            System.IO.MemoryStream memoryStream = new System.IO.MemoryStream();

            System.Runtime.Serialization.Formatters.Binary.BinaryFormatter bFormatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
            bFormatter.Serialize(memoryStream, this);
            memoryStream.Seek(0, System.IO.SeekOrigin.Begin);
            IEntityForm entity= (IEntityForm)bFormatter.Deserialize(memoryStream);
            return entity;
        }

really easy and working!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文