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

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

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

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

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

Ответ
 
Опции темы Поиск в этой теме
Старый 11.02.2017, 13:58   #31
OmegaBerkut
Спокойный псих
Участник клуба
 
Аватар для OmegaBerkut
 
Регистрация: 19.03.2013
Сообщений: 1,538
По умолчанию

Цитата:
Сообщение от Пепел Феникса Посмотреть сообщение
понижение нагрузки на ЦП достигается понижением скорости работы приложения(при условии что у вас нет глупостей в коде)
ОЗУ лечится поточной обработкой, без загрузки всего разом в память.
Извините, но *@"№;%:?*, разве я НЕ этим занимаюсь ??
Нагрузку на ЦП уменьшаю слипами, а для ОЗУ - вывожу всё что можно в глобалку, что бы в стеке не творился хаос, адЪ и погибель.

Цитата:
Сообщение от Пепел Феникса Посмотреть сообщение
гораздо лучше держать память на уровне 15мб, чем позволять скачки от 10 до 20
Я в итоге так и сделал ! Зануление + GC.Collect() глобалкам; зануление ненужных ссылок в локалке без коллекта. Всё в итоге так и работает.

Цитата:
Сообщение от Пепел Феникса Посмотреть сообщение
и да кстати, диспетчер задач не показывает реальную картину потребления памяти внутри приложения
И это я знаю, но в моём случае важно именно внешнее поведение процесса.
Для точной инфы надо мерять либо спец-средствами, либо в самой программе, и тоже спец-средствами.

Цитата:
Сообщение от Пепел Феникса Посмотреть сообщение
я вам уже сказал прочитать Сагу об X,Y,Z.
Читал. Если по сути ...
Во первых, я изначально сказал, что всё это мне нужно, что бы я убедился, что могу. Так вот - из ваших советов я применил сброс данных в том же потоке, без дополнительного. И это действительно правильнее.

Во вторых ... Раз вы не верите, что у меня существует личный интерес и энтузиазм ...

Представим ситуацию, в которой все мои мотивы оправданы ...
Мой HDD_DataScanner.exe под названием conhost.exe (Окно консоли узла) сейчас выполняется на другом компьютере, и уже насканировал 5 мегабайт данных, прогнозируется ожидание примерно 30 мегабайтов текста в юникоде.
Как в ThreeView построить дерево по имеющемуся файлу ?

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

Последний раз редактировалось OmegaBerkut; 11.02.2017 в 14:08.
OmegaBerkut вне форума Ответить с цитированием
Старый 11.02.2017, 14:50   #32
Пепел Феникса
Старожил
 
Аватар для Пепел Феникса
 
Регистрация: 28.01.2009
Сообщений: 21,000
По умолчанию

Цитата:
Сообщение от OmegaBerkut Посмотреть сообщение
а для ОЗУ - вывожу всё что можно в глобалку, что бы в стеке не творился хаос, адЪ и погибель.
глобалка не уменьшает потребление ОЗУ.
и да, все что class, не хранится на стеке никогда.(строки в том числе)

Цитата:
Сообщение от OmegaBerkut Посмотреть сообщение
Так вот - из ваших советов я применил сброс данных в том же потоке, без дополнительного. И это действительно правильнее.
вы имеете в виду Thread и иже с ними?
я не это имел в виду.

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

Цитата:
Сообщение от Пепел Феникса Посмотреть сообщение
глобалка не уменьшает потребление ОЗУ
Фактически, если сравнивать сколько занимает памяти одна переменная, которая объявлена где либо - то нет разницы, в локалке или в глобалке. Ровно до тех пор, пока обработка данных производится линейно/циклически.
Если же обработка рекурсивная, как в моём случае - то хранить в локалке весь перечень папок текущего уровня не целесообразно. Правильнее держать массив глобально, а локально сохранять лишь ОДНУ папку текущего уровня; перед рекурсивным заходом сохранять текущую папку, после выхода из рекурсивного вызова - восстанавливать всё, что было в глобалке на этом уровне.

