Извиняюсь за тупой вопрос, но вот в декомпилированном коде непосредственно перед вызовом SetEnvironmentVariableA есть цикл, в котором в строке ищется "=", чтобы разбить строку на имя переменной окружения и значение. А если этого "=" не будет, то он так и будет сканировать память, пока не повезёт?
Если я вас правильно понял, то у вас поток бизнес-логики пытается писать в неблокирующий сокет, а если не смог, то bytebuffer отдаётся другому потоку, который это сделает. Можно было бы сразу отдавать bytebuffer в поток-писатель, это очень слабо сказалось бы на latency. Я бы ещё понял, если бы вам очень хотелось иметь синхронные вызовы записи, чтобы обрабатывать сетевые ошибки в том же потоке, который приготовил байты для отправки, но раз уж у вас есть и асинхронная запись, то ваше приложение должно уже быть готово к асинхронности.
Когда прочитал примерно треть статьи, почувствовал, что меня грузят хреновой тучей информации, заправленной бурлящими эмоциями (обида, "справедливое" возмущение, ...). Остальное прокрутил мышкой. Мне такое читать не хочется, новой информации я не верю, что почерпну. Независимо от того, что написано в статье, я не верю, что "Эльбрус" станет самоокупаемым коммерчески успешным продуктом, тупо потому что стоит дохрена при так себе производительности. Сомневаюсь, что в статье приведены обратные факты.
Зашёл почитать про лексеры и парсеры, и, хоть я и не Scala-разработчик, имею много замечаний по прочитанному коду.
Первое - в BinaryOperation/UnaryFunction не надо делать equals(), который принимает String. Гораздо лучше будет для хранения операций использовать не List, а Map (она же есть в Scala, я верю в это), тем более что вы потом по содержимому List-а делаете операции map()/filter().
Во-вторых, и бинарные операции, и унарные, и константы имеют очень много общего: они имеют обозначение (ваше getDesignation), и могут быть вычислены (ваше calc()/getValue), поэтому вместо того, чтобы объявлять эти методы в трейтах по-отдельности, вполне подошёл бы родительский трейт (я верю, что такое есть в Scala). При этом сильно убавится кода, который делает одно и то же для разных трейтов (например, токенизация).
В-третьих, нафига BinaryOperactionFabric? Вместо того, чтобы императивно клеить символ к функции и кешировать, проще в коде декларативно наобъявлять статических экземпляров трейта, а "фабрика" по-английски будет "Factory".
Тут я, наконец, добрался до токенизации. Ну, это где символы обрамляются сепараторами через string.replace(), и потом всё нарезается через string.split(). Мощно. Я долго искал себе оправдание, почему я не додумался до такого? Потом придумал искусственный случай, когда это сломается (если обозначение операции является подстрокой обозначения другой операции), и успокоился.
А где же парсер? А его тут нет. Тут сразу считалка, которая выполняет операции в том порядке, в котором они объявлены. Прикольно, если бы токенизатор понимал пробел как разделитель, то считалка понимала бы сразу и префиксную нотацию, и инфиксную, и постфиксную! (И любую кашу из них).
Когда я дошёл до того места, где обработка скобок происходит способом "когда нашли открывающую скобку, то сканируем строку дальше, считая открывающие и закрывающие скобки, чтобы найти нужную закрывающую скобку, и скармливаем внутрискобочное выражение в вычислитель", я понял, что парсера тут не будет, а логика разбора и вычисления перемешана.
Я вообще не хотел насмехаться ни над кодом, ни над автором (хотя скорее всего звучит именно так), я хотел мозг свой размять.
Хрень полная. Его делали не Westwood, и графика в нём сильно хуже, чем в первом, не говоря уже про прекрасно нарисованный второй. Насколько я знаю, в третьем используется отдельно разработанный движок, который потом отдали в DreamForge. Те на основе движка и графики сварганила Dungeon Hack, но потом взялась за хорошие собственные игры типа Ravenloft, с собственной стильной графикой.
Рисовать спрайты на клетчатой бумаге - это мы делали, прямо в школьных тетрадках. А вот рисовать спрайты на миллиметровке - это интересно, до такого мы не додумывались. Может, потому что миллиметровка была дороже.
Это в полной мере относится к Renegade 3, заставка красивая, игра - и некрасивая, и играется плохо. И первый уровень "prehistoric" ещё самый визуально чистый, следующие уровни, средневековый и футуристичный - это просто каша из пикселей
Я сходил в github-репозиторий автора. Я нифига не UI-разработчик, но что за бардак? Какие-то lock-файлы, какие-то конфиги среды разработки, gradle wrapper целым jar-ником лежит. Я догадываюсь, что автор тупо закоммитил всё, что у него было, но так не надо
Для этой игры тоже можно сделать подобное. Поскольку пишутся байты не последовательно, а читаются - последовательно, то стек можно использовать для чтения. Пока я вижу, что для отрисовки монстров используется много копипастного кода, для каждого монстра свои процедуры. Есть надежда это оптимизировать и выиграть место для отрисовки всего экрана, оставаясь в 48 кб
Эмуляция - она на то и эмуляция, что игра не знает, что еë эмулируют на повышенной скорости. Но то, что вы хотите, возможно, хотя для этого игру надо не ускорить, а замедлить. Механика игры работает так: между каждым кадром координаты кораблей изменяются в соответствии с их скоростями. Если разделить эти приращения координат на 2, то при вдвое увеличенной скорости эмуляции вы получите ту же динамику боя. Но придётся иметь несколько версий игры, под разные множители
Прикольно. Байт-код, похоже, фиксированного размера, чтобы проще было для переходов находить инструкцию по индексу. Виртуальная машина регистровая, и приходится указывать регистр-получатель результата. Я так понял, что идентификатор курсора - это r[0], используется, когда нужно значения колонки прочитать. Столбцы идентифицируются индексами, значит компилятор зачитывает схему таблицы для кодогенерации. Оптимизация так себе: столбец "favorite_color" зачитывается из курсора дважды, второй раз только для того, чтобы ResultsRow мог сформировать результат из последовательного набора регистров. Интересно, почему не скопировать регистр-регистр в этом случае.
Я не знаю питон совсем, и верю автору, что R лучше для обработки таблиц. Но в восхвалении R автора периодически заносит.
Что представляет собой data.frame в классическом Computer Science? Это список указателей на массивы. Массивы — это колонки. Так было на ассемблере, так было на С/С++, Паскале и т.д
какой "классический Computer Science" имеет тут в виду автор - я не знаю, думаю, просто выпендривается. С и Паскаль содержат такие типы данных как структуры/записи, и таблицы реализуются массивом структур. Это одинаково компактно по памяти по сравнению с колоночным хранением.
Механизм NSE (Non-Standard Evaluation) вкупе с пайпами позволяет упомянуть имя датафрейма только в первой строчке и больше его не использовать
NSE - жуткая штука, работает магически, отлаживать её страшно. Но я соглашусь с тем, что компактный язык запросов в функциональном языке можно сделать только макросами или специальным парсером.
Книга действительно рассчитана непонятно на кого, она плоха для всех. В ней нет ничего нового, значит не на электронщиков. Она плохо подходит для обучения, значит не на новичков. Для инженеров она слишком формалистична и непрактична. Если на математиков - нафига городить схемы вообще, достаточно сказать, что есть функции and, or, not, и всё, дальше достаточно любого математического формализма. Вы оправдываетесь, что вы математик, я верю плохо, как раз математикам свойственно делать всё максимально компактно и использовать иероглифы для выразительности.
Я правильно понял вашу логику: "Внешний порт платы обозначим вот так, потому что это внутренний порт для внешнего устройства"? Вы штаны случайно не наизнанку носите?
У вас какая-то непонятная принципиальность: или только внешняя форма, или только подписи. В стандартной системе отображения, на которую вам уже указывали, применяется внешняя форма для базовых блоков и прямоугольники для сложных блоков. Базовые блоки должны отображаться максимально просто и наглядно, чтобы восприниматься спинным мозгом. В математике, к примеру, для простейших операций применяются наглядные символы, а для синусов и логарифмов - имена
Аналогично предыдущему, я не утверждал, что для всех случаев нужно убрать подписи, а для тех, где назначение порта очевидно. Это так, например, для всех стандартных блоков. У вас же входные и выходные порты различаются цветом, так зачем на базовом блоке "not" ещё что-то подписывать?
Открыл предыдущую статью, охренел от её размера, на глаз не нашёл, где там это написано. Если логика "по проводкам сигнал идёт от чёрного к белому", то меня бы устроил такой ответ
я думаю, что имелось ввиду наоборот: удалённый отлаживаемый начинает контролировать процесс-отладчик
Извиняюсь за тупой вопрос, но вот в декомпилированном коде непосредственно перед вызовом SetEnvironmentVariableA есть цикл, в котором в строке ищется "=", чтобы разбить строку на имя переменной окружения и значение. А если этого "=" не будет, то он так и будет сканировать память, пока не повезёт?
Если я вас правильно понял, то у вас поток бизнес-логики пытается писать в неблокирующий сокет, а если не смог, то bytebuffer отдаётся другому потоку, который это сделает. Можно было бы сразу отдавать bytebuffer в поток-писатель, это очень слабо сказалось бы на latency. Я бы ещё понял, если бы вам очень хотелось иметь синхронные вызовы записи, чтобы обрабатывать сетевые ошибки в том же потоке, который приготовил байты для отправки, но раз уж у вас есть и асинхронная запись, то ваше приложение должно уже быть готово к асинхронности.
Наоборот, дифракция - частный случай интерференции
Когда прочитал примерно треть статьи, почувствовал, что меня грузят хреновой тучей информации, заправленной бурлящими эмоциями (обида, "справедливое" возмущение, ...). Остальное прокрутил мышкой. Мне такое читать не хочется, новой информации я не верю, что почерпну. Независимо от того, что написано в статье, я не верю, что "Эльбрус" станет самоокупаемым коммерчески успешным продуктом, тупо потому что стоит дохрена при так себе производительности. Сомневаюсь, что в статье приведены обратные факты.
Зашёл почитать про лексеры и парсеры, и, хоть я и не Scala-разработчик, имею много замечаний по прочитанному коду.
Первое - в BinaryOperation/UnaryFunction не надо делать equals(), который принимает String. Гораздо лучше будет для хранения операций использовать не List, а Map (она же есть в Scala, я верю в это), тем более что вы потом по содержимому List-а делаете операции map()/filter().
Во-вторых, и бинарные операции, и унарные, и константы имеют очень много общего: они имеют обозначение (ваше getDesignation), и могут быть вычислены (ваше calc()/getValue), поэтому вместо того, чтобы объявлять эти методы в трейтах по-отдельности, вполне подошёл бы родительский трейт (я верю, что такое есть в Scala). При этом сильно убавится кода, который делает одно и то же для разных трейтов (например, токенизация).
В-третьих, нафига BinaryOperactionFabric? Вместо того, чтобы императивно клеить символ к функции и кешировать, проще в коде декларативно наобъявлять статических экземпляров трейта, а "фабрика" по-английски будет "Factory".
Тут я, наконец, добрался до токенизации. Ну, это где символы обрамляются сепараторами через string.replace(), и потом всё нарезается через string.split(). Мощно. Я долго искал себе оправдание, почему я не додумался до такого? Потом придумал искусственный случай, когда это сломается (если обозначение операции является подстрокой обозначения другой операции), и успокоился.
А где же парсер? А его тут нет. Тут сразу считалка, которая выполняет операции в том порядке, в котором они объявлены. Прикольно, если бы токенизатор понимал пробел как разделитель, то считалка понимала бы сразу и префиксную нотацию, и инфиксную, и постфиксную! (И любую кашу из них).
Когда я дошёл до того места, где обработка скобок происходит способом "когда нашли открывающую скобку, то сканируем строку дальше, считая открывающие и закрывающие скобки, чтобы найти нужную закрывающую скобку, и скармливаем внутрискобочное выражение в вычислитель", я понял, что парсера тут не будет, а логика разбора и вычисления перемешана.
Я вообще не хотел насмехаться ни над кодом, ни над автором (хотя скорее всего звучит именно так), я хотел мозг свой размять.
Жду от автора статью "Почему Java должна быть единственным языком программирования в образовательном процессе".
Чёрт, целая статья, и ни слова про LD_LIBRARY_PATH.
Хрень полная. Его делали не Westwood, и графика в нём сильно хуже, чем в первом, не говоря уже про прекрасно нарисованный второй. Насколько я знаю, в третьем используется отдельно разработанный движок, который потом отдали в DreamForge. Те на основе движка и графики сварганила Dungeon Hack, но потом взялась за хорошие собственные игры типа Ravenloft, с собственной стильной графикой.
Рисовать спрайты на клетчатой бумаге - это мы делали, прямо в школьных тетрадках. А вот рисовать спрайты на миллиметровке - это интересно, до такого мы не додумывались. Может, потому что миллиметровка была дороже.
Это в полной мере относится к Renegade 3, заставка красивая, игра - и некрасивая, и играется плохо. И первый уровень "prehistoric" ещё самый визуально чистый, следующие уровни, средневековый и футуристичный - это просто каша из пикселей
Я сходил в github-репозиторий автора. Я нифига не UI-разработчик, но что за бардак? Какие-то lock-файлы, какие-то конфиги среды разработки, gradle wrapper целым jar-ником лежит. Я догадываюсь, что автор тупо закоммитил всё, что у него было, но так не надо
Для этой игры тоже можно сделать подобное. Поскольку пишутся байты не последовательно, а читаются - последовательно, то стек можно использовать для чтения. Пока я вижу, что для отрисовки монстров используется много копипастного кода, для каждого монстра свои процедуры. Есть надежда это оптимизировать и выиграть место для отрисовки всего экрана, оставаясь в 48 кб
Эмуляция - она на то и эмуляция, что игра не знает, что еë эмулируют на повышенной скорости. Но то, что вы хотите, возможно, хотя для этого игру надо не ускорить, а замедлить. Механика игры работает так: между каждым кадром координаты кораблей изменяются в соответствии с их скоростями. Если разделить эти приращения координат на 2, то при вдвое увеличенной скорости эмуляции вы получите ту же динамику боя. Но придётся иметь несколько версий игры, под разные множители
Прикольно. Байт-код, похоже, фиксированного размера, чтобы проще было для переходов находить инструкцию по индексу. Виртуальная машина регистровая, и приходится указывать регистр-получатель результата. Я так понял, что идентификатор курсора - это r[0], используется, когда нужно значения колонки прочитать. Столбцы идентифицируются индексами, значит компилятор зачитывает схему таблицы для кодогенерации. Оптимизация так себе: столбец "favorite_color" зачитывается из курсора дважды, второй раз только для того, чтобы ResultsRow мог сформировать результат из последовательного набора регистров. Интересно, почему не скопировать регистр-регистр в этом случае.
Н.Носов "Фантазёры"
Я не знаю питон совсем, и верю автору, что R лучше для обработки таблиц. Но в восхвалении R автора периодически заносит.
какой "классический Computer Science" имеет тут в виду автор - я не знаю, думаю, просто выпендривается. С и Паскаль содержат такие типы данных как структуры/записи, и таблицы реализуются массивом структур. Это одинаково компактно по памяти по сравнению с колоночным хранением.
NSE - жуткая штука, работает магически, отлаживать её страшно. Но я соглашусь с тем, что компактный язык запросов в функциональном языке можно сделать только макросами или специальным парсером.
Заголовок и вступление ставят под сомнение полезность указателей. Но вся статья рассматривает только применение указателей как параметров.
Книга действительно рассчитана непонятно на кого, она плоха для всех. В ней нет ничего нового, значит не на электронщиков. Она плохо подходит для обучения, значит не на новичков. Для инженеров она слишком формалистична и непрактична. Если на математиков - нафига городить схемы вообще, достаточно сказать, что есть функции and, or, not, и всё, дальше достаточно любого математического формализма. Вы оправдываетесь, что вы математик, я верю плохо, как раз математикам свойственно делать всё максимально компактно и использовать иероглифы для выразительности.
Я правильно понял вашу логику: "Внешний порт платы обозначим вот так, потому что это внутренний порт для внешнего устройства"? Вы штаны случайно не наизнанку носите?
У вас какая-то непонятная принципиальность: или только внешняя форма, или только подписи. В стандартной системе отображения, на которую вам уже указывали, применяется внешняя форма для базовых блоков и прямоугольники для сложных блоков. Базовые блоки должны отображаться максимально просто и наглядно, чтобы восприниматься спинным мозгом. В математике, к примеру, для простейших операций применяются наглядные символы, а для синусов и логарифмов - имена
Аналогично предыдущему, я не утверждал, что для всех случаев нужно убрать подписи, а для тех, где назначение порта очевидно. Это так, например, для всех стандартных блоков. У вас же входные и выходные порты различаются цветом, так зачем на базовом блоке "not" ещё что-то подписывать?
Открыл предыдущую статью, охренел от её размера, на глаз не нашёл, где там это написано. Если логика "по проводкам сигнал идёт от чёрного к белому", то меня бы устроил такой ответ