Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > .NET Frameworks (точка нет фреймворки) > C# (си шарп)
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 09.02.2017, 23:52   #1
OmegaBerkut
Спокойный псих
Участник клуба
 
Аватар для OmegaBerkut
 
Регистрация: 19.03.2013
Сообщений: 1,538
По умолчанию Есть функция, хочется узнать мнение со стороны

Если следующую функцию вызвать с параметрами например "C:\", 0 - стек не рванёт ?
Код:
private void ScanDir(string intputpath, int level)
{
	string[] inner_paths;
	try
	{
		inner_paths=Directory.GetDirectories(intputpath);
	}
	catch { return; }
	string tabs="";
	int i=0;
	for (;i<level;i++)
		tabs+="\t";
	for (i=0;i<inner_paths.Length;i++)
	{
		info+=tabs+"<DIR> "+inner_paths[i]+"\r\n";
		ScanDir(inner_paths[i],level+1);
		inner_paths[i]=null;
	}
	inner_paths=null;
	try
	{
		inner_paths=Directory.GetFiles(intputpath);
	} catch { return; }
	for (i=0;i<inner_paths.Length;i++)
	{
		info+=tabs+inner_paths[i]+"\r\n";
			inner_paths[i]=null;
	}
}
Переменная string info - глобальная, до вызова функции опустошается руками.
Функцию планируется вызывать в потоке под try, и всё что отсканил - всё моё.

upd: перепилил так, что бы по минимуму использовать локальную область видимости: только индексатор и текущая папка; массив же спихнул в глобалку ... P. S. Ещё не проверял ...
Подпись ? Не, не слышал ...

Последний раз редактировалось OmegaBerkut; 10.02.2017 в 01:41.
OmegaBerkut вне форума Ответить с цитированием
Старый 10.02.2017, 02:36   #2
Пепел Феникса
Старожил
 
Аватар для Пепел Феникса
 
Регистрация: 28.01.2009
Сообщений: 21,000
По умолчанию

вы переделайте на хвостовую рекурсию, тогда никогда не рванет.
а по факту очень маловероятно, только если стек итак почти исчерпан.
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел.
Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите.
Пепел Феникса вне форума Ответить с цитированием
Старый 10.02.2017, 09:24   #3
Alex11223
Старожил
 
Аватар для Alex11223
 
Регистрация: 12.01.2011
Сообщений: 19,500
По умолчанию

Цитата:
Сообщение от Пепел Феникса Посмотреть сообщение
переделайте на хвостовую рекурсию
А она ж не гарантирована в C#.

Цитата:
Сообщение от OmegaBerkut Посмотреть сообщение
Переменная string info - глобальная, до вызова функции опустошается руками.
Зачем заниматься всякой фигней из-за придуманной проблемы?

Особенно совсем бессмысленными "оптимизациями" типа i и присваиваний null.

Если уж так боитесь этого, то лучше просто самому стек использовать, чем какие-то полумеры.

Для табов цикл кстати вообще не нужен:
Код:
new string('\t', level)
И для строки с путями
Код:
String.Join("\r\n", paths.Select(s => tabs + s))
И не используйте имена переменных с _, так не принято в C#.
Ушел с форума, https://www.programmersforum.rocks, alex.pantec@gmail.com, https://github.com/AlexP11223
ЛС отключены Аларом.

Последний раз редактировалось Alex11223; 10.02.2017 в 09:28.
Alex11223 вне форума Ответить с цитированием
Старый 10.02.2017, 12:55   #4
Пепел Феникса
Старожил
 
Аватар для Пепел Феникса
 
Регистрация: 28.01.2009
Сообщений: 21,000
По умолчанию

Цитата:
Сообщение от Alex11223 Посмотреть сообщение
А она ж не гарантирована в C#
я имел в виду и развернуть естественно.
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел.
Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите.
Пепел Феникса вне форума Ответить с цитированием
Старый 10.02.2017, 14:03   #5
OmegaBerkut
Спокойный псих
Участник клуба
 
