Pull to refresh
94
0
Григорий Борисович @naething

Пользователь

Send message

У вас, кажется, в обработчике TIMER1_COMPA_vect в случае frame_counter=20 ничего не происходит. Но я, собственно, не за этим.

Для реализации подобных конечных автоматов можно из любопытства попытаться применить идею из https://www.chiark.greenend.org.uk/~sgtatham/coroutines.html . С помощью нее можно писать код в императивном стиле, вместо явной обработки состояний:

#define BEGIN_COROUTINE static int32_t state = -1; switch(state) { case -1:
#define YIELD do { state = __LINE__; return; case __LINE__: ; } while(0);
#define END_COROUTINE }

ISR(TIMER1_COMPA_vect) {
    static uint8_t cur_pos_num;
    static int8_t i;

    BEGIN_COROUTINE
        for (;;) {
            for (cur_pos_num = 0; cur_pos_num < 6; ++cur_pos_num) {
                for (i = 9; i >= 0; --i) {
                    set_posi_sig();
                    YIELD;

                    if (i == numbers[cur_pos_num]) {
                        set_nego_sig();
                    } else {
                        set_zero_sig();
                    }
                    YIELD;
                }

                for (i = 0; i < 20; ++i) {
                    set_zero_sig();
                    YIELD;
                }
            }
        }
    END_COROUTINE
}

Если под номер состояния выделять большой int расточительно, то можно каждый раз явно передавать в YIELD какое-то уникальное число:

#define YIELD(s) do { state = s; return; case s: ; } while(0);

Практическая целесообразность под большим вопросом, но по-моему довольно интересный трюк.

Вряд ли Fuchsia будет очень бысрой. Там все слишком изолированно и асинхронно. Например, драйвер сетевой карты работает с одном процессе (не в ядре), а релиазация протокола TCP/IP — в другом (тоже не в ядре). Файловая система в третьем, и так далее. Ядро, по сути, лишь предоставляет примитивы межпроцессной коммуникации. Упор на бесопасность и изоляцию, за что скорее всего придется заплатить производительностью.
Но вы серьезно думаете, что разработчик с десятилетним стажем, работавший хотя бы по 1.5 года на каждом месте, успешно в течение десяти лет обманывал всех, что он не умеет писать код?
Не обязательно обманывал. Мог заниматься какой-то ерундой все эти 10 лет. Если у кого-то опыт в 10 лет, это не значит, что у него высокий уровень. Может он достиг какого-то приемлемого для своей прошлой работы уровня, но это не значит, что этот уровень устроит мою команду. Причем крутость работодателя тоже ни о чем не говорит. Даже в хваленой корпорации добра таких личностей более чем хватает. И даже на уровнях выше сеньора я таких людей там видел.

Для чего нужны все эти алгоритмы обхода деревьев на собеседовании? Он что, каждый день будет писать эти деревья или алгоритмы сортировки в прод?
Цель алгоритмического собеседования — вовсе не проверить, насколько вы хорошо знаете алгоритмы обхода деревьев. Алгоритм выступает лишь в роли контекста. Цель собеседования — получить представление об общем уровне вашей «соображалки», оценить коммуникативные навыки, стиль мышления, и заодно проверить навыки перевода идей из головы в код.

Но конечно сложно поспорить, что часто они действительно вырождаются в проверку, умеете ли вы писать обходы деревьев. Тут уж зависит все от собеседователя. Поэтому я понимаю общее недовольство алгоритмическими собеседованиями, но я в корне не согласен с критикой типа «я ж не буду писать сортировку каждый день, зачем вы меня ее спрашиваете». Я поддерживаю критику вроде «зачем вы меня заставляете решать задачки чтобы тупо посмотреть, решил я ее или нет, и докапываетесь до неважных деталей, вместо того, чтобы оценивать мои общие мыслительные способности в процессе собеседования».
Я плачу 25% налогов. Что я делаю не так?

Либо вы получаете меньше 100 тысяч в год, либо я хочу знать ваши секретные методы ухода от налогов :)
В статье слишком много ложной информации про жизнь в Калифорнии, поэтому не могу пройти мимо.

