использование string
for(int t=0; t<10000/*так к примеру*/; t++)
{
str += "Какой-то текст";
}
вот, данная система начинает очень медленно работать при достижении str определенного размера.
Как быть в такой ситуации?
Сейчас решил проблему так: создаю массив переменных типа string и в этом же цикле тусую в каждую стрингу по пару-десять записей - производительность возросла в сотни раз.
Может можно как иначе?
string str = "";
for(int t=0; t<10000/*так к примеру*/; t++)
{
str += "Какой-то текст";
}
вот, данная система начинает очень медленно работать при достижении str определенного размера.
Как быть в такой ситуации?
Сейчас решил проблему так: создаю массив переменных типа string и в этом же цикле тусую в каждую стрингу по пару-десять записей - производительность возросла в сотни раз.
Может можно как иначе?
Попробуй StringBuilder.
Можно метод Append из StringBuilder, для увеличения скорости можно воспользоваться массивом символов фиксированного размера. В твоём варианте львиную долю производительности забирает сборщик мусора, так как ему приходится удалять предыдущую копию строки в цикле.
Ну, сборщик мусора-то запустится только тогда, когда память закончится, а вот выделение каждый раз памяти под новый объект и копирование данных из старого места в новое очень сильно на себя тянет ресурсов.
Вообще, StringBuilder начинает делать простую конкатенацию строк вроде начиная приблизительно с 50000 операций (кто-то там тестил). До этого они по производитеьности приблизительно одинаковы.
А как пользоваться массивом символов?
1) На текущий объект не установлено ни одной активной ссылки;
2) При выходе из области видимости (например, возврат управления из функции);
3) Банальный конец памяти;
Для подтверждения этих слов можно открыть журнал MSDN Magazine за май 2005 на странице 11.
Попробуй StringBuilder.
Спасибо, помогло !!!
Сборщик мусора уничтожает объекты, когда:
1) На текущий объект не установлено ни одной активной ссылки;
2) При выходе из области видимости (например, возврат управления из функции);
3) Банальный конец памяти;
Для подтверждения этих слов можно открыть журнал MSDN Magazine за май 2005 на странице 11.
Это да, но условия 1) не достаточно для моментального включения сборщика мусора. Т.е. он не включается для при появлении нового объекта, на который нет активных ссылок. Процедура сборки мусора включает в себя фрагментацию кучи, поэтому он работает не так часто, как кажется, т.к. вся процедура - ресурсоемкая штука. А вот выполнение одновременно условий 1) и 3) достаточно для включения сборщика.
Условие 2), как я понял или равно 1) или в случае value-type объектов происходит очистка стека уже без сборщика.
P.S. можно открыть отдельную ветку для обсуждения нюансов работы с памятью, а то много чего там есть интересного.
1) Вызове Finalize
2) Вызове IDisposable.Dispose
3) Вызове GC.Collect
4) MSIL-инструкцией POP
Куча делится на GC Heap, где размещаются объекты малого размера и LOH (Large Object Heap) для объектов>85000 байт. Вот LOH не уплотняется при локальном сборе, а GC Heap уплотняется. Под уплотнение отводятся определённые кванты времени и условия. Например, сборщик мусора вызывается при переключения контекста (при передаче управления потоку или процессу). К глобальному сбору относится (перемещение объекто в LOH) выгрузка домена приложения и банальная нехватка памяти. Сборщик мусора не отвечает за установку активных ссылок. За это отвечает сам экземпляр, информацию об этом можно получить из TypeHandle и EECLass этого экземпляра. Поэтому ресурсов для уплотнения GC Heap много не надо и сборка в GC Heap произойдёт при наличии пассивных ссылок в момент переключения контекста.
А существует ещё один способ сборки: При JIT-клмпиляции компилятор может узнать, в каком месте кода происходит последнее использование объекта. Пример:
object o=new object();
int x=6;
object[] b=new object[2];
b[0]=o;
b=null;
JIT-компилятор определяет место удаления экземпляра o так:
объекта. Пример:
1)
object o=new object();
o.Finalize();//
int x=6;
object[] b=new object[2];
b[0]=o; //экземпляр o ещё используется,
//переносим Finalize сюда
b=null;
2)
object o=new object();
o.Finalize();//
int x=6;
object[] b=new object[2];
b[0]=o;
b=null; //в b содержится ссылка на o
3)
object o=new object();
o.Finalize();//
int x=6;
object[] b=new object[2];
b[0]=o;
b=null;
o.Finalize();
Таким образом на этапе JIT компиляции определяется места для вызова сборки мусора
Сборщик мусора вызвается при:
1) Вызове Finalize
Это не так, легко проверяется. Обычно Finalize используется для удаления неуправляемых ресурсов.
Больше спорить не буду ;), т.к. про LOH, к сожалению, ничего не знаю.
Я к тому, что это борладовская реализация, даже названия методов те же.
Совпадения сигнатур и алгоритмов,не означает совпадение реализаций.
public void main()
//Реализация
{
int a=5,b=6,c;
c = a;
a = b;
b = c;
}
//Сигнатура
public void exchenge(int a, int b)
//Реализация
{
int c = a;
a = b;
b = c;
}
//Сигнатура
public void main()
//Реализация
{
int a=5,b=6;
exchenge(a,b);
}
//алгоритм
Дано: а,б
вводим временную переменную с
с:=а
а:=б
б:=с