У тебя есть потребность в общении, ты пытаешься его удовлетворить и идёшь для этого играть в настолки. При этом в собственно настолках не видишь смысла, но вынужден заниматься этой, с твоей точки зрения, хернёй ради общения. И в результате этот процесс вымораживает тебя больше, чем ты получаешь удовлетворения от общения.
Ещё два момента:
«Побыть в толпе» ― не факт, что тот тип общения, который тебе нужен. Меня лично «толпы» вымораживают непрерывными разговорами обо всём и в результате ни о чём. Кому-то нравится. Бывает, приколько послушать, но быстро надоедает, а участвовать вообще не тянет. Со временем понял, что легко переношу разговоры максимум втроём, в идеале один на один. Чем меньше людей, тем разговоры глубже и честнее. При этом, раз уж мы общаемся один на один, то наверняка мне этот человек интересен и симпатичен, и я ему тоже. Тем проще и тем больше удовлетворение. А добавляешь ещё людей ― хочется попрощаться и уйти.
Общение не ограничивается разговорами. Это любая совместная деятельность. Мне лично очень зашли социальные парные танцы. Из любопытства попробовал и втянулся. Занятия, тренировки, вечеринки. Если хочется поговорить ― людей много, выбор имеется, есть большая и разнообразная тема для разговоров, которая интересна всем. Если не хочется разговаривать, парный танец ― тоже общение партнёра с партнёршей, только невербальное. И как я люблю, один на один. Причём танцы хоть и парные, но социальные, т.е. постоянных пар нет, ты танцуешь и общаешься с кем хочешь и когда хочешь.
Настольные игры, это один из видов совместной деятельности, но ни мне, ни тебе он не заходит. Значит надо поискать такой вариант, который зайдёт.
Позвольте мне также побыть занудой и заметить, что локальные переменные не размещаются на стеке, там размещаются значения локальных переменных ;) Но всё-таки, «типы размещаются на стеке» — это удобное упрощение, как мне кажется.
Можно я тоже побуду занудой? Значения локальных переменных любых типов могут располагаться на стеке; могут располагаться в регистрах процессора; могут располагаться в куче, если на ними создаётся замыкание; могут вообще нигде не располагаться.
Его основная область применения десктопные приложения, в основном виндовые, но в последнее время сделан ряд шагов к кросплатофрменности.
Вот любопытно, сколько на одно выпущенное десктопное приложение сейчас приходится игр, сделанных на Unity. Не окажется ли так, что основная область применения C# сегодня ― это кроссплатформенный геймдев?
Топовые конфигурации PC могут сильно опережать приставки.
Ладно бы ПК и приставки отличались только скоростью. Они же отличаются органами управления и собственно играми. Играть хочется в что хочется, а не в что дают. На ПК выбор шире.
В Unity используется очень простой Boehm GC, в котором нет даже деления на поколения. Что больше всего помогает GC в управлении памятью в Unity ― это не генерировать тонны мусора в каждом кадре.
С версии Unity 2019 сборщику мусора добавили incremental-режим, чтобы не тормозить мир надолго, а размазывать одну относительно большую паузу по нескольким соседним кадрам.
Вроде бы спираль Эйлера (спираль Корню, клотоида) позволяет вычислять точки на себе в зависимости от пройденного расстояния вдоль кривой, а не на основе абстрактного t, как у Безье.
Когда-то пытался сделать сплайны на основе спиралей Эйлера как раз для простоты равномерного движения — пускать паровозики с вагончиками, но сходу что-то не пошло и сделал просто на дугах окружностей.
А я ничего такого представить не могу. Ну кроме умышленного замедления, где над, собственно, кодом обернут цикл на 10k операций.
Одна высокоуровневая "операция" без всяких циклов может разлагаться на непредсказуемое количество низкоуровневых. Никто не может сказать чётко, что такое "операция" в O() и чему она соответствует в реальности, и как результат, никто об этом и не говорит.
Можно читать и обрабатывать байты из файла по одному через какой-нибудь высокоуровневый поток, можно буферизировать ввод и двигать указатель по байтам в буфере, а можно читать и обрабатывать не байты, а пачки по 16/32 байта через SSE/AVX. Алгоритмически варианты не отличаются, а разница в скорости на многие порядки и определяется исключительно константами.
На практике, если у вас N>30, то O(N^2) почти всегда медленнее O(N log N), а даже самая быстрая реализация O(N^3) медленнее даже самой дерьмовой реализации O(N^2) алгоритма. Опять же, если умышленно искусственно код не замедлять.
Умышленно никто не замедляет, просто необходимость оптимизировать код, когда такая необходимость существует, регулярно упускается в пользу рассуждений об O(). Типа, N^2 лучше, чем N^3, значит соответствующая реализация должна работать быстрее и можно не напрягаться. А это O() описывает не реализации и не скорость, а исключительно поведение алгоритмов на максимально неудобных входных данных при росте их объёма.
Для двух конкретных реализаций можно построить два графика времени их работы в зависимости от объёма входных данных, сравнивать и делать выводы.
Графики O(n^2) и O(n^3) даже нарисовать невозможно, делать выводы и подавно. Единственный вывод, которых можно сделать, — существует такое неизвестно какое N, больше которого любая возможная реализация алгоритма O(N^2) будет работать быстрее любой возможной реализации O(N^3). Ну, не очень полезное практически знание. N-то у нас обычно задано заранее или мы уже представляем, в каких примерно пределах оно может гулять.
Просто альтернативный подход ― это преждевременная пессимизация, когда ты стреляешь себе в ногу прямо сейчас специально и прицельно; вместо того чтобы мимоходом написать пару простых строк, от которых когда-нибудь в будущем тебе может прилететь, а может и не прилететь ― но даже если и прилетит, их не жалко переписать под новые требования.
Вот есть «ленивые вычисления» (привет, LINQ!), а это такое «ленивое программирование». Принцип одинаковый ― незачем делать сейчас то, что сейчас никому не нужно, и хрен знает, потребуется ли в будущем.
Не бывает в программировании абсолютного «медленно» и абсолютного «быстро». Бывает «достаточно быстро» и «недостаточно быстро», а несколько размытая граница между ними определяется обстоятельствами. LINQ вероятно не стоит пихать внутрь цикла из 10k итераций на кадр / 60 кадров в секунду ― 16 миллисекунд не резиновые. Но если код запускается при нажатии юзером на GUI-кнопку, то вообще плевать, за сколько он отрабатывает, за 1/10 микросекунды или за 10. Лучше будет тот вариант, который проще и понятнее. Если LINQ вдруг проще, то и пусть будет он, отличная же вещь.
Очень сложно придумать хоть сколько нибудь реальный алгоритм… Вся константа зарыта в коде.
Вот. Константы в коде. Очень легко представить две реализации одного алгоритма, одна из которых для обработки каждого элемента входных данных совершает по времени в 100k больше бессмысленной работы, чем другая реализация.
O() ― это такая странная безразмерная штука про условные операции абстрактного исполнителя алгоритма в вакууме. Мы же пишем код для конкретного исполнителя, под данные определённого размера и характера; и время работы этого кода в секундах ― единственное, что нас реально волнует.
Знать про O() вообще полезно, но не написав код, только по двум разным O() делать какие-то выводы, это пальцем в небо и «преждевременная пессимизация».
Так и осталось непонятно почему для автора медленный код — более «эстетичный».
Логическая ошибка. Статья про то, что эстетичный код бывает «медленным», и что это не повод убивать эстетику, если скорость работы и так устраивает. Из этого утверждения не следует, что медленный код ― эстетичный.
«Художникам» от мира программирования стоит подумать о смене профессии на действительно творческую, ИМХО. Ради себя и других.
Как это возможно, программировать и одновременно не дружить с логикой?
Поскольку O() тупо не учитывает константы, то O(N), O(N/100k) и O(N*100k) друг другу тождественны. Ну и как тут можно серьёзно рассуждать о производительности?
Моё видение ситуации, как шизоида:
У тебя есть потребность в общении, ты пытаешься его удовлетворить и идёшь для этого играть в настолки. При этом в собственно настолках не видишь смысла, но вынужден заниматься этой, с твоей точки зрения, хернёй ради общения. И в результате этот процесс вымораживает тебя больше, чем ты получаешь удовлетворения от общения.
Ещё два момента:
«Побыть в толпе» ― не факт, что тот тип общения, который тебе нужен. Меня лично «толпы» вымораживают непрерывными разговорами обо всём и в результате ни о чём. Кому-то нравится. Бывает, приколько послушать, но быстро надоедает, а участвовать вообще не тянет. Со временем понял, что легко переношу разговоры максимум втроём, в идеале один на один. Чем меньше людей, тем разговоры глубже и честнее. При этом, раз уж мы общаемся один на один, то наверняка мне этот человек интересен и симпатичен, и я ему тоже. Тем проще и тем больше удовлетворение. А добавляешь ещё людей ― хочется попрощаться и уйти.
Общение не ограничивается разговорами. Это любая совместная деятельность. Мне лично очень зашли социальные парные танцы. Из любопытства попробовал и втянулся. Занятия, тренировки, вечеринки. Если хочется поговорить ― людей много, выбор имеется, есть большая и разнообразная тема для разговоров, которая интересна всем. Если не хочется разговаривать, парный танец ― тоже общение партнёра с партнёршей, только невербальное. И как я люблю, один на один. Причём танцы хоть и парные, но социальные, т.е. постоянных пар нет, ты танцуешь и общаешься с кем хочешь и когда хочешь.
Настольные игры, это один из видов совместной деятельности, но ни мне, ни тебе он не заходит. Значит надо поискать такой вариант, который зайдёт.
Можно я тоже побуду занудой? Значения локальных переменных любых типов могут располагаться на стеке; могут располагаться в регистрах процессора; могут располагаться в куче, если на ними создаётся замыкание; могут вообще нигде не располагаться.
Вот любопытно, сколько на одно выпущенное десктопное приложение сейчас приходится игр, сделанных на Unity. Не окажется ли так, что основная область применения C# сегодня ― это кроссплатформенный геймдев?
«Назло бабушке перестану какать» :)
Ладно бы ПК и приставки отличались только скоростью. Они же отличаются органами управления и собственно играми. Играть хочется в что хочется, а не в что дают. На ПК выбор шире.
Они были в IL/CLR, но C# и BCL ничего про них не знали.
Они на виду и им есть что терять.
Сомневаюсь, но можешь проверить.
Дураками людей считать не надо. Все всё прекрасно понимают.
[del]
В Unity используется очень простой Boehm GC, в котором нет даже деления на поколения. Что больше всего помогает GC в управлении памятью в Unity ― это не генерировать тонны мусора в каждом кадре.
С версии Unity 2019 сборщику мусора добавили incremental-режим, чтобы не тормозить мир надолго, а размазывать одну относительно большую паузу по нескольким соседним кадрам.
https://blogs.unity3d.com/2018/11/26/feature-preview-incremental-garbage-collection/
Вроде бы спираль Эйлера (спираль Корню, клотоида) позволяет вычислять точки на себе в зависимости от пройденного расстояния вдоль кривой, а не на основе абстрактного t, как у Безье.
Когда-то пытался сделать сплайны на основе спиралей Эйлера как раз для простоты равномерного движения — пускать паровозики с вагончиками, но сходу что-то не пошло и сделал просто на дугах окружностей.
Одна высокоуровневая "операция" без всяких циклов может разлагаться на непредсказуемое количество низкоуровневых. Никто не может сказать чётко, что такое "операция" в O() и чему она соответствует в реальности, и как результат, никто об этом и не говорит.
Можно читать и обрабатывать байты из файла по одному через какой-нибудь высокоуровневый поток, можно буферизировать ввод и двигать указатель по байтам в буфере, а можно читать и обрабатывать не байты, а пачки по 16/32 байта через SSE/AVX. Алгоритмически варианты не отличаются, а разница в скорости на многие порядки и определяется исключительно константами.
Умышленно никто не замедляет, просто необходимость оптимизировать код, когда такая необходимость существует, регулярно упускается в пользу рассуждений об O(). Типа, N^2 лучше, чем N^3, значит соответствующая реализация должна работать быстрее и можно не напрягаться. А это O() описывает не реализации и не скорость, а исключительно поведение алгоритмов на максимально неудобных входных данных при росте их объёма.
Для двух конкретных реализаций можно построить два графика времени их работы в зависимости от объёма входных данных, сравнивать и делать выводы.
Графики O(n^2) и O(n^3) даже нарисовать невозможно, делать выводы и подавно. Единственный вывод, которых можно сделать, — существует такое неизвестно какое N, больше которого любая возможная реализация алгоритма O(N^2) будет работать быстрее любой возможной реализации O(N^3). Ну, не очень полезное практически знание. N-то у нас обычно задано заранее или мы уже представляем, в каких примерно пределах оно может гулять.
И есть геймдев, где само словосочетание "считанные миллисекунды" режет ухо, потому что их на всё про всё в кадре всего 16.
Просто альтернативный подход ― это преждевременная пессимизация, когда ты стреляешь себе в ногу прямо сейчас специально и прицельно; вместо того чтобы мимоходом написать пару простых строк, от которых когда-нибудь в будущем тебе может прилететь, а может и не прилететь ― но даже если и прилетит, их не жалко переписать под новые требования.
Вот есть «ленивые вычисления» (привет, LINQ!), а это такое «ленивое программирование». Принцип одинаковый ― незачем делать сейчас то, что сейчас никому не нужно, и хрен знает, потребуется ли в будущем.
Не бывает в программировании абсолютного «медленно» и абсолютного «быстро». Бывает «достаточно быстро» и «недостаточно быстро», а несколько размытая граница между ними определяется обстоятельствами. LINQ вероятно не стоит пихать внутрь цикла из 10k итераций на кадр / 60 кадров в секунду ― 16 миллисекунд не резиновые. Но если код запускается при нажатии юзером на GUI-кнопку, то вообще плевать, за сколько он отрабатывает, за 1/10 микросекунды или за 10. Лучше будет тот вариант, который проще и понятнее. Если LINQ вдруг проще, то и пусть будет он, отличная же вещь.
Вот. Константы в коде. Очень легко представить две реализации одного алгоритма, одна из которых для обработки каждого элемента входных данных совершает по времени в 100k больше бессмысленной работы, чем другая реализация.
O() ― это такая странная безразмерная штука про условные операции абстрактного исполнителя алгоритма в вакууме. Мы же пишем код для конкретного исполнителя, под данные определённого размера и характера; и время работы этого кода в секундах ― единственное, что нас реально волнует.
Знать про O() вообще полезно, но не написав код, только по двум разным O() делать какие-то выводы, это пальцем в небо и «преждевременная пессимизация».
Ну так всё ровно в соответствии с поговоркой.
Логическая ошибка. Статья про то, что эстетичный код бывает «медленным», и что это не повод убивать эстетику, если скорость работы и так устраивает. Из этого утверждения не следует, что медленный код ― эстетичный.
Как это возможно, программировать и одновременно не дружить с логикой?
Поскольку O() тупо не учитывает константы, то O(N), O(N/100k) и O(N*100k) друг другу тождественны. Ну и как тут можно серьёзно рассуждать о производительности?