• Как в rust конвертировать place expression в value expressions?

    bingo347
    @bingo347
    Crazy on performance...
    Проблема с типами тут.
    Тип fn() -> u8 - это указатель на функцию. В него можно записать или обычную функцию с подходящей сигнатурой или замыкание, которое ничего не замыкает:
    fn some_func() -> u8 {
        0
    }
    
    let f: fn() -> u8 = some_func;
    let f: fn() -> u8 = || 0;

    Если же замыкание что-то замыкает (захватывает переменные из окружения), то это уже анонимная структура, хранящая в себе все захваченные значения (или ссылки на них), и у этой структуры просто перегружен оператор круглые скобки через трейты Fn/FnMut/FnOnce. Притом, так как компилятор генерирует для каждого замыкания в коде свою анонимную структуру, у каждого замыкания будет свой уникальный тип.

    Если массив замыканий полностью формируется в цикле, то замыкания будут одного типа и все скомпилируется:
    fn main() {
        let mut funcs = Vec::with_capacity(3);
        for i in 1u8..=3 {
            funcs.push(move || i);
        }
        
        for i in 0..3 {
            println!("{}", funcs[i]());
        }
    }


    P.S. для рэнжей есть литералы, не нужно их создавать через std::ops::RangeInclusive::<u8>::new
    Ответ написан
    2 комментария
  • Как происходит исполнение кода в Event Loop и управление потоками для веб приложений?

    bingo347
    @bingo347 Куратор тега Node.js
    Crazy on performance...
    1. Как происходит связь между кодом js, c++. На самом гитхабе Nodejs можно открыть папки с функциями, которые я импортирую в коде. А также их реализации в файлах .cc расширения. Но не могли бы подробнее описать механизм, которые позволяет 2 разных языка использовать.
    JS движок (например V8) предоставляет платформе (Node.js) некоторый C++ api, через который платформа может движком управлять. Например через это api можно дать движку строчку с JS кодом и попросить его выполнить, а в ответ получить указатель на результат выполнения (V8 например возвращает результат последнего выражения в коде). Так же, если у нас есть указатель на JS функцию, можно попросить движок ее выполнить с определенными аргументами и this, а в ответ получить результат этого выполнения (функция что-то вернула или бросила исключение). Ну и наконец, мы можем дать этому api указатель на C/C++ функцию, а движок сделает из нее JS функцию и вернет указатель на нее, когда JS функция вызывается движок вызовет нашу C/C++ функцию и даст ей на вход контекст выполнения, из которого можно извлечь this и аргументы функции, так же через контекст можно установить результат выполнения JS функции, указав что JS функция должна вернуть некоторое JS значение или бросить некоторое исключение.

    2. V8 - движок для исполнения JS кода, то есть превращения его в машинный код для исполнения комманд. Libuv написана на с++. Они же не работают в паре? Я так понимаю, что часть кода исполняется на движке v8, а различные асинхронные вызовы, которые через Nodejs api делегируются библиотеке Libuv - уже от неё превращаются в низкоуровневый машинный код, который исполняется компьютеров?Можете чуть пролить свет на исполнения уже между этими компонентами Libuv, V8.
    V8 ничего не знает о libuv, как и libuv ничего не знает о V8.
    V8 занимается компиляцией/интерпретацией/выполнением JS кода, управлением JS памятью и некоторыми другими связанными с JS вещами. В V8 нет никаких event loop и чего-то подобного, он запускает JS код только когда ему об этом скажет платформа (например Node.js).
    Libuv занимается асинхронными операциями. Что-то переадресует операционной системе, например сетевые сокеты можно собрать в пачку и отдать в epoll в Linux или kqueue в MacOS, заблокировав лишь один поток сразу на тысячи сокетов. А что-то просто блокируется на фоновых потоках, например обращения к файловой системе. Event loop нет и здесь, но зато есть очередь задач, которые потенциально готовы.
    Ну и наконец сама платформа (Node.js) реализует event loop (по сути просто бесконечный цикл), в котором получает потенциально готовые задачи от libuv и раскладывает по своим очередям готовые, а неготовые планирует в libuv, спрашивает у V8 не хочет ли он сделать сборку мусора, ну и наконец говорит V8 вызвать некоторые JS функции.

    3. После того, как Nodejs передает асинхронный вызов Libuv на исполнение. То callback функция помещается позже в стэк для исполнения, а исполнятся начинается после того, как система просигнализирует о завершении процесса, например считывания файла. Или вначале считывается файл, а потом система об этом сигнализирует и помещается callback функция в стэк Event Loop'a для исполнения?
    Выше уже расписал как Node.js взаимодействует с libuv в теле event loop, так же расписал как JS код может вызвать C++ функцию. Рассмотрим на сильно упрощенном примере, что происходит когда в JS коде на Node.js мы вызываем fs.readFile(filepath, callback):
    1. fs.readFile - это обычная JS функция, но внутри она вызывает некоторую C++ функцию из Node.js, которая получает указатель на строку filepath и указатель на JS функцию callback, но эта C++ функция будет запущена на том же потоке где и event loop (по сути где-то внутри цикла), а блокировать нам нельзя. Поэтому она просто планирует вызов другой C++ функции на фоновых потоках и завершается, возвращая тем самым управление JS коду.
    2. В какой-то момент до запланированной C++ функции дойдет очередь на выполнение на одном из фоновых потоков, она прочитает файл в память и добавит в очередь готовых задач некоторый объект, который является результатом операции чтения из файла, этот объект будет хранить в себе указатель на прочитанные данные и указатель на JS функцию callback.
    3. Еще через некоторое время поток с event loop извлечет из очереди этот объект результат и скажет V8 вызвать функцию callback с данными из файла.

    4. Можете более подробней рассказать про исполнение кода на инстансах приложения в зависимости от количества ядер процессора и управления потоками:

    4.1 Есть к примеру приложений на Nodejs. На компьютере 4 ядра. Я на каждом ядре могу запустить инстанс этого приложения. И у каждого инстанса в pool thread'e будет по 4 потока дополнительных, которые создаются по умолчанию?
    Каждый инстанс Node.js - это отдельный процесс операционной системы. У каждого процесса своя изолированная память. И да, каждый может запускать несколько потоков (у Node.js кстати 4 потока - это минимум, при большой нагрузке она может добавить в пул до 128 потоков), но в случае с Node.js большая часть потоков почти всегда что-то ждут (пока тот же файл прочитается например) и почти не тратят ресурсы CPU, а активно работает лишь один - тот в котором event loop.

    4.2 Если отойти от ноды и запустить приложение на php фреймворке на Apache и этот сервер выделяет под каждый запрос свой поток.В данном случае - это такой же условно поток, который может выделяться и библиотекой Libuv или это абсолютно разные понятия? И сколько инстансов php приложения запущено, когда Apache под каждый создает свой поток? Как соотносится поток с инстансом приложения на php.
    С точки зрения операционной системы - да, это такие же потоки. Разница заключается в том, что в этих потоках происходит. В php только 1 поток, который то что-то полезное делает, то ждет ответа от БД/файловой системы/еще чего-то. А в Node.js это разделено, 1 поток занят только полезной работой (выполнением JS кода) и несколько только ждут ответа.
    Насчет какие там лимиты на количество инстансов php у Apache я не скажу, но они точно не бесконечные, а значит если лимит будет исчерпан, то клиенты (браузер) будут ждать пока какой-то из инстансов php не завершит свою работу полностью. А в node.js мы на одном инстансе можем обслуживать сразу множество клиентов, выполняя задачи для каждого по чуть-чуть, пока для одного клиента ждем ответ из БД можем заняться обработкой запроса от другого клиента.

    4.3 Может в дополнение расскажите про потоки в системе, их ограничения и т.д
    Тут целую лекцию можно читать. Думаю это стоит вынести в отдельный вопрос.
    Ответ написан
    3 комментария
  • Реально ли заменить gulp на vite?

    bingo347
    @bingo347
    Crazy on performance...
    Есть сборщик gulp
    То что под gulp есть сборщики не делает сам gulp сборщиком. Gulp - task runner, запускалка задач. То есть сборщик под капотом может быть любой, хоть тот же vite.
    Теперь про vite, основная его фишка - это ускорение dev сборок и за счет этого ускорение самого процесса разработки. Достигает он это за счет того, что по сути не собирает Ваши исходники, а только применяет к ним трансформации, хотя зависимости все же собирает с помощью esbuild. При этом для прода вся сборка переадресуется на rollup. И то что в dev и в prod у Вас будут по сути разные сборщики изредка приводит к багам, которые воспроизводятся только в prod сборках. Rollup надо сказать тоже не идеален и на больших проектах порой ломает код, хоть и редко.
    Тут мое ИМХО и не более
    Rollup для сборки библиотек.
    Webpack для сборки конечных приложений.
    Vite интересен скорее интегрированным в него vitest, который позволяет писать unit тесты ближе к логике (привык я к хорошему в Rust).

    А по факту, смена сборщика чревата ошибками, сильными изменениями в структуре проекта и прочими подводными камнями.
    Если вопрос "стоит ли переезжать" появился только из hype-driven-development (погоней за модой по-простому), то ответ однозначный - нет, не стоит.
    Если же текущая сборка накладывает на Вас сильные ограничения и борьба с этими ограничениями занимает очень много времени, настолько, что потенциальные проблемы от смены сборки скорее всего займут времени меньше, то да, стоит переезжать.
    Ответ написан
    1 комментарий
  • Обработать If-Modified-Since?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Ответ написан
    Комментировать
  • Как правильно расширить дженерик интерфейс?

    bingo347
    @bingo347 Куратор тега TypeScript
    Crazy on performance...
    Что-то вроде такого:
    https://www.typescriptlang.org/play?#code/KYDwDg9g...
    Ответ написан
    Комментировать
  • Как реализовать логику игры на js?

    bingo347
    @bingo347
    Crazy on performance...
    Так как в нормальном диалоге следующие реплики зачастую зависят от предыдущих, то нужны не массивы, а дерево запросов и ответов. Или даже граф, так как возможно что несколько путей приведут к одной ноде.
    А дальше усложняйте на свой вкус, введите шкалу отношения например, от которой зависят реплики бота.
    Ответ написан
    1 комментарий
  • Является ли абстрактная фабрика способом динамически создавать классы?

    bingo347
    @bingo347
    Crazy on performance...
    Пример бы привели, который увидели.
    Если кратко - ответ нет, абстрактная фабрика отличается от обычной, тем что создает объекты не конкретного типа, а более абстрактного (любого типа удовлетворяющего интерфейсу например).
    Динамически создавать классы не во всех ЯП можно, а паттерны абстрагированы от ЯП.
    Ответ написан
    1 комментарий
  • Как сделать фильтрацию массива?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Про метод массива some уже написали выше.
    Я бы еще вынес некоторые условия из итерации:
    const brandsPredicate = s.hasOwnProperty("brands") && s.brands.length > 0
      ? product => s.brands.includes(product.brand_id)
      : () => true;
    const paramsPredicate = s.hasOwnProperty("params") && s.params.length > 0
      ? product => product.hasOwnProperty("params") &&
        s.params.some(param => product.params.includes(param))
      : () => true;
    
    const result = products.filter(product => brandsPredicate(product) && paramsPredicate(product));
    Ответ написан
    1 комментарий
  • По какой причине выдает ошибка в TypeScript?

    bingo347
    @bingo347 Куратор тега TypeScript
    Crazy on performance...
    function isPostField(field: string): field is keyof Post {
      return field === 'title' || field === 'text';
    }
    
    export class SearchingPipe implements PipeTransform {
      transform(posts: Post[], search: string, searhcField: string = 'title') {
        if (!isPostField(searhcField) || !search.trim()) {
          return posts;
        }
    
        return posts.filter((post) => {
         
          return post[searhcField]
            .toLocaleLowerCase()
            .includes(search.toLocaleLowerCase());
        });
      }
    }
    Ответ написан
    Комментировать
  • Зачем нужен метод clone() если есть ссылки?

    bingo347
    @bingo347
    Crazy on performance...
    Метод clone из трейта Clone производит копию некоторого ресурса, мы получаем еще один ресурс во владение. При этом данные не обязательно копируются, логика может быть любой, например Rc и Arc в нем просто увеличивают счетчик ссылок, а ресурс остается одним, разделяя владение на несколько владельцев.
    Ссылки ограничены временем жизни ресурса, на который они ссылаются, к тому же менять ресурс мы можем только по уникальной ссылке, а метод clone создаст копию ресурса и отдаст владение этой копией, что позволит этой копии жить дольше, чем исходный ресурс, а так же изменять эту копию независимо от исходного ресурса.
    Ответ написан
    1 комментарий
  • Как получить utc offset с точность до секунд?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Думаю можно просто рассчитать:
    function calculateUTCOffsetSeconds(timestamp) {
      const date = new Date(timestamp);
      const utcTime = date.getUTCHours() * 3600 +
        date.getUTCMinutes() * 60 +
        date.getUTCSeconds();
      const localTime = date.getHours() * 3600 +
        date.getMinutes() * 60 +
        date.getSeconds();
      return localTime - utcTime;
    }
    console.log(calculateUTCOffsetSeconds(-2208988800000));
    Ответ написан
    Комментировать
  • Для чего внутри связного списка нужен массив?

    bingo347
    @bingo347
    Crazy on performance...
    К ответам выше я бы еще добавил, что массивы более дружелюбны к процессорному кэшу чем связные списки. Варьируя размер массивов в нодах списка можно подобрать такой размер ноды, чтоб она соответствовала размеру кэш-линии.
    Ответ написан
    Комментировать
  • Как создать Тип функции, принимающей тип и возвращающей интерфейс?

    bingo347
    @bingo347 Куратор тега TypeScript
    Crazy on performance...
    type TypeMap = {
      string: string;
      number: number;
      bigint: bigint;
      boolean: boolean;
      symbol: symbol;
      undefined: undefined;
      object: object;
      function: Function;
    };
    
    type TypeName<T> = {
      [K in keyof TypeMap]: T extends TypeMap[K] ? K : never;
    }[keyof TypeMap];
    
    
    const evgeniy = <T extends string | number>(x: T) => ({
      resultedType: typeof x as TypeName<T>,
    });
    Ответ написан
    Комментировать
  • Уменьшается ли используемая память программы?

    bingo347
    @bingo347
    Crazy on performance...
    Во-первых, размер стека фиксирован, стек выделяется в момент запуска потока.
    Во-вторых, компилятор и сам достаточно умный, чтобы переиспользовать стек под разные переменные использование которых не пересекается.
    В-третьих, экономия на спичках, а читаемость ухудшается.

    P.S. такую штуку действительно иногда используют, но ради того чтоб вызвать деструктор в нужной точке кода.
    Ответ написан
    Комментировать
  • Как поправить функцию, чтобы она работала после обработки Webpack?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Не навешивать обработчики из html.
    https://developer.mozilla.org/en-US/docs/Web/API/E...
    Ответ написан
    Комментировать
  • Как в setInterval вызывать задержку следующего реста, пока не выполнится предыдущий?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    const freqUpdateInMs = 1000
    
    export default {
      data() {
        return {
          loading: false,
          items: {},
          timer: null
        }
      },
      mounted() {
        const fetchData = () => {
          this.$store.commit('setLoading', true)
          this.fetchData()
            .finally(() => {
              this.timer = setTimeout(fetchData, freqUpdateInMs)
              this.$store.commit('setLoading', false)
            })
        }
        fetchData()
      },
      beforeDestroy() {
        clearTimeout(this.timer)
      }
    }
    Ответ написан
  • Как внутри функции с generic запустить цикл в цикле на react?

    bingo347
    @bingo347 Куратор тега TypeScript
    Crazy on performance...
    Нужно ограничить дженерик, иначе там может оказаться любой тип, а в Object.entries любой тип отдать нельзя.
    interface TableProps<T extends Record<string, unknown>> {
        entities: T[] | null; // тут возможно еще стоит сделать это поле необязательным?
    }
    
    const Table = function <T extends Record<string, unknown>>({
        entities,
    }: TableProps<T>) {
        // ...
        return (<>
            {entities?.map((entity, key) => {
                return Object.entries(entity).map(([key, value], index) => {
                    // ...
                });
            })}
        </>);
    }
    Ответ написан
    1 комментарий
  • Как искать в открытых файлах?

    bingo347
    @bingo347
    Crazy on performance...
    64352b32a6cc7214748039.bin
    Ответ написан
    Комментировать