C#对象比较和内存分配

C#对象比较和内存分配,c#,C#,我的同事为大多数基本类型提供了10个不同的函数字符串,int,double,bool 我对1000万个项目进行了测试,在我的机器上更改值比检查它们是否不同然后更改它们快40%左右。我测试了1000万个不需要更改的项目和1000万个需要更改的项目 当问他为什么他有这些功能,而不是仅仅改变价值观,因为它更便宜。他告诉我这是为了防止内存分配和内存碎片。因此,如果对象是相同的,它可以保留在相同的内存地址中,因此速度更快 public static void CopyIfDifferent(ref str

我的同事为大多数基本类型提供了10个不同的函数<代码>字符串,
int
double
bool

我对1000万个项目进行了测试,在我的机器上更改值比检查它们是否不同然后更改它们快40%左右。我测试了1000万个不需要更改的项目和1000万个需要更改的项目

当问他为什么他有这些功能,而不是仅仅改变价值观,因为它更便宜。他告诉我这是为了防止内存分配和内存碎片。因此,如果对象是相同的,它可以保留在相同的内存地址中,因此速度更快

public static void CopyIfDifferent(ref string vValueToCopyTo, string vValueToCopyFrom)
{
    if (!ValuesAreEqual(vValueToCopyTo, vValueToCopyFrom))
    {
        vValueToCopyTo = vValueToCopyFrom;
    }
}
public static bool ValuesAreEqual(string vValue1, string vValue2)
{
    if (vValue1 == null && vValue2 == null)
    {
        return true;
    }
    if (vValue1 == null || vValue2 == null)
    {
        return false;
    }
    return vValue1 == vValue2;
}
使用函数

Utils.CopyIfDifferent(ref GroupIDFK, item.GroupIDFK);

我的问题是。在更改之前检查值是否比仅更改值更好?如果是,为什么?

是的,我想交换指针(只是更改)比检查差异更有效,因为检查需要更多的时间


即使是最快的检查,也就是检查引用是否相等,引用交换也需要(或多或少)相同的时间。

关于防止内存分配和内存碎片,它对于值类型是无用的,因为引用没有变化。变量有自己的内存,其内容被替换,因此没有新的内存分配

IMHO在设置值类型之前检查相等性的唯一原因是:

  • 您需要引发一些事件(如OnChange)
  • 设置该值将启动一个复杂的操作,如将其保存到数据库或刷新缓存
  • 该值类型确实经常设置
一个简单的测试可以显示如何执行:

using System;
using System.Diagnostics;

