【问题标题】:large list of strings should be impossible大的字符串列表应该是不可能的
【发布时间】:2015-06-08 13:51:44
【问题描述】:

我在存储字符串列表的 C# 控制台应用程序中运行了代码。此代码的目标是在 1 秒内创建尽可能多的字符串“q”集合。这只是对我编程能力的一种锻炼,并没有实际应用。

当我运行此代码时,它会在 1 秒内自行停止,当我计算所有字符串中的所有“q”时,我得到 214,870,505,313,584,即数百万亿。字符“q”占用一个字节,如果这个东西有 200 万亿字节,则意味着字符串列表超过 2 TB。

这怎么可能,是否正在进行某种自动压缩?有没有办法关掉它?

如果需要,这里是代码。

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace ConsoleAppWebScrape
{
    class Program
    {
        //the origional string
        static string l = "q";
        static DateTime d;
        static List<string> output = new List<string>();

        static void Main(string[] args)
        {
            //hit enter to start
            Console.Read();
            d = DateTime.Now;

            //start the string doubling thread
            Thread thred2 = new Thread(new ThreadStart(doubleL));
            thred2.Start();
            //start the write to list thread                                                                                               
            Thread thred1 = new Thread(new ThreadStart(writeToFile));
            thred1.Start();

            while (haveTime())
            {
               //pause current thread for the remander of the second. 
            }

            long lo = howmany();

            Console.WriteLine(lo);
            Console.ReadLine();
        }

        //determines the amount of "q"s in the list of strings
        static long howmany()
        {
            long lo = 0;
            foreach (string s in output)
            {
                lo += s.Length;
            }
            return lo;
        }
        //writes to the list of strings.
        static void writeToFile()
        {
            while (haveTime())
            {
                output.Add(l);
            }
        }
        //builds a string by doubling the origional string
        static bool tobig = false;
        static void doubleL()
        {
            while (haveTime() && !tobig)
            {
                if (l.Length < 268435456)
                {
                    l = l + l;
                }
                else
                {
                    tobig = true;
                }
            }
        }
        //bool to determin if it is running inside one second
        static bool haveTime()
        {
            if ((DateTime.Now - d).TotalSeconds < 1)
            {
                return true;
            }
            return false;
        }
    }
}

【问题讨论】:

  • 你是对字符串的长度求和,而不是 q 的数量。
  • 你不断添加相同的字符串。如果你使用output.Add("q"); 而不是output.Add(l); 我想你会遇到内存不足的异常。
  • @ZoharPeled 这不会改变任何事情。您的代码仍然会一遍又一遍地添加相同的字符串。
  • @Servy 如果是output.Add(new string("q")); 会怎样?同样的事情?
  • 另外,char "q" 不占用一个字节 - 在 .NET 中 strings 是 UTF-16,这意味着它们每个字符占用两个字节,或者某些字符占用四个字节(Unicode U+10000 到 U+10FFFF)。字符q 表示为两个字节。

标签: c# string list compression


【解决方案1】:

我前段时间读到字符串存储在堆上并被引用。由于它一遍又一遍地使用同一个字符,因此您可能会创建数万亿个对同一个物理地址的引用。

【讨论】:

  • 正确。您一遍又一遍地将相同字符串的引用添加到第一个线程中的列表中,直到第二个线程更改字符串,然后第一个线程广告一个新的引用,依此类推。因此,在您的列表中,您有 X 引用“q”,Y 引用“qq”等等。 (X 和 Y 可能非常大,随着时间的推移它们会变大,因为将字符串加倍比添加对列表的引用需要更多时间)
  • @DenisYarkovoy 缺乏适当的同步意味着主线程实际上不会像你预期的那样频繁地反映第二个线程的更新,这意味着会有如果有适当的同步,相同字符串的副本会多得多。
猜你喜欢
  • 2013-07-10
  • 2016-10-26
  • 2017-10-23
  • 1970-01-01
  • 1970-01-01
  • 2011-09-19
  • 1970-01-01
  • 2020-11-01
  • 1970-01-01
相关资源
最近更新 更多