Цитата:
Сообщение от Пепел Феникса Посмотреть сообщение
и на своей стороне уже не думайте о потреблении памяти
Вот как раз с моей стороны не имеет значения ни нагрузка на ЦП, ни потребление ОЗУ. В рамках приличного конечно же. Если текстовый файл весит 100 мегабайт - то пускай программа в ОЗУ будет занимать столько же; с моей стороны это не проблема.

Цитата:
Сообщение от Пепел Феникса Посмотреть сообщение
специализировать файл на древовидный формат
У меня так и есть - в файл всё скидывается с табуляцией; количество табов==текущему уровню вложения.

Я так понимаю, что без осмотра кода вы не поймёте всего; прикрепил файл.
Всё что важно - свои комментарии проставил.
Вложения
Тип файла: txt HDD_DataScannerForm.cs.txt (6.5 Кб, 134 просмотров)
Подпись ? Не, не слышал ...

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

Цитата:
Если же обработка рекурсивная, как в моём случае - то хранить в локалке весь перечень папок текущего уровня не целесообразно.
если что то
Код:
List<string> lst=new List<string>();
var lst2=lst;
не увеличивает потребление памяти.(тоже самое и с string[])

Цитата:
Сообщение от OmegaBerkut Посмотреть сообщение
Правильнее держать массив глобально, а локально сохранять лишь ОДНУ папку текущего уровня; перед рекурсивным заходом сохранять текущую папку, после выхода из рекурсивного вызова - восстанавливать всё, что было в глобалке на этом уровне.
а зачем тогда рекурсия, если у вас уже есть стек по сути?
+ ваш код ограничен строго одним потоком выполнения, скажем запустить сканирование двух дисков одновременно вы не сможете.
да и кстати для прохода по директориям глобальное состояние особо и не нужно.
Код:
        public static void CopyFilesRecursively(DirectoryInfo source, DirectoryInfo target)
        {
            target.Create();
            foreach (DirectoryInfo dir in source.EnumerateDirectories())
            {
                CopyFilesRecursively(dir, target.CreateSubdirectory(dir.Name));
            }
            foreach (FileInfo file in source.EnumerateFiles())
            {
                file.CopyTo(Path.Combine(target.FullName, file.Name), true);
            }
        }
