【问题标题】:Slow running grid loop creating缓慢运行的网格循环创建
【发布时间】:2013-08-19 00:03:58
【问题描述】:

我正在尝试为 SQL 解析器创建一个图像,但我遇到了一个障碍,它开始运行非常快,但随着时间的推移,它逐渐变慢,并且内存一直在 60MB 和 300MB 之间波动。对于 3000x3000 的图像,它需要超过 16 个小时......

class Img2Sql
{
    static string table_name="test";
    static string sql_data="";
    public void Start()
    {
        Console.Write("Enter in a full path to file: ");
        String file_full_path = Console.ReadLine();

        Bitmap image = AForge.Imaging.Image.FromFile(file_full_path);
        Console.WriteLine("Loaded image from File.... {0}\n", file_full_path);

        int x = 0;
        int y = 0;
        int grid_x = image.Width;
        int grid_y = image.Height;

        Color pix;
        for (y = 0; y < grid_y; y++)
        {
            for (x = 0; x < grid_x; x++)
            {
                Console.WriteLine("({0},{1})",x,y);
                pix = image.GetPixel(x, y);
                sql_data += pixel_to_sql(pix, x, y);
                //process_slow_destory_max_min(ref pix, ref img, x, y);

            }
        }
        Console.WriteLine(sql_data);
    }

    static string pixel_to_sql(Color pix,int x,int y)
    {
        return ("INSERT INTO "+table_name+"(red,green,blue,x,y) VALUES("+pix.R+","+pix.G+","+pix.B+","+x+","+y+");\n");
    }
}

这似乎是一个相当直接的循环.....

【问题讨论】:

  • 我相信你有你的理由,但这是存储图像数据的最佳方式吗? 9,000,000 个插入是很多插入,大概是慢速部分。您是否查看过创建 DataTable 并使用消防水带光标插入它(参见 SqlBulkCopy)?
  • 您会针对这些数据运行什么样的 SQL 查询?
  • 我在为我的公司工作的一个更大的项目需要这个。我不能真正谈论整个项目,因为它仍处于 alpha 阶段,因此相当机密,但是我们确实需要此功能正常工作,因为它是核心组件。有人能帮我解决原始查询吗?
  • 至少使用 StringBuilder 来构建你的 sql_data,不是吗? ...不确定整体影响,但 string += string 9000000 次肯定没有帮助! ...祝你好运!
  • 您使用的是什么数据库管理系统?在一些有“图像”数据类型,例如mssql.

标签: c# .net sql loops


【解决方案1】:

我猜你的问题是字符串连接。在没有使用分析器测量实际性能的情况下,这只是一个猜测,但我确实看到了一个问题。

这一行:

 sql_data += pixel_to_sql(pix, x, y);

.NET 中的字符串是不可变的,因此当您添加到字符串时,它每次都会创建一个全新的字符串。因此,对于 3000x3000 的图像,您正在创建 900 万个字符串值,每个值都存储在内存中(一段时间)。

改用StringBuilder,如下所示:

StringBuilder sql_data_builder = new StringBuilder();
...
sql_data_builder.Append(pixel_to_sql(pix, x, y));
...
Console.WriteLine(sql_data_builder.ToString());

【讨论】:

    【解决方案2】:

    您可以尝试运行并行线程。就目前而言,代码将在单个内核上运行,并且可能您有一个可以利用的多处理器。将图像分割成块并在自己的线程中运行每个块。

    此外,使用 StringBuilder 会有所帮助,因为字符串操作非常慢,而且您有很多。

    【讨论】:

      【解决方案3】:

      您可能想查看SqlBulkCopy class

      然后你会按照这些思路做一些事情。

      Color pix;
      var myList = new List<myPixel>();
      for (y = 0; y < grid_y; y++)
      {
          for (x = 0; x < grid_x; x++)
          {
              Console.WriteLine("({0},{1})",x,y);
              pix = image.GetPixel(x, y);
              myPixels.Add(new myPixel() { Pixel = pix, X = x, Y = y});
          }
      }
      
      var dataTable = //convert your object to a datatable
      
      dbConnection.Open();
      //Save to SqlServer
      var bulkCopy = new SqlBulkCopy(dbConnection) { DestinationTableName = "YourDatabaseTableName"};
      
      bulkCopy.WriteToServer(dataTable);
      dbConnection.Close();
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-11-11
        • 2017-05-12
        • 2019-01-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多