В Сан-Франциско — 9 404 долларов США в месяц
Сложно в это поверить, по личному опыту зарплаты сильно выше, чем 112 тысяч в год. Особенно в крупных компаниях. Если это данные с glassdoor, то скорее всего они не включают акции (RSU), и вообще они сильно там занижены. В зависимости от компании, опыта специалиста и умения себя продать, годовой доход software engineer колеблется с среднем в интервале от 120 до 400 тысяч в год. Медиана, я думаю, где-то в районе 150-200 тысяч. Чтобы увидеть, сколько получают в крупных компаниях, рекомендую использовать levels.fyi вместо glassdoor.

(вычитаем из зарплаты 28% федерального и 28% подоходного налога штата).
Это ложная информация. Налог в штата в Калифорнии в среднем около 9% (он прогрессивный). Федеральный налог тоже прогрессивный. Просто наберите в Гугле «california income tax calculator» и введите годовой доход в долларах.

Например, если ввести 112858 долларов в год (=9404 в месяц, как в статье), то все налоги в сумме получатся около 30,5%. Итого чистыми в месяц у вас будет около 6500 долларов в месяц, что по курсу 63 рубля за доллар составляет 409500 рублей в месяц.

Этот расчет подтвержается личным опытом. Когда я пять лет назад работал джуниором в стартапе, то моя зарплата как раз была в точности 112 тысяч в год. Чистыми примерно столько и получалось в месяц.

делим зарплату на 2,7 — во столько раз стоимость жизни тут выше, чем в Москве
Бесспорно, цены на жилье и услуги в окрестностях СФ действительно очень высокие. Однако, цены на товары (автомобили, электроника, ...) могут быть и ниже московских. Поэтому простым делением на коэффициент сложно что-то посчитать.

StampedLock будет эффективнее ReentrantReadWriteLock за счёт того, что в случае успеха оптимистичной блокировки (fast path) вообще не происходит обновления разделяемых переменных, в то время как ReentrantReadWriteLock даже в лучшем случае выполняет как минимум один CAS.

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

     long stamp = sl.tryOptimisticRead();
     int ret = buf.get(offset);
     if (!sl.validate(stamp)) {
         // lock and re-read (slow path)
     }
     return ret;

Если писатель пришел после того, как мы вызвали tryOptimisticRead(), но до того, как мы вызвали validate(), то buf.get() и buf.put() могут быть вызваны одновременно, что может быть проблемой, в зависимости от внутренней реализации класса ByteBuffer. Если бы вместо buf.get() и buf.put() были бы явное чтение/запись из массива, не было бы проблем.

Поэтому лучше не выпендриваться использованием низкоуровневых примитивов синхронизации и использовать обычный мьютекс.
Можно добавить в список: лексический анализатор Питона выдает два специальных токена INDENT и DEDENT, которые обозначают увеличение и уменьшение уровня отступа, соответсвенно. Было бы логично их тоже считать за токены.
Альбом «Flying Microtonal Banana» от King Gizzard and the Lizard Wizard.

www.youtube.com/watch?v=Q-i1XZc8ZwA
Согласен, что эта особенность плохо документирована, но все-таки ставить на это можно. При наличии сомнений можно использовать такую обертку:
template<typename T>
T* unaligned_cast(void* p) {
    static_assert(__alignof__(T) == 1);
    return reinterpret_cast<T*>(p);
}

Когда я работал над реализацией протокола WiFi, мы тоже пришли к похожему решению:

fuchsia.googlesource.com/fuchsia/+/refs/heads/master/src/connectivity/wlan/lib/common/rust/src/big_endian.rs

В основном протоколе все поля в little endian, но иногда попадаются big endian из верхних слоев.
тогда требования к выравниванию структуры в целом (а они обычно у компилятора есть даже для упакованных структур)

Я всегда считал, что у упакованных структур нет требований к выравниванию. В этом, в общем-то, и весь их смысл. Если есть сомнения/паранойя, можно вставить в код
static_assert(__alignof__(MyStruct) == 1);
перед тем, как делать reinterpret_cast.

Но формально нарушение выравнивания является undefined behavior, и существуют архитектуры, где это фатально.
Здесь нет никакого нарушения выравнивания. У упакованных структур выравнивание всегда равно единице, поэтому нарушить его невозможно. В этом весь смысл упакованных структур.

Работает это не только на x86 и ARM. Если платформа не поддерживает невыровненные обращения к памяти, то для чтения/записи поля из упакованной стрктуры компилятор вставит соответствующие инструкции.

