String и StringBuilder
Недавно отпимизировал алгоритм: раньше он работал 18 минут. Сейчас 0.4 секунды. Было необходимо сделать для сайта sitemap, дабы скормить его поисковым гиганатам. В таблице базы данных содержалось всего 18 000 строк, и алгоритм пробегал по ней за 18 минут, и делалось это вот так:
string GenerateSmap()
{
string strResult = "";
SqlConnection SQLDB;
SqlCommand SQLDBCMD;
SqlDataReader SqlR;
SQLDB = new SqlConnection(strConn);
SQLDBCMD = new SqlCommand("SELECT id_article, article_num FROM articles", SQLDB);
SQLDB.Open();
SqlR = SQLDBCMD.ExecuteReader();
while (SqlR.Read())
{
strResult = strResult + ("<url>\r\n");
strResult = strResult + ("<loc>http://www.kazved.ru/article/" + SqlR["id_article"] + ".aspx</loc>\r\n)");
strResult = strResult + ("<changefreq>monthly</changefreq>\r\n");
strResult = strResult + ("<priority>0.8</priority>\r\n"); strResult = strResult + ("</url>\r\n");
}
SqlR.Close();
SQLDB.Close();
return strResult;
}
Представляете, 18 (!!!) минут! это целую минуту на каждую 1000 строк! Дело заключается не в SQL, а в «strResult = strResult + ...». Дело в том, что, каждый раз, когда мы обращаемся к System.String, мы каждый раз создаем новый объект string в памяти. Это сильно замедляет процесс, если вы часто делаете повторяющиеся изменения в стринге. Для этих целей горздо продуктивнее использовать класс System.Text.StringBuilder, он не создает новый объект в памяти, а оперирует уже имеющимся. В данном примере, использование StringBuilder будет таким:
string GenerateSmap() { StringBuilder strResult = new StringBuilder();
...
while (SqlR.Read())
{
strResult.Append("<url>\r\n"); strResult.Append("<loc>http://www.kazved.ru/article/" + SqlR["id_article"] + ".aspx</loc>\r\n)");
strResult.Append("<changefreq>monthly</changefreq>\r\n"); strResult.Append("<priority>0.8</priority>\r\n"); strResult.Append("</url>\r\n");
}
...
return strResult.ToString();
}
После такого преобразования, функция стала выполняться не 18 минут, а 0.4 секунды! Мы имеем ускорение в 2700 раз!Кстати, при сооздании StringBuilder’a, вы можете задать его размер, прописав свойство Capacity, или используя оверлоад:
MyStringBuilder.Capacity = 25;
StringBuilder MyStringBuilder = new StringBuilder("Hello World!", 25);
Так же, можно прочитать и задать его длину, для этого используется свойство Length. Если вы здаете Length больше чем Capacity, то Capacity увеличится и станет равным Length. А если вы зададите Length меньше чем длина строки, что находится в StringBuilder’е, стринг билдер сам уменьшит эту строку.
Редактирование строки в StringBuilder.
Для редактирование строк в StringBuilder есть 5 методов: StringBuilder.Append, StringBuilder.AppendFormat, StringBuilder.Insert, StringBuilder.Remove, StringBuilder.Replace Названия у них говорят сами за себя, примеры использования простые. Метод StringBuilder.Append добавляет данные в конец строки, уже показывал в начале статьи, но пусть еще раз:
StringBuilder MyStringBuilder = new StringBuilder("Йа ");
MyStringBuilder.Append("креведко");
Console.WriteLine(MyStringBuilder);
StringBuilder.AppendFormat делает тоже самое что и Append, но еще применяет IFormattable, который принимает стандартные шаблоны форматирования.
int MyInt = 25;
StringBuilder MyStringBuilder = new StringBuilder("На ашем счету ");
MyStringBuilder.AppendFormat("{0:C} ", MyInt);
Console.WriteLine(MyStringBuilder);
StringBuilder.Insert делает вставку в текстовую строку в указанном месте:
StringBuilder MyStringBuilder = new StringBuilder("Hello World!");
MyStringBuilder.Insert(6,"Beautiful ");
Console.WriteLine(MyStringBuilder);
StringBuilder.Remove удаляет в указанном месте указанное количество символов:
StringBuilder MyStringBuilder = new StringBuilder("Hello World!");
MyStringBuilder.Remove(5,7); //с 5го по 7ой, нумерация идет от 0
Console.WriteLine(MyStringBuilder);
StringBuilder.Replace просто заменяет указанные символы на другие:
StringBuilder MyStringBuilder = new StringBuilder("Hello World!");
MyStringBuilder.Replace('!', '?');
Console.WriteLine(MyStringBuilder);
Тру, взял на заметку.
Нашет тут моленькие подскозки для себя, спасибо.
РЕспект за статью, я уж думал все, нужно другой язык программирования учить или еще что то в этом проде .... просто не знал принципа работы Стринг ..
Большое спасибо, очень полезная информация