Аватар для OmegaBerkut
 
Регистрация: 19.03.2013
Сообщений: 1,538
По умолчанию

Цитата:
Сообщение от Alex11223 Посмотреть сообщение
Зачем заниматься всякой фигней из-за придуманной проблемы?
Зачем критиковать без повода ? Что конкретно вам сделали мои "велосипеды" ?
Переменные без нижнего подчёркивания ? А как же тогда быть с осмысленным названием для тех переменных, у которых два и более слов ? Пусть даже и с сокращением ... Писать через большую букву ? Согласен. Но мне не удобно.
И почему НЕ ПРИНЯТО ? За это убивают ? Программа начинает работать хуже ?

P. S. Мне когда переменную нужно передать в класс для хранения, я не парюсь с названием переменной внутри класса, и параметром в конструкторе/функции ... В функции имя параметра обычное "blablabla", а внутри класса - "_blablabla".
Что значит вообще не принято ? Откуда категория и категоричность ?
Подпись ? Не, не слышал ...
OmegaBerkut вне форума Ответить с цитированием
Старый 10.02.2017, 14:10   #6
Alex11223
Старожил
 
Аватар для Alex11223
 
Регистрация: 12.01.2011
Сообщений: 19,500
По умолчанию

Цитата:
Сообщение от OmegaBerkut Посмотреть сообщение
Зачем критиковать без повода ? Что конкретно вам сделали мои "велосипеды" ?
Превратили нормальную функцию которая могла бы просто вернуть значение в непонятно что

Цитата:
Сообщение от OmegaBerkut Посмотреть сообщение
А как же тогда быть с осмысленным названием для тех переменных, у которых два и более слов ?
В C# принято использовать camelCase (для классов, свойств и методов — CamelCase).

Цитата:
Сообщение от OmegaBerkut Посмотреть сообщение
И почему НЕ ПРИНЯТО ? За это убивают ? Программа начинает работать хуже ?
Людям читать менее удобно Исходный код же в первую очередь для людей.
Всегда лучше придерживаться соглашений принятых в этом языке и т.п., самому же удобнее будет, и другие читатели кода не будут удивляться.
Ушел с форума, https://www.programmersforum.rocks, alex.pantec@gmail.com, https://github.com/AlexP11223
ЛС отключены Аларом.

Последний раз редактировалось Alex11223; 10.02.2017 в 14:29.
Alex11223 вне форума Ответить с цитированием
Старый 10.02.2017, 14:52   #7
OmegaBerkut
Спокойный псих
Участник клуба
 
Аватар для OmegaBerkut
 
Регистрация: 19.03.2013
Сообщений: 1,538
По умолчанию

Цитата:
Сообщение от Alex11223 Посмотреть сообщение
Превратили нормальную функцию которая могла бы просто вернуть значение в непонятно что
Это превращение для оптимизации использования памяти, что в моём случае имеет значение. Об оптимизации чуть дальше.
Цитата:
Сообщение от Alex11223 Посмотреть сообщение
В C# принято использовать camelCase (для классов, свойств и методов — CamelCase).
Про "негласные" правила наименования переменных и свойств я знаю.
Цитата:
Сообщение от Alex11223 Посмотреть сообщение
Людям читать менее удобно Исходный код же в первую очередь для людей
Код я пишу исключительно для себя; деньги мне за этот код никто не платит. Если я зарабатываю на своём кодинге - я стараюсь придерживаться всех гласных и "негласных" правил.
Если код чисто для себя, и/или за бесплатно, то в таком случае посторонние люди, которые сами залезли в мой код - это "их проблема", что "им неудобно читать".
Любой форум можно считать исключением - сюда я выкладываю лишь выдержку из кода, и здесь простите всего одно название переменной, которое не понравилось только вам ... Впредь буду стараться для вас писать код "по правилам".