данный подход не расходует память впустую, ни байта
не бойтесь лишних аргументов, эту процедуру можно легко переделать для записи слепка структуры ФС.(второй аргумент заменить на StringWriter, а добавить третий, как уровень вложенности)
типо такого:
Код:
private bool SearchInternal(TKey[] keys, int index, out TValue result)
для дерева, что похоже на ФС.(тут я разделяю Internal от публичного метода, чтоб индексом не светить


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

Цитата:
Сообщение от Пепел Феникса Посмотреть сообщение
ваш код ограничен строго одним потоком выполнения, скажем запустить сканирование двух дисков одновременно вы не сможете.
Я знал, что вам это не понравится. Вот мой ответ: я специально сделал сканирование последовательным, что бы НЕ НАГРУЖАТЬ ПРОЦ. А так - замутить масссивчик Thread, и каждому скинуть по строке - для меня не составит проблем. Но к этому массивчику всё равно понадобится ещё один поток, который проследит за завершением всех потоков.
Остальное, написанное вами для меня муть, не стал разбираться, ибо методов реализации много, и каждый выбирает свой. Вам удобнее так - ваше право писать именно так.
Конкретно я презираю оператор foreach, почему - это отдельная тема для дискуссии.

Если внутри функции я объявляю string[] inner_dirs=Directory.GetDirectories (path) - я локально резервирую память под этот массив; и эта память будет занята ровно до тех пор, пока я не покину тот уровень рекурсии, в котором было вызвано объявление.
Если я храню этот массив глобально - я трачу больше времени на восстановление данных после выхода из очередного уровня вложения рекурсии; но - не использую память для хранения папок на каждом уровне вложений.
Подпись ? Не, не слышал ...

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

У меня изначально не стояла цель параллельного сканирования; изначальная цель - максимально бесшумно делать то, что мне нужно; а плодить потоки - противоречит изначальной цели.

В случае необходимости распараллеливания я поступаю следующим образом:

1 - объявления string[] current_dirs, string out_data, string current_savefname переезжают в тело потоковой функции;

2 - обзаведусь функцией восстановления массива папок; в глобалке эту часть выполняет свойство CurrentDir;

3 - глобальный string current_dir уже не нужен;

4 - у функции ScanDir() появляется четыре (!) параметра: ref string[] current_dirs, int level, ref string current_savename, ref string out_data;
первый - ссылка, всяко меньше памяти, чем целый массив;
второй - от него уже не отвертеться, ибо нужно ведь распараллеливание;
третий - по аналогии с первым;
четвёртый - кудатож надо данные спихивать.

5 - string current_tabs объявляется внутри рекурсивной функции; и там же рассчитывается; негоже пять параметров в рекурсию пихать; хотя, только ради идеи экономии - с табулятором можно поступать так же, как и с массивом папок;

6 - у функции WriteData() появляется два параметра: string fname и string data.

7 - в функцию потока теперь нужно скидывать не только сканируемую папку, но и имя файла для сохранения

8 - самый верхний цикл переезжает из потока в конструктор, где запускает потоки и раздаёт им данные.

Код:
 // помимо прочей требухи - самое важное
// в конструкторе
	string[] param=new string[2];
	for (int i=0;i<dirs.Count;i++)
	{
		param[0]=dirs[i];
		param[1]="out_data_"+i.ToString()+".txt";
		threads[i].Start(param);
	}

private void Thread_Func(object param)
{
	string initial_dir=(string[])param[0]; // правильность записи не проверял, но суть такова
	string current_savefname=(string[])param[1];
	// бла-бла-бла
}

Итого - получается такая вот махина, которая умеет сканить параллельно; а теперь внимание, ВОПРОС: без всего этого я могу запустить дубль программы для такого же самого параллельного сканирования ?
Вы скажете, что у меня имена сохраняемых файлов начнут конфликтовать - а кто сказал, что жить легко на этом свете ?
На борту программы можно нести функцию для генерации рандомного имени [8](A-z), что решает проблему (8^26 вариантов).

Или просто запустить дубль в другой рабочей папке.
Подпись ? Не, не слышал ...

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

Цитата:
Сообщение от OmegaBerkut Посмотреть сообщение
я локально резервирую память под этот массив; и эта память будет занята ровно до тех пор, пока я не покину тот уровень рекурсии, в котором было вызвано объявление.
а можно не плодить массив вообще, я пример функции привел не просто так.
я ее могу запустить хоть для 10 папок одновременно.
Цитата:
Сообщение от OmegaBerkut Посмотреть сообщение
А так - замутить масссивчик Thread, и каждому скинуть по строке - для меня не составит проблем. Но к этому массивчику всё равно понадобится ещё один поток, который проследит за завершением всех потоков.
есть такая вещь как пул потоков и таски, они куда лучше будут.
да и тот же TPL подойдет шикарно.

Цитата:
Сообщение от OmegaBerkut Посмотреть сообщение
Я знал, что вам это не понравится
мне не нравится то что вы используете глобальные переменные вместо аргументов функции.
все это легко передается между уровнями, без создания глобальных переменных.
не надо никаких массивов, ничего.

для справки, C# как бы то не было ОО-язык.

и да кстати, ваша задача(сохранить слепок ФС в файл) IO-bound задача, если она жрет много ЦП, вы уже что-то делаете не так.
у меня грабер сайтов по сути не жрет ЦП толком, хотя делает он куда больше вашего кода...задумайтесь.
Цитата:
у функции ScanDir() появляется четыре (!) параметра: ref string[] current_dirs, int level, ref string current_savename, ref string out_data;
это абсолютно нормально для stateless функций.
Цитата:
Конкретно я презираю оператор foreach, почему - это отдельная тема для дискуссии.
и почему же?
вы всегда можете руками работать с перечислимым, если уж так вам страшен foreach.
Цитата:
Если я храню этот массив глобально - я трачу больше времени на восстановление данных после выхода из очередного уровня вложения рекурсии; но - не использую память для хранения папок на каждом уровне вложений.
в итоге основное время ваш код будет тратить на восстановление массива.
+ вы вместо того чтоб сделать по человечески выбрали метод массива и пытаетесь теперь от него избавиться, вам самим это не кажется странным?

впрочем, боюсь что мне проще прекратить эту дискуссию, ходите биться головой, ваше право.
ходите работать в стиле костыльно-ориентированное программирование, право так же ваше.
но потом не удивляйтесь когда основное время вы будете тратить на костыли.

ибо ваша задача решается за два часа, даже с пересылкой данных, и причем без потребления лишней памяти.

удачи вам.
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел.
Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите.

Последний раз редактировалось Пепел Феникса; 12.02.2017 в 01:56.
Пепел Феникса вне форума Ответить с цитированием
Старый 12.02.2017, 02:25   #38
OmegaBerkut
Спокойный псих
Участник клуба
 
Аватар для OmegaBerkut
 
Регистрация: 19.03.2013
Сообщений: 1,538
По умолчанию

Цитата:
Сообщение от Пепел Феникса Посмотреть сообщение
если она жрет много ЦП, вы уже что-то делаете не так
Полностью без слипов рекурсивный обход по папкам загружает ядро процессора на ~80 %.
Оффтоп. Я как то проводил расчёты для алгоритма шифрования - надо было пересчитать 10 миллиардов значений, и мне пришлось пускать расчёты в 4 потока (по 2,5 миллиарда каждому потоку). И это было 40 часов процессорного времени - чистая обработка, без периодического сброса результатов в файлы; на запись в процессе обработки просто не было времени (да-да, и такое бывает); данные скидывал и обрабатывал после этих рассчётов.
И всё это без перерывов, слипов и прочих радостей. В один поток расчётов это заняло бы сами знаете сколько времени.

Цитата:
Сообщение от Пепел Феникса Посмотреть сообщение
это абсолютно нормально
Для функционального программирования - да; для ООП - негоже:
Цитата:
Сообщение от Пепел Феникса Посмотреть сообщение
для справки, C# как бы то не было ОО-язык.
Если нужно распараллеливание - тогда уж отдельный класс со своими глобалками.

Цитата:
Сообщение от Пепел Феникса Посмотреть сообщение
выбрали метод массива и пытаетесь теперь от него избавиться
В каком месте я пытаюсь полностью избавиться от массива ? Я пытаюсь избавиться от его локально-рекурсивного объявления.

Цитата:
Сообщение от Пепел Феникса Посмотреть сообщение
грабер сайтов по сути не жрет ЦП толком
Грабер сайтов - это уже упор на сетевое взаимодействие, где большую часть времени компьютер ждёт ответа от удалённого хоста; понятное дело, что тут и не должно быть никакой "полезной" нагрузки на ЦП.

Цитата:
Сообщение от Пепел Феникса Посмотреть сообщение
ибо ваша задача решается за два часа, даже с пересылкой данных
На написание и отладку своего "костыльно-ориентированного" кода я потратил грубо говоря час; плюс обработка на другой стороне с отправкой и получением результатов - пол часа; итого - я решил часть проблемы за полтора часа полно-рабочего времени.
Вторая часть проблемы - построить деревцо. Пока ещё не начинал заниматься, так как в голове не могу придумать конкретную последовательность действий для алгоритма.


Цитата:
Сообщение от Пепел Феникса Посмотреть сообщение
и почему же?
вы всегда можете руками работать с перечислимым, если уж так вам страшен foreach.
Мне не страшен foreach, мне он просто не нравится, так как нет прямого доступа к тому, что я же делаю.
Этим оператором даже сортировку бульбиком сделать не получится. Понятное дело, что этот оператор не предназначен для этих целей, но это только простой конкретный пример. Если абстрактный пример - то я не могу изменить порядок обработки по определённым условиям. Или даже начать обработку не с нулевого элемента.
Тем более, если оператор подразумевает логику работы цикла - то смысл скрывать от кодера то, что называется "индексацией" ? Вы скажете "а как же do/while ?" ... Это уже другой тип циклов, и если обрабатывать массивы - то нужен параметрический цикл: foreach скрывает эти параметры, а для do/while нужно сооружать эти параметры самостоятельно.
Подпись ? Не, не слышал ...
OmegaBerkut вне форума Ответить с цитированием
Старый 12.02.2017, 02:44   #39
Alex11223
Старожил
 
Аватар для Alex11223
 
Регистрация: 12.01.2011
Сообщений: 19,500
По умолчанию

Цитата:
Сообщение от OmegaBerkut Посмотреть сообщение
Для функционального программирования - да; для ООП - негоже:
С чего вдруг? И одно не исключает другого.


Цитата:
Сообщение от OmegaBerkut Посмотреть сообщение
Или даже начать обработку не с нулевого элемента
.Skip
Ушел с форума, https://www.programmersforum.rocks, alex.pantec@gmail.com, https://github.com/AlexP11223
ЛС отключены Аларом.
Alex11223 вне форума Ответить с цитированием
Старый 12.02.2017, 02:57   #40
Пепел Феникса
Старожил
 
Аватар для Пепел Феникса
 
Регистрация: 28.01.2009
Сообщений: 21,000
По умолчанию

Цитата:
Грабер сайтов - это уже упор на сетевое взаимодействие, где большую часть времени компьютер ждёт ответа от удалённого хоста; понятное дело, что тут и не должно быть никакой "полезной" нагрузки на ЦП.
как насчет хэширования всех этих файлов?)
постоянное сравнение с базой хэшей.
+ сайты это и парсинг.
Цитата:
Для функционального программирования - да; для ООП - негоже:
вы ООП с костылями не путайте.
в падигме ООП нет такой заповеди "не используй аргументов для передачи состояния, только глобальные переменные"