namespace ConsoleApplication1
{
    public class Program
    {
        public static void Main(string[] args)
        {
            Process proc = Process.GetCurrentProcess();
            Console.WriteLine("GetTotalMemory:{0} PrivateMemorySize64:{1}  press enter to continue", GC.GetTotalMemory(true), proc.PrivateMemorySize64);
            Console.ReadLine();

            const int testCount = 1000000000;
            var stopWatch = new Stopwatch();

            int a = 2456;
            int b = 2456;
            stopWatch.Start();
            for (int i = 0; i < testCount; i++)
            {
                CopyIfDifferent(ref a, b);
            }
            stopWatch.Stop();
            Console.WriteLine("int equal CopyIfDifferent ElapsedMilliseconds:{0}", stopWatch.ElapsedMilliseconds);
            Console.WriteLine("GetTotalMemory:{0} PrivateMemorySize64:{1}  press enter to continue", GC.GetTotalMemory(true), proc.PrivateMemorySize64);
            GC.Collect();
            Console.ReadLine();
            stopWatch.Restart();
            for (int i = 0; i < testCount; i++)
            {
                a = b;
            }
            stopWatch.Stop();
            Console.WriteLine("int equal assignment ElapsedMilliseconds:{0}", stopWatch.ElapsedMilliseconds);
            Console.WriteLine("GetTotalMemory:{0} PrivateMemorySize64:{1}  press enter to continue", GC.GetTotalMemory(true), proc.PrivateMemorySize64);
            Console.ReadLine();
            string c = "dfsgdgdfg";
            string d = "dfsgdgdfg";
            stopWatch.Restart();
            for (int i = 0; i < testCount; i++)
            {
                CopyIfDifferent(ref c, d);
            }
            stopWatch.Stop();
            Console.WriteLine("string equal CopyIfDifferent ElapsedMilliseconds:{0}", stopWatch.ElapsedMilliseconds);
            Console.WriteLine("GetTotalMemory:{0} PrivateMemorySize64:{1}  press enter to continue", GC.GetTotalMemory(true), proc.PrivateMemorySize64);
            Console.ReadLine();
            stopWatch.Restart();
            for (int i = 0; i < testCount; i++)
            {
                c = d;
            }
            stopWatch.Stop();
            Console.WriteLine("string equal assignment ElapsedMilliseconds:{0}", stopWatch.ElapsedMilliseconds);
            Console.WriteLine("GetTotalMemory:{0} PrivateMemorySize64:{1}  press enter to continue", GC.GetTotalMemory(true), proc.PrivateMemorySize64);
            Console.ReadLine();
            int e = 2456;
            int f = 3465464;
            stopWatch.Restart();
            for (int i = 0; i < testCount; i++)
            {
                CopyIfDifferent(ref e, f);
            }
            stopWatch.Stop();
            Console.WriteLine("int different CopyIfDifferent ElapsedMilliseconds:{0}", stopWatch.ElapsedMilliseconds);
            Console.WriteLine("GetTotalMemory:{0} PrivateMemorySize64:{1}  press enter to continue", GC.GetTotalMemory(true), proc.PrivateMemorySize64);
            Console.ReadLine();
            stopWatch.Restart();
            for (int i = 0; i < testCount; i++)
            {
                e = f;
            }
            stopWatch.Stop();
            Console.WriteLine("int different assignment ElapsedMilliseconds:{0}", stopWatch.ElapsedMilliseconds);
            Console.WriteLine("GetTotalMemory:{0} PrivateMemorySize64:{1}  press enter to continue", GC.GetTotalMemory(true), proc.PrivateMemorySize64);
            Console.ReadLine();
            string g = "dfsgdgdfg";
            string h = "gdfhfghfghfghf";
            stopWatch.Restart();
            for (int i = 0; i < testCount; i++)
            {
                CopyIfDifferent(ref g, h);
            }
            stopWatch.Stop();
            Console.WriteLine("string different CopyIfDifferent ElapsedMilliseconds:{0}", stopWatch.ElapsedMilliseconds);
            Console.WriteLine("GetTotalMemory:{0} PrivateMemorySize64:{1}  press enter to continue", GC.GetTotalMemory(true), proc.PrivateMemorySize64);
            Console.ReadLine();
            stopWatch.Restart();
            for (int i = 0; i < testCount; i++)
            {
                g = h;
            }
            stopWatch.Stop();
            Console.WriteLine("string different assignment ElapsedMilliseconds:{0}", stopWatch.ElapsedMilliseconds);
            Console.WriteLine("GetTotalMemory:{0} PrivateMemorySize64:{1}  press enter to continue", GC.GetTotalMemory(true), proc.PrivateMemorySize64);
            Console.ReadLine();
        }
        public static void CopyIfDifferent(ref string vValueToCopyTo, string vValueToCopyFrom)
        {
            if (!ValuesAreEqual(vValueToCopyTo, vValueToCopyFrom))
            {
                vValueToCopyTo = vValueToCopyFrom;
            }
        }
        public static void CopyIfDifferent(ref int vValueToCopyTo, int vValueToCopyFrom)
        {
            if (vValueToCopyTo != vValueToCopyFrom)
            {
                vValueToCopyTo = vValueToCopyFrom;
            }
        }
        public static bool ValuesAreEqual(string vValue1, string vValue2)
        {
            if (vValue1 == null && vValue2 == null)
            {
                return true;
            }
            if (vValue1 == null || vValue2 == null)
            {
                return false;
            }
            return vValue1 == vValue2;
        }
    }
}
使用系统;
使用系统诊断;
命名空间控制台应用程序1
{
公共课程
{
公共静态void Main(字符串[]args)
{
Process proc=Process.GetCurrentProcess();
WriteLine(“GetTotalMemory:{0}privateMorysize64:{1}按enter键继续”,GC.GetTotalMemory(true),proc.privateMorysize64);
Console.ReadLine();
const int testCount=100000000;
var stopWatch=新秒表();
INTA=2456;
int b=2456;
秒表。开始();
对于(int i=0;i// Compare strings: case sensitive, current culture 
if (String.Equals(vValueToCopyTo, vValueToCopyFrom))
  vValueToCopyTo = vValueToCopyFrom;

// Compare strings: case insensitive and invariant culture 
if (String.Equals(vValueToCopyTo, vValueToCopyFrom, StringComparison.OrdinalIgnoreCase))
  vValueToCopyTo = vValueToCopyFrom;
  if (a == b)
    a = b;
  if (a != b) // != instead of ==
    a = b;
public static void CopyIfDifferent(ref string vValueToCopyTo, string vValueToCopyFrom)
{
    if (!ValuesAreEqual(vValueToCopyTo, vValueToCopyFrom))
    {
        vValueToCopyTo = vValueToCopyFrom;
    }
}
string s1 = "One";
string s2 = "Two";

CopyIfDifferent(ref s2, s1);
s2 = s1;
public static void CopyIfDifferent(ref int vValueToCopyTo, int vValueToCopyFrom)
{
    if (!ValuesAreEqual(vValueToCopyTo, vValueToCopyFrom))
    {
        vValueToCopyTo = vValueToCopyFrom;
    }
}

public static bool ValuesAreEqual(int vValue1, int vValue2)
{
    return vValue1 == vValue2;
}