Теперь об оптимизации ...
1. Я кода пришёл в шарп из C++ - то обнаружил, что мне не обязательно следить за использованием памяти; отсюда есть одна проблема: я могу "забыть", отвыкнуть от того, что нужно следить за использованием памяти; ибо если мне придётся вернуться обратно в C++, или перейти на какой нибудь Java - то я столкнусь с Leak Memmory. Именно поэтому я стараюсь придерживаться собственного принципа, который гласит - "если выполняешь выделение памяти - будь так добр сделать всё доступное, что бы освободить те переменные, которые используешь".
2. Ручное зануление ссылочных типов данных таки влияет на использование памяти. Можете сами посмотреть на поведение памяти процесса во время выполнения даже этого кода ... Если я зануляю все ссылки внутри массивов, и зануляю все массивы, и зануляю все ссылки - сборщик мусора освобождает память быстрее. И наоборот.
Раньше грешил использованием GC.Collect(), но когда настала пора обработки больших объёмов данных - я обнаружил, что цикл с этим коллектом работает примерно в 15 раз медленнее, поэтому сейчас я только зануляю ссылки. Зануление же ссылок на скорость влияет очень слабо, так как ссылки внутри массива я зануляю в том месте, где точно знаю, что это мне больше не понадобится; например - в конце тела цикла.
Подпись ? Не, не слышал ...
OmegaBerkut вне форума Ответить с цитированием
Старый 10.02.2017, 14:56   #8
pu4koff
Старожил
 
Аватар для pu4koff
 
Регистрация: 22.05.2007
Сообщений: 9,065
По умолчанию

Ничего, что из-за string info там куча хлама на каждый чих создаётся в памяти? Для таких компоновок строк так-то придуман StringBuilder.
pu4koff вне форума Ответить с цитированием
Старый 10.02.2017, 15:04   #9
Alex11223
Старожил
 
Аватар для Alex11223
 
Регистрация: 12.01.2011
Сообщений: 19,500
По умолчанию

Цитата:
Сообщение от OmegaBerkut Посмотреть сообщение
Я кода пришёл в шарп из C++ - то обнаружил, что мне не обязательно следить за использованием памяти
В С++ (а не чистом С) тоже есть smart pointer'ы, RAII и т.п.


Цитата:
Сообщение от OmegaBerkut Посмотреть сообщение
Это превращение для оптимизации использования памяти, что в моём случае имеет значение.
Почему вы так решили? Вы замеряли оба варианта (и не забыли про классические ошибки начинающих замеряльщиков типа не Release сборки)?

Без оптимизации программа хуже работает? Если нет, то только зря усложнили код добавив глобальную переменную Теперь при чтении и изменении кода всегда придется помнить о ней, не забывать вызывать функцию до ее чтения, а потом захочется еще где-нибудь поменять ее значение и все станет еще сложнее, а потом по привычке появятся еще такие же переменные.
Ну и сложнее выполнять код параллельно, писать тесты и т.п.
Ушел с форума, https://www.programmersforum.rocks, alex.pantec@gmail.com, https://github.com/AlexP11223
ЛС отключены Аларом.

Последний раз редактировалось Alex11223; 10.02.2017 в 15:14.
Alex11223 вне форума Ответить с цитированием
Старый 10.02.2017, 15:52   #10
OmegaBerkut
Спокойный псих
Участник клуба
 
Аватар для OmegaBerkut
 
Регистрация: 19.03.2013
Сообщений: 1,538
По умолчанию