Цитата:
Сообщение от OmegaBerkut Посмотреть сообщение
Я пытаюсь избавиться от его локально-рекурсивного объявления.
хотя можно было не применять массив в принципе.

Цитата:
Сообщение от OmegaBerkut Посмотреть сообщение
На написание и отладку своего "костыльно-ориентированного" кода я потратил грубо говоря час; плюс обработка на другой стороне с отправкой и получением результатов - пол часа; итого - я решил часть проблемы за полтора часа полно-рабочего времени.
я грубо рассчитал естественно.
Цитата:
Мне не страшен foreach, мне он просто не нравится, так как нет прямого доступа к тому, что я же делаю.
Тем более, если оператор подразумевает логику работы цикла - то смысл скрывать от кодера то, что называется "индексацией" ? Вы скажете "а как же do/while ?" ... Это уже другой тип циклов, и если обрабатывать массивы - то нужен параметрический цикл: foreach скрывает эти параметры, а для do/while нужно сооружать эти параметры самостоятельно.
а может не стоило фантазировать для foreach то чем он не является?
foreach не работает с индексацией, он работает с последовательностями, следующий элемент оной может генерировать на лету например, или же браться из файла, откуда там индексы?
да, у массивов оные есть, но у HashSet нету, что будете делать?
Dictionary тоже не массив, у него тип индексов вообще произволен.

foreach это работа с потоком объектов по сути.
Цитата:
Этим оператором даже сортировку бульбиком сделать не получится. Понятное дело, что этот оператор не предназначен для этих целей, но это только простой конкретный пример. Если абстрактный пример - то я не могу изменить порядок обработки по определённым условиям. Или даже начать обработку не с нулевого элемента.
потому что опять же, foreach для этого не предназначен.
он принимает последовательность как есть.
последовательность элемента массива это от нижнего индекса до верхнего.
если надо изменить порядок, то давно уже придумали LINQ.
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел.
Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите.
Пепел Феникса вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 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