我需要创建一个布尔值数组,其范围可以是100,000s甚至数百万条。它还需要超快,因此每次迭代的每毫秒都很重要。
在开始循环时,我已经知道数组中将有多少条目。问题是,预先创建一个bool数组并通过索引填写值会更快(这是随机访问 - 可能会很慢吗?),或者我应该创建一个List<bool>
,继续添加条目到列表,最后返回.ToArray()
?
换句话说:
选项1
var array = new bool[size];
for (var n=0; n<size; n++)
array[n] = GetValue(n);
return array;
选项2
var list = new List<bool>();
for (var n=0; n<size; n++)
list.Add(GetValue(n));
return list.ToArray();
或许还有第三种方式甚至更快?
答案 0 :(得分:5)
使用System.Collections.BitArray
,不要担心速度。
上面你的建议只会浪费你的记忆力。这样可以优化速度和大小,并且可以很好地打包bool
值(每个字节8个,如众神所预期的那样:)。
回复以下评论:如果您使用BitArray
,一切都将为零。仅设置您拥有GetValue == true
。
答案 1 :(得分:2)
与第一个一起去。它可能是唯一的原因。 “慢”是指它是否保持从处理器缓存外部分页数据。
该列表将具有完全相同的问题,除了它还需要执行多个内存分配和副本。
答案 2 :(得分:2)
以下代码似乎显示(至少对我来说)本页讨论的方法,使用循环对bool[]
的简单分配是最快的。
代码似乎也告诉我,除非GetValue(n)
在计算上是微不足道的,否则分配字节的开销不是我希望优化的过程的一部分。
希望这在某种程度上有所帮助。
编辑:添加了运行结果(在我的机器上)
-- 187ms BitArray
-- 171ms List<bool>().ToArray
-- 168ms bool[] set only if true
-- 130ms bool[] always set
--11460ms bool[] always set with 'complex' GetValue()
class Program
{
static void Main(string[] args)
{
BitArray bitArray = new BitArray(10000000);
bool[] boolArray = new bool[10000000];
Stopwatch sw1 = new Stopwatch();
sw1.Start();
for (int i = 0; i < 10000000; i++)
{
bitArray[i] = GetMod2(i);
}
Console.WriteLine(sw1.ElapsedMilliseconds);
sw1.Restart();
var list = new List<bool>();
for (int i = 0; i < 10000000; i++)
list.Add(GetMod2(i));
var boolArray2 = list.ToArray();
Console.WriteLine(sw1.ElapsedMilliseconds);
sw1.Restart();
for (int i = 0; i < 10000000; i++)
{
bool nextVal = GetMod2(i);
if (nextVal)
bitArray[i] = true;
}
Console.WriteLine(sw1.ElapsedMilliseconds);
sw1.Restart();
for (int i = 0; i < 10000000; i++)
{
boolArray[i] = GetMod2(i);
}
Console.WriteLine(sw1.ElapsedMilliseconds);
sw1.Restart();
for (int i = 0; i < 10000000; i++)
{
boolArray[i] = GetRand(i);
}
Console.WriteLine(sw1.ElapsedMilliseconds);
Console.ReadLine();
}
static bool GetMod2(int i)
{
return (i % 2) == 1;
}
static bool GetRand(int i)
{
return new Random().Next(2) == 1;
}
}
答案 3 :(得分:0)
现在这是一件有趣的旧事。在@paul的启发下,我自己运行了10,000,000个布尔值的基准测试。考虑到对这个问题的评论中的讨论,结果(以毫秒为单位)非常令人惊讶:
BitArray:517
BitArray + CopyTo(数组):536
List + ToArray():455
bool array:483
这是什么样的书!尽管List<Bool>
每次都插入一条新记录,而bool[]
和BitArray
在每条记录上都被初始化为false
,而我只更新了它们价值应该是true
,List<bool>
一致,一致,甚至包括.ToArray()
电话。
另一种情况是实际应用比教科书知识更好,似乎......:)