Вот весь пост — прямо классическая иллюстрация причины, скрывающейся за правилом: никогда не парсить бинарные данные с помощью приведения к типу указателя на __attribute__((packed)) структурки.
Приведенное вами «правило» необоснованно по изложенной выше причине. Упакованные структуры — весьма практичный способ разбора бинарных данных.
Ха, я вот проработал в гугле ровно 1 год. В общем, негативный экспириенс. Но:

проходят анальное интервью с идиотскими вопросами и «алгоритмами».
А мне кстати собеседование понравилось, но я люблю алгоритмы. Люди были крайне вежливы.

работают над какой-то самописной херней от гугла(т.е. опыт не трансферится на какие-то другие компании)
Самописная херня была очень прикольная кстати (OS Fuchsia). Опыт пускай и не переносится напрямую, но все равно я многому интересному успел научиться.

получают офер на 50-60% выше, чем получают в гугле
В моем случае разница получилась всего лишь в 30%, но да, 50-60% вполне может быть, если гугловский офер был изначально низкий.

сваливают от этой помойки
Пока мое наименее любимое место работы в Долине, но помойкой все-таки не стал бы называть.
YCM это clang зависимый (с точки зрения C/C++) плагин

Да, я знаю. В моем проекте кто-то уже проделал основную работу по интеграции YCM и я пытался использовать этот готовый конфиг. Но что-то он не справлялся.

Нет, вот с «все кнопки как в Vim» это очень не так. Далеко не все, и не сказать чтобы «как в Vim». Скорее: «некоторые кнопки примерно как Vim».


Согласен, что не «прям все». Но я каких-то супер-продвинутых функций vim не использую, поэтому особой разницы не замечаю. Просто привык работать с командами перемещения/редактирования/поиска и модальному интерфейсу, которые работают без проблем. Если ваши запросы сильно выше, то наверное у вас будет другой опыт.
Честно говоря не помню, но скорее всего не пробовал. Спасибо за наводку, посмотрю при случае.
В Калифорнийской мотошколе нас учили, что совсем параллельно небезопасно ехать — лучше, чтобы оставалось пространство сбоку для маневра (для объезда препятствия, например). Рекомендуют «diamond formation» при групповой езде. Один, например, едет спереди и левее, а другой сзади и правее, но дистанцию между мотоциклами при этом можно держать меньше, чем просто при езде за машиной.
Калифорнийский мотоциклист с двухмесячным стажем на связи. Спасибо за статью, ваше красочное описание асфальтовой болезни мотивировало меня наконец купить мотоштаны.

Мои пять копеек: если стоите первым на светофоре и загорелся зеленый, посмотрите по сторонам, прежде чем ехать.
Либо я пропустил, либо тема навигации в большом проекте не раскрыта. Сколько ни пробовал разных плагинов для переключения между файлами, везде есть какие-то проблемы или тормоза. Теги тоже не очень хорошо работают. На прошлой работе пытался настроить YouCompleteMe, но он либо зависал, либо не находил нужное (огромный проект на C++).

В студенческие годы у меня тоже был вим с кучей плагинов и настроенных конфигов, и он вполне справлялся со студенческими проектами. Но сейчас я обычно использую IntelliJ/PyCharm/CLion с Vim-плагином. Все кнопки как в Vim, только еще есть полноценный IDE и никаких плясок с бубнами. Выбрал шрифт, цвета по вкусу, сочетания клавиш и поехали.

CLion, правда, на прошлой работе я в итоге выкинул. Он жутко тормозил даже на моей 54-ядерной рабочей станции со 128 ГБ памяти. В итоге я установил IntelliJ Community Edition и использовал его как текстовый редактор без функций IDE. Все равно удобдней, чем Vim с плагинами.
Все-таки это не совсем свертка в традиционном понимании этого слова. Свертка — это линейная операция: значение клекти вычисляется как взвешенная сумма ее окрестности. Иными словами, влияние каждого соседа суммируется независимо от других соседей.

А здесь в качестве «ядра» выступает произвольная булева функция от 9 переменных. Линейных булевых функций от девяти переменных существуется всего лишь 2^10, в то время как количество всех функций от 9 переменных — 2^512.
Не очень понятное решение. Это довольно редкий случай, когда нужны _сразу_ несколько переменных одного типа. Да и даже в том случае, может быть более читаемо объяивить каждую переменную на своей строке. Да и если захочется сделать указание типа опциональным, то будет странно.

Information

Rating
Does not participate
Location
Palo Alto, California, США
Date of birth
Registered
Activity