我知道这个问题已经完成,但我对此略有不同。一些人指出这是过早的优化,如果我只是为了实用性和实用性而要求,这是完全正确的。我的问题源于一个实际问题,但我仍然很好奇。
我正在创建一堆 SQL 语句来创建一个脚本(因为它将被保存到磁盘中)来重新创建一个数据库模式(很容易有数百个表、视图等)。这意味着我的字符串连接是仅附加的。根据 MSDN,StringBuilder 的工作原理是保留一个内部缓冲区(肯定是 char[])并将字符串字符复制到其中并根据需要重新分配数组。
但是,我的代码有很多重复的字符串(“CREATE TABLE [”、“GO\n”等),这意味着我可以利用它们被实习,但如果我使用 StringBuilder 则不能,因为它们每次都会被复制。唯一的变量本质上是表名,并且已经作为字符串存在于内存中的其他对象中。
据我所知,在读入我的数据并创建包含架构信息的对象之后,我的所有字符串信息都可以通过实习重用,是吗?
假设这样,那么字符串的 List 或 LinkedList 会不会更快,因为它们保留了指向实习字符串的指针?然后,只需调用一次 String.Concat() 即可对长度完全正确的整个字符串进行一次内存分配。
List 必须重新分配 string[] 的 interned 指针,而链表必须创建节点并修改指针,所以它们不是“免费”的,但如果我连接数千个 interned 字符串,那么它们看起来就像他们会更有效率一样。
现在我想我可以想出一些关于每个 SQL 语句的字符计数的启发式方法并计算每种类型并得到一个粗略的想法并预先设置我的 StringBuilder 容量以避免重新分配它的 char[] 但我必须以相当大的幅度过冲以减少重新分配的可能性。
因此,对于这种情况,获得单个连接字符串的速度最快:
- 字符串生成器
- 列表<string> 的实习字符串
- LinkedList<string> 的实习字符串
- 具有容量启发式的 StringBuilder
- 还有什么?
作为一个单独的问题(我可能并不总是去磁盘)到上面:单个 StreamWriter 到输出文件会更快吗?或者,使用 List 或 LinkedList 然后将它们从列表中写入文件,而不是首先在内存中连接。
编辑: 根据要求,参考(.NET 3.5)到 MSDN。它说:“如果有可用空间,则将新数据附加到缓冲区的末尾;否则,分配一个新的更大的缓冲区,将原始缓冲区中的数据复制到新缓冲区,然后将新数据附加到新缓冲区缓冲。” 这对我来说意味着一个 char[] 被重新分配以使其更大(这需要将旧数据复制到调整大小的数组)然后追加。