Если с нуля писать, то не настроить, но писать с нуля совершенно необязательно. Берём mbedOS, например, и там всё чудесно инициализируется по умолчанию, а sleep_for() принимает аж литералы времени типа 5s
Или например моя самоделка вообще на Rust в качестве часов использует LPTIMER, и частота ядра ей для работы со временем вообще по барабану. Если PWM понадобится - тогда да, придётся считать.
User-space threads существовали ещё на рубеже тысячелетий. В разных инкарнациях: в рамках просто одного процесса, как M:N в системные потоки, может ещё какие-то варианты были.
Потеряли популярность они из-за того, что требовали экзотических фокусов для своей работы: если пользовательский код делал read(), то нельзя было просто дать ему дёрнуть syscall. Эту функцию надо было перехватить и подменить на вызов менеджера ввода-вывода, который оборачивал вызов в select(). И так с каждым потенциально блокирующим системным вызовом. И не забывать обновлять библиотеку каждый раз, когда что-то меняем в сисколлах.
Сделать всё это на уровне компилятора будет ещё сложнее, чем полагаться на системные библиотеки со стандартным API: придётся отслеживать все версии всех платформ где компилятор работает. А если для вашего языка есть несколько реализаций, то будет ещё веселее.
На C++ тоже можно взять folly и написать в пару строк. Корутины в C++ действительно переусложнённые, подход из Rust мне нравится больше, но абсолютно везде сделать поддержку ввода-вывода и минимально необходимых функций для корутин займёт немало кода.
Я вполне могу представить ситуацию, как опытный разработчик на C или C++ решает попробовать Rust, компилирует небольшую программу в режиме релиза, обращает внимание на размер получившегося файла, сразу же отказывается от освоения этого языка и идёт потешаться над ним на форумах.
Проблема понятная и реально существующая, но разработчик какой-то не очень опытный, всё-таки. За десяток лет так и не узнать про strip и отладочные символы...
Внутреннего кода у него ещё больше, но тут NDA, так что поверьте на слово: достаточно. И обсуждения "вот это казалось бы общепринятое поведение разносит код вдребезги в таком-то сочетании компилятора/стандартной библиотеки/платформы" в их команде происходят с печальной регулярностью.
Примерно 500 разработчиков? За последние 365 дней у меня было 304 CL, 100 дней - 139 CL. За месяц 51 CL, но я тут в последние дни много мелочёвки фигачил.
асимптотическая сложность не играет большой роли, когда данных мало
Ой не скажите. На эти грабли вполне можно наступить с со списком из нескольких сотен элементов.
Не далее как несколько месяцев назад в одном из наших сервисов вынужденно меняли архитектуру. Сервис по большому счёту представляет собой QUIC сервер, на котором каждому из сконфигурированных проектов выделен свой IP адрес. В силу разных исторических причин в "архитектуре до" для каждого из проектов создавался свой сокет, слушавший на его адресе и порту 443. И с ростом числа проектов это начало презирядненько жрать процессор.
Как выяснилось (c), в ядре Linux раскладывание UDP пакетов по сокетам сделано так: сначала за O(1) в хэш-таблице находится порт, а потом линейным поиском по списку сокетов на этом порту ищется нужный IP. Потому что сколько сокетов на одном порту нормальные люди откроют: один, ну может пять если у них какие-то особые потребности. "Асимптотическая сложность не играет большой роли". Но это ж у нормальных, а у нас были многие сотни, и этот линейный поиск начал всерьёз влиять и на пожираемый процессор, и на пропускную способность, и на latency.
В "архитектуре после" сокет сделали один, и раскидывание пакетов по обработчикам проводили уже в user-space с более оптимизированными алгоритмами. Метрики улучшились прямо на глазах.
Обычно если задача решается функцией из стандартной библиотеки и соискатель её использует, то просят написать реализацию самостоятельно, а не впадают в шок.
Ну так перепишем. Тоже мне новость, ситуация изменилась или умники какие-то нашли как программу лояльности обмануть. Через год это случится практически неизбежно; если сервис написан и забыт на долгое время, то скорее всего он или никому не нужен, или через полгодика рванёт из-за каких-то внутренних причин.
Вы даже не представляете, что спрашивают на интервью в Амазоне. То есть там теоретически есть coding и system design, но на практике половину от каждого из этих интервью занимает полоскание мозга по Amazon Leadership Principles. И ещё есть отдельное интервью, посвящённое только им.
После этого адочка пойти на обычные "два кодинга, system design, behavioral" - это просто праздник какой-то.
А про компании второго эшелона - очень многие повторяют структуру интервью FAANG, когда достигают определённого размера. Dropbox, Linkedin (даже в домикрософтовскую эпоху), Datadog... Был один мелкий стартап, Data Arrow кажется назывался, в котором со мной просто поговорили, не задавая технических вопросов вообще. Единственное исключение, других таких не было.
В FAANG другие масштабы и другие подходы. Когда мы фигачим CDN на два миллиарда пользователей, десять миллионов запросов - это в секунду.
Что касается "аналитиков" воспроизводящих баги и т.д., то кажется в командах, разрабатывающих клиентские приложения они есть, как первая линия фильтрации, но в бэкенде и библиотеках их просто не существует. Так же не существует QA инженеров и т.д. и т.п. Есть менеджеры, есть разработка, иногда есть SRE. Делаешь что-то - делай так, чтобы самому же не пришлось вешаться, его поддерживая и отлаживая. Когда в компании десятки тысяч программистов, нанять ещё и дополнительных людей ставить им конкретные задачи, с разжёванными требованиями и чётким ТЗ - дело практически невыполнимое.
Когда-то давным-давно, в начале 2000х, когда по земле бродили мамонты вроде меня, было две популярные реализации STL для C++ (и куча форков, конечно). В одной из них сложность list::size() была O(1), а в другой O(n).
И каждый раз, когда программист, не понимающий про сложность алгоритмов, писал перебор элементов списка с их нумерацией, жизнь показывала, зачем знать про сложность алгоритмов. Иногда не сразу, а когда список разрастался с десяти элементов до тысячи.
Эту задачку математики жуют со второй половины прошлого века. Разумеется, практически по всем возможным вариантам уже оттоптались вдосталь. Вот, например, ещё в 1983 году: https://changyaochen.github.io/assets/pdfs/secprob2.pdf
Если вы про вариант, когда можно держать буфер из K кандидатов, или возвращаться к уже отвергнутым с некоторой вероятностью успеха, то он тоже изучался. Практически любую формулировку этой задачи можно забить в гугл и найти статью на десяток страниц с его разбором.
Но почему? Это же признак хорошего менеджмента, и даже умеющего в не очень широко известные алгоритмы, что серьёзный плюс для IT. Я бы наоборот, поставил их в приоритет.
Если это трололо, то прекрасное. Если серьёзно, то лучше бы было трололо :)
"Посмотрите, как при помощи усердия и прилежания в языке X можно сделать то же самое, что в Y реализуется при помощи тайпчекера."
И ведь у C++ система типов довольно слабая, но даже она лучше, чем ничего.
Тем, кто хочет по-прежнему использовать mutex, но не нарываться на проблему "захватили не тот mutex" или "не захватили вообще", могу порекомендовать аннотации из Abseil для проверок во время компиляции: https://abseil.io/docs/cpp/guides/synchronization#thread-annotations
Если с нуля писать, то не настроить, но писать с нуля совершенно необязательно. Берём mbedOS, например, и там всё чудесно инициализируется по умолчанию, а sleep_for() принимает аж литералы времени типа
5s
Или например моя самоделка вообще на Rust в качестве часов использует LPTIMER, и частота ядра ей для работы со временем вообще по барабану. Если PWM понадобится - тогда да, придётся считать.
User-space threads существовали ещё на рубеже тысячелетий. В разных инкарнациях: в рамках просто одного процесса, как M:N в системные потоки, может ещё какие-то варианты были.
Потеряли популярность они из-за того, что требовали экзотических фокусов для своей работы: если пользовательский код делал read(), то нельзя было просто дать ему дёрнуть syscall. Эту функцию надо было перехватить и подменить на вызов менеджера ввода-вывода, который оборачивал вызов в select(). И так с каждым потенциально блокирующим системным вызовом. И не забывать обновлять библиотеку каждый раз, когда что-то меняем в сисколлах.
Сделать всё это на уровне компилятора будет ещё сложнее, чем полагаться на системные библиотеки со стандартным API: придётся отслеживать все версии всех платформ где компилятор работает. А если для вашего языка есть несколько реализаций, то будет ещё веселее.
На C++ тоже можно взять folly и написать в пару строк. Корутины в C++ действительно переусложнённые, подход из Rust мне нравится больше, но абсолютно везде сделать поддержку ввода-вывода и минимально необходимых функций для корутин займёт немало кода.
Перед тем, как обсуждать "правильность" поведения API, надо договориться о том, какие у нас "правильные" ожидания.
Сколько строк должно быть прочитано из пустого файла?
Сколько строк должно быть прочитано из файла, содержащего единственный байт 'a'?
Сколько строк должно быть прочитано из файла '\n'?
Сколько строк должно быть прочитано из файла 'a\n'?
Сколько строк должно быть прочитано из файла 'a\nb'?
И вот по этим ответам уже придумывать API.
Проблема понятная и реально существующая, но разработчик какой-то не очень опытный, всё-таки. За десяток лет так и не узнать про strip и отладочные символы...
Ну вы можете посмотреть на опыт автора в программировании на С/C++, BoringSSL общедоступен: https://github.com/google/boringssl/commits?author=davidben
Внутреннего кода у него ещё больше, но тут NDA, так что поверьте на слово: достаточно. И обсуждения "вот это казалось бы общепринятое поведение разносит код вдребезги в таком-то сочетании компилятора/стандартной библиотеки/платформы" в их команде происходят с печальной регулярностью.
Примерно 500 разработчиков? За последние 365 дней у меня было 304 CL, 100 дней - 139 CL. За месяц 51 CL, но я тут в последние дни много мелочёвки фигачил.
Ой не скажите. На эти грабли вполне можно наступить с со списком из нескольких сотен элементов.
Не далее как несколько месяцев назад в одном из наших сервисов вынужденно меняли архитектуру. Сервис по большому счёту представляет собой QUIC сервер, на котором каждому из сконфигурированных проектов выделен свой IP адрес. В силу разных исторических причин в "архитектуре до" для каждого из проектов создавался свой сокет, слушавший на его адресе и порту 443. И с ростом числа проектов это начало презирядненько жрать процессор.
Как выяснилось (c), в ядре Linux раскладывание UDP пакетов по сокетам сделано так: сначала за O(1) в хэш-таблице находится порт, а потом линейным поиском по списку сокетов на этом порту ищется нужный IP. Потому что сколько сокетов на одном порту нормальные люди откроют: один, ну может пять если у них какие-то особые потребности. "Асимптотическая сложность не играет большой роли". Но это ж у нормальных, а у нас были многие сотни, и этот линейный поиск начал всерьёз влиять и на пожираемый процессор, и на пропускную способность, и на latency.
В "архитектуре после" сокет сделали один, и раскидывание пакетов по обработчикам проводили уже в user-space с более оптимизированными алгоритмами. Метрики улучшились прямо на глазах.
А в чём проблема реализовать merge sort или quicksort? Это достаточно простые алгоритмы, если не загоняться супероптимизациями. HashMap ещё проще.
Слабовато готовят интервьюеров в Яндексе :)
Обычно если задача решается функцией из стандартной библиотеки и соискатель её использует, то просят написать реализацию самостоятельно, а не впадают в шок.
Ну так перепишем. Тоже мне новость, ситуация изменилась или умники какие-то нашли как программу лояльности обмануть. Через год это случится практически неизбежно; если сервис написан и забыт на долгое время, то скорее всего он или никому не нужен, или через полгодика рванёт из-за каких-то внутренних причин.
Вы даже не представляете, что спрашивают на интервью в Амазоне. То есть там теоретически есть coding и system design, но на практике половину от каждого из этих интервью занимает полоскание мозга по Amazon Leadership Principles. И ещё есть отдельное интервью, посвящённое только им.
После этого адочка пойти на обычные "два кодинга, system design, behavioral" - это просто праздник какой-то.
А про компании второго эшелона - очень многие повторяют структуру интервью FAANG, когда достигают определённого размера. Dropbox, Linkedin (даже в домикрософтовскую эпоху), Datadog... Был один мелкий стартап, Data Arrow кажется назывался, в котором со мной просто поговорили, не задавая технических вопросов вообще. Единственное исключение, других таких не было.
В FAANG другие масштабы и другие подходы. Когда мы фигачим CDN на два миллиарда пользователей, десять миллионов запросов - это в секунду.
Что касается "аналитиков" воспроизводящих баги и т.д., то кажется в командах, разрабатывающих клиентские приложения они есть, как первая линия фильтрации, но в бэкенде и библиотеках их просто не существует. Так же не существует QA инженеров и т.д. и т.п. Есть менеджеры, есть разработка, иногда есть SRE. Делаешь что-то - делай так, чтобы самому же не пришлось вешаться, его поддерживая и отлаживая. Когда в компании десятки тысяч программистов, нанять ещё и дополнительных людей ставить им конкретные задачи, с разжёванными требованиями и чётким ТЗ - дело практически невыполнимое.
Когда-то давным-давно, в начале 2000х, когда по земле бродили мамонты
вроде меня,было две популярные реализации STL для C++ (и куча форков, конечно). В одной из них сложность list::size() была O(1), а в другой O(n).И каждый раз, когда программист, не понимающий про сложность алгоритмов, писал перебор элементов списка с их нумерацией, жизнь показывала, зачем знать про сложность алгоритмов. Иногда не сразу, а когда список разрастался с десяти элементов до тысячи.
N это количество рассматриваемых кандидатов? См раздел 5 вот в этой статье, поиск с заранее неизвестным N: https://changyaochen.github.io/assets/pdfs/secprob2.pdf
Эту задачку математики жуют со второй половины прошлого века. Разумеется, практически по всем возможным вариантам уже оттоптались вдосталь. Вот, например, ещё в 1983 году: https://changyaochen.github.io/assets/pdfs/secprob2.pdf
Если вы про вариант, когда можно держать буфер из K кандидатов, или возвращаться к уже отвергнутым с некоторой вероятностью успеха, то он тоже изучался. Практически любую формулировку этой задачи можно забить в гугл и найти статью на десяток страниц с его разбором.
Это отличный пример, почему даже фронтэндщику с перекладыванием структурок в JS стоит хотя бы в общих чертах представлять себе всякие заумные алгоритмы: они всплывают в совершенно непредсказуемых местах. Даже книжки про это есть: https://www.amazon.com/Algorithms-Live-Computer-Science-Decisions/dp/1627790365/
Но почему? Это же признак хорошего менеджмента, и даже умеющего в не очень широко известные алгоритмы, что серьёзный плюс для IT. Я бы наоборот, поставил их в приоритет.
На всякий случай, алгоритм тут: https://en.wikipedia.org/wiki/Secretary_problem