Цитата:
Сообщение от pu4koff Посмотреть сообщение
Ничего, что из-за string info там куча хлама на каждый чих создаётся в памяти?
string info как раз и предназначен для того, что бы напихивать туда этот хлам. У меня параллельный поток раз в минуту сбрасывает данные в файл и опустошает переменную. Естесна потоки синхронизированы, вручную.
Цитата:
Сообщение от Alex11223 Посмотреть сообщение
Вы замеряли оба варианта
Я уже писал об этом в том же сообщении ...
Цитата:
Сообщение от OmegaBerkut Посмотреть сообщение
Ручное зануление ссылочных типов данных таки влияет на использование памяти. Можете сами посмотреть на поведение памяти процесса во время выполнения даже этого кода
Цитата:
Сообщение от Alex11223 Посмотреть сообщение
Без оптимизации программа хуже работает? Если нет, то только зря усложнили код
Вот этого я сейчас вообще не понял ...
Если БЕЗ оптимизации программа работает ХУЖЕ - то это нормально. ПОСЛЕ оптимизации программа работает лучше.
Цитата:
Сообщение от Alex11223 Посмотреть сообщение
зря усложнили код добавив глобальную переменную
Для оптимизации я добавил в глобалку следующую инфу:
1) массив текущих папок;
2) текущий уровень вложения;
3) текущую папку для глобалки;
4) строка табуляции;
5) свойства для п. 2 и 3.

2 для того, что бы в его свойстве (5) менять табулятор (4) по необходимости;
3 добавлено исключительно для свойства (5), в котором подгуржаются текущие папки (1).

В результате получилась вот такая вот конструкция:
Код:
private void ScanDir()
{
	CurrentLevel++;
	string save_dir=CurrentDir;
	int i=0;
	if (current_dirs.Length>0)
		for (;i<current_dirs.Length;i++)
		{
			out_data+=current_tabs+"<DIR> "+CutPathName(current_dirs[i])+"\r\n";
			try { CurrentDir=current_dirs[i]; }
			catch
			{
				out_data+=current_tabs+"<ошибка доступа>\r\n\r\n";
				CurrentDir=save_dir;
				continue;
			}
			waiting=true; // синхронизатор этого потока
			Thread.Sleep(120); // задержка, что бы второй поток успел скинуть данные
			while (saving) // ожидание флага из потока записи
				Thread.Sleep(100);
			waiting=false;
			ScanDir();
			CurrentDir=save_dir;
		}
	else
		out_data+=current_tabs+"<папки отсутствуют>\r\n";
	save_dir=null;
	string[] inner_files;
	try { inner_files=Directory.GetFiles(save_dir); }
	catch { out_data+=current_tabs+"<ошибка доступа>\r\n\r\n"; return; }
	if (inner_files.Length>0)
		for (i=0;i<inner_files.Length;i++)
		{
			out_data+=current_tabs+CutPathName(inner_files[i])+"\r\n";
			inner_files[i]=null;
		}
	else
		out_data+=current_tabs+"<файлы отсутствуют>\r\n";
	inner_files=null;
	CurrentLevel--;
}
И всё работает. С минимальными затратами памяти, что в данном случае, как я уже говорил - важно.
Собстна массив inner_files используется только после рекурсивной обработки всех предыдущих каталогов, и на память никак не влияет.
Функция CutPathName(string) - это тоже собственный велосипед, но создано не из-за интереса, а из-за того, что я не нашёл вырезатор имени папки для собственно папки (Path.GetDirectoryName(string) не работает для каталога); для файла же оригинал - Path.GetFileName(string).
В памяти самой функции нужно хранить только индексатор для цикла обработки папок (переносить в глобалку чревато), и собственно текущая папка уровня.

Теперь у меня встал вопрос, как построить ThreeView по имеющемуся файлу ... Первое что приходит в голову - погружать по событию разворачивания уровня, в зависимости от уровня, бла-бла-бла ... Это ещё нужно сидеть мудрить ... Но у меня полный обход диска D:\ - 10,5 мегабайт текста в юникоде; поэтому всё упирается в необходимость эмпирических наблюдений.
Подпись ? Не, не слышал ...
OmegaBerkut вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
узнать есть ли в массиве одинаковые числа lanabanana Общие вопросы Delphi 12 23.02.2016 15:42
С какой стороны функция LORDIF Общие вопросы C/C++ 1 28.05.2012 22:38
ListView как узнать есть ли строки? Кольша Мультимедиа в Delphi 4 27.08.2011 14:17
Стороны света ≈ стороны монитора Alex Cones Свободное общение 21 26.08.2010 17:15