Обновить
20
Денис@ftc

Программист

7
Подписчики
Отправить сообщение

Если набить желудок, меньше силы воли тратится на борьбу с чувством голода. А сила воли весьма конечна и лучше бы её экономить.
Также, я заметил, что продукты по-разному влияют на чувство голода. Например, сожрав пачку творога (200гр), я достаточно долго не хочу есть (хотя калорий в ней немного). А сожрав такое же по калориям количество овощей, я уже через час опять жрать хочу.

Справедливости ради скажу, что это может быть из-за того, что gmail достаточно дотошно режет письма на входе.
Т.е. мог быть какой-нить DMARC у медлаборатории не настроен и всё, gmail от них письмо не примет.

Ага, а потом получаем прогрессбар как в старых виндах при копировании - "Осталось миллион-с-чем-то минут" и "с чем-то" постоянно уточняется.

Well, для миллиона и у меня разницы не наблюдается

const int ITERATIONS = 100000000;

		static void Main(string[] args)
		{
			var start = DateTime.Now.Ticks;
			TestLoop();
			var delta = (DateTime.Now.Ticks - start) / TimeSpan.TicksPerMillisecond;
			Console.WriteLine("Loop: {0:0.000}", delta);
			start = DateTime.Now.Ticks;
			TestMethod();
			delta = (DateTime.Now.Ticks - start) / TimeSpan.TicksPerMillisecond;
			Console.WriteLine("Method: {0:0.000}", delta);
		}

		private static void TestMethod()
		{
			int result = 0;
			for (int i = 0; i < ITERATIONS; i++)
			{
				result = Method(result, i);
			}
			Console.WriteLine(result.ToString());
		}

		private static int Method(int a, int b)
		{
			return a + b;
		}

		private static void TestLoop()
		{
			int result = 0;
			for (int i = 0; i < ITERATIONS; i++)
			{
				result += i;
			}
			Console.WriteLine(result.ToString());
		}

Для ста миллионов она в общем-то есть. Однако только в Debug-версии (что понятно, потому что в Release метод инлайнится и IL-код получается идентичным).

А вот что в питоне происходит - хороший вопрос. Наверняка какие-то оптимизации.

Главное чтобы этот пул не фрагментировался потом (а то получим ровно ту же проблему, которую пытались решать).

Да, точно, согласен.

Можно и так, правда всё равно придётся вешать лок на newColors, а по сути это значит, что можно и глобальный лок на весь ThreadedScale навесить, разницы особо не будет.

while (yFloor + 1 >= h) yFloor--; - не помню, почему она такая, возможно в какой-то момент что-то из этого было float-ом и было нужно избежать ненужных приведений типов. Но замечание резонное, да.

А про ColorLerpUnclamped я бы послушал более детально, если можно.

Про аллокации самый классный вопрос, без шуток. Вообще, этот кусок кода был написан потому, что нужен был способ ресайзить прилетающие картинки, не делая крупных аллокаций на каждую новую картинку.
Почему так - я наткнулся на фрагментацию managed heap в Unity (ну по крайней мере такова гипотеза техсуппорта самой Unity, с которым я эту проблему обсуждал). Грубо говоря, если выделять большие куски памяти (под массив newColors) каждый раз при ресайзе новой текстуры, размер потребляемой Unity памяти на девайсе постоянно растёт (ибо она не может выделить новый кусок в старом хипе почему-то, хотя managed объекты там подохли уже).
Собственно потому да, аллокации мы тут экономим. Крупные конечно только.

Про замену useBilinear я бы поспорил - всё же вытаскивать наружу "потроха" в виде ParameterizedThreadStart наверное не очень хорошо.
Вот на какой-нить Enum его заменить наверное можно бы, да. Ну либо прямо делегат в параметр пробрасывать (но тогда надо формализовать, что там за Object у него будет в параметре, т.е. потребитель должен знать, какие методы можно передавать в аргумент, а какие нельзя - опасно, ИМХО.

w и w2 - согласен, в целом нейминг в этом куске у меня не самый лучший (ибо писалось "по-быстрому" без последующего приведения в порядок)

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

Это как бы не совсем о том, чтобы не судить вообще. А о том, что "каким судом судите, таким и вас будут судить".
Ну или "нефиг морализаторствовать, если у самого рыльце в пушку".

Это-то понятно. Тогда уж делать массив WaitHandles по числу дополнительных тредов и в основном дёргать WaitAll на них.

Есть конечно. Вроде бы и тот и тот. Да, семафоры тут конечно лучше подойдут, согласен. Говорю же - есть куда оптимизировать.

Впрочем, будет ли существенно быстрее семафор тут - не думаю, как раз Mutex всего (cores - 1) раз лочится и разлочится (по сути просто инкремент защищает).

А хотя сам себя запутал - лишнего треда там нет, но основной тред ждёт таким образом остальных, если он вдруг оказался быстрее всех. В целом функция нормальная, если не из main треда Unity запускать. Ну и кстати да, чтобы не делать лишний тред, там присутствует некоторая "лапшистость" (запускаются cores - 1 тредов циклом, а потом последний кусок работы запускается в текущем треде отдельно).

В этом месте я откровенно поленился и создаю лишний тред, да. По-хорошему, в основном потоке API сделать асинхронным и ждать в этом while корутиной, а не вот так "в лоб".

Гм, ничего конечно не мешает. И конкретно в данном случае - да, именно так и делается.

Впрочем, есть ситуации, когда "де-лапшизация" кода таки просаживает ему производительность.
Вот скажем пример https://gist.github.com/denis-ftc-denisov/7c293bd41822c557e84f9358882467e9

Как его сделать менее "лапшой", притом, чтобы не выделять дополнительно памяти (можно выделить константное число памяти, но не пропорционально размеру ввода или вывода) и не начать расходовать CPU (с CPU тут попроще). И это ещё "приличная" версия, можно эффективнее написать, но будет совсем лапша.

Это копейки. На 10 вызовах в секунду вы даже померить разницу не сможете.

Если их 10 в секунду - конечно нет смысла их экономить. А если миллион?

Если вам нужна информация из одного файла в двух разным местах, то читать его два раза не надо. Прочитайте один раз и используйте результат сколько угодно. Алгоритм в жертву понятности приносить не надо.

Само собой, но тогда потребуется какой-то менеджер этого файла завести (о чём я и говорю - чуть посложнее, чем "в лоб"). Да, отдельное веселье, когда файл нельзя весь целиком запихать в память (ну или можно, но крайне нежелательно) и нужен поточный парсер.

Тяжёлая. Но, если контент тяжелее издержек, то в параллель будет быстрее. Это к тому, что даже распиливание IO на части не всегда роняет производительность, а иногда может даже ускорять. Тут аксиомы не годятся, тут нужны измерения.

Тут согласен конечно. Мой пример - игровой конфиг (по сути - json-ка на десяток килобайт). Вот её тянуть одним запросом не в пример эффективнее, чем дёргать какое-то API при получении каждой настройки.

В моем мире среди "согласно тому, кто за что отвечает" как раз IO и будет таким компонентом разбиения. Чтение диска и работа с сетью, это низкоуровневый код и бизнес логика ничего об этом знать не должна. Это один из принципов того, как я разделяю на модули.

В общем-то да, тут согласен. Проблема в том, что если модули сравнительно развесистые и у каждого своё IO, иногда стоит это IO объединить под какой-то общей структурой.

Где упадёт скорость при разделении? Лишние вызовы?

Лишние вызовы. Создание новых объектов (чтобы не таскать из метода в метод по 10 параметров). Новые обращения к диску и сети (потому что теперь объекты независимо обращаются итп).

Общая сущность будет просто удобнее, если это файл, то его можно в несколько соединений скачать по частям. Хотя разбить на части и скачать отдельными запросами тоже можно.

Эм, вот и просадка - вместо одного запроса к серверу получаем N. Это уже не "спички" (вызовы), сетевой запрос - тяжёлая штука.

Что именно уронит производительность?

Если "в лоб" разделить код по модулям (согласно тому, кто за что отвечает), можно получить отдельные хождения в IO, которые уронят производительность.

Информация

В рейтинге
Не участвует
Зарегистрирован
Активность

Специализация

Разработчик мобильных приложений, Разработчик игр
Ведущий
C#
C++
Unity3d
PHP