• Сказ об опасном std::enable_shared_from_this, или антипаттерн «Зомби» — разбор полётов
    0
    В таком случае мне кажется проблема в бизнес логике, а не в shared_ptr.
    Я конечно над этим не задумывался, но мне кажется, что RAII — это ответственность именно конкретного участка кода, не нужно надеяться на raii извне.

    То есть, когда Вы обмениваетесь умными указателями, то эти указатели — это не raii, это всеголишь гарантия, что не будет утечек памяти. А raii должен обеспечивать каждый сам
  • Сказ об опасном std::enable_shared_from_this, или антипаттерн «Зомби» — разбор полётов
    0
    Ну мне кажется тот, кто создал shared_ptr, хорошо понимает, что при выходе из скоупа объект останется жить. Странно было бы полагаться на иное поведение
  • Сказ об опасном std::enable_shared_from_this, или антипаттерн «Зомби» — разбор полётов
    0
    А, кажется начинаю понимать. То есть гонкой вы называете примерно такое поведение:

    thread1:
    sp->work();
    sp->release();
    std::cout << "Here sp released";
    


    thread2:
    sp = wp.lock();
    std::cout << "Log \"Here sp released\" not printed";
    


    Тогда здесь в строках std::cout действительно будет то, что Вы подразумеваете под «гонкой»
  • Сказ об опасном std::enable_shared_from_this, или антипаттерн «Зомби» — разбор полётов
    0
    Но в таком случае, если я правильно понимаю, объект еще будет жив? То есть, если в результате lock объект получен, то он не мог ни на каком предыдущем шаге быть уничтожен? (иначе откуда бы он тогда взялся для нас). И также, он не может находиться в ситуации самоуничтожения, так как сначала декрементится счетчик для shared, а потом вызывается деструктор (ну мне так кажется)
  • Сказ об опасном std::enable_shared_from_this, или антипаттерн «Зомби» — разбор полётов
    0
    А поясните пожалуйста такой момент

    запускает лямбда-функцию на выполнение в отдельном потоке
    пытается взять сильную ссылку на экземпляр класса с проверкой результата; проверка проходит успешно
    уничтожает единственную внешнюю сильную ссылку

    Почему здесь происходит гонка данных? Это связано с тем, что weak_ptr::lock() не thread-safe?
  • Особенности профилирования программ на C++
    0
    Ну есть профайлеры, которые показывают загрузку потокв в динамике. Но думаю это не сильно поможет для данной задачи.
    Я бы сделал обертку для lock-а и собирал бы время там, если не найдется решения получше
  • Особенности профилирования программ на C++
    +3
    Тут есть несколько проблем
    1) Сложнее понять стек вызовов, когда половина функций заинлайнилась, а половина нет.
    2) Сложно оценить относительное время работы функций
    Всетаки если бы программист хотел, чтобы «функции вообще нет», то он наверно и не писал бы функцию. А если функция есть, значит каким-то целям программиста она служила.
  • Управляя коллективом, нарушьте все правила
    +1
    Вот интересно, то есть программисты должны иметь «свой путь», им давай только конечную цель, а не набор правил, но сами менеджеры при найме кандидатов должны превратиться в роботов, следующих определенному списку правил?
  • Задачки по программированию — плохой способ оценки квалификации Senior Developer'а
    0
    Вот кстати, недавно на хабре проскочила статья, где была эта ссылка
    shipilev.net/blog/2014/safe-public-construction
    Здесь правда про яву, но думаю, в C++ будет также
  • Задачки по программированию — плохой способ оценки квалификации Senior Developer'а
    0
    Нет, дело во внутренних полях класса.
  • Задачки по программированию — плохой способ оценки квалификации Senior Developer'а
    0
    Где count.load и где оперирование указателем? Точно также можно сказать «создание потока создает необходимый барьер», но это не значит, что теперь все программы можно писать без мьютексов?
  • Задачки по программированию — плохой способ оценки квалификации Senior Developer'а
    0
    Мьютексы — это не только про гонку данных, но еще и про барьеры в памяти. Если нет барьера, то и результат не предсказуем.
    В данном случае может получиться так. Пусть в классе есть какое-то поле x.
    Мы создаем экземпляр этого класса, инициализируем это поле, и берем указатель на этот класс. Но вот только указатель уходит в memory, а инициализированное поле пока остается в регистре ядра.
  • Задачки по программированию — плохой способ оценки квалификации Senior Developer'а
    0
    1) Кроме указателя еще существуют и данные. И они могут «добежать» позже самого указателя
  • Задачки по программированию — плохой способ оценки квалификации Senior Developer'а
    0
    В принципе, код мне нравится, но мне кажется в нем есть ошибки (если это я ошибаюсь, то было бы хорошо, если объясните, что не так).
    Дальше буду писать без «мне кажется»

                if (!next) {
                    std::lock_guard<std::mutex> _(expansion);
                    if (!next) next = std::make_unique<MemoryPool>();
                }
    

    Мьютекс должен быть симметричный. То есть, если создаем объект под мьютексом, то и читать должны под мьютексом.
    Также, сам код
                if (!next) {
                    std::lock_guard<std::mutex> _(expansion);
                    if (!next) next = std::make_unique<MemoryPool>();
                }
                return next->allocate(); 
    

    неверен по той же причине

    2)
    elem->~ElemT();
    

    Если элемент не сконструироваля, то деструктор у него вызывать нельзя

    3)
                    while(!freeList.at(pos).compare_exchange_weak(index, TAKEN, std::memory_order_relaxed)){ []{}; };
    
                    // take the spot
                    elem = &arena[index];
    


    Нужна проверка перед elem = &arena[index]; что index <> TAKEN.
    Можете попробовать прокрутить в голове алгоритм с двумя потоками и ChunkSize == 1
  • Почему Rust должен стать функциональным языком программирования
    0
    Дело врядли в выделении памяти. Это поведение я видел на C++. Возможно, что всетаки связано с троттлингом
  • Почему Rust должен стать функциональным языком программирования
    +1
    Вроде я когдато видел такой тест, что
    slow_func()
    tBegin =
    fast_func()
    tEnd =
    Давало результат в худшую сторону, чем просто
    tBegin =
    fast_func()
    tEnd =
    Притом что slow_func и fast_func могуть быть как связаны друг с другом, а могут и не связаны.
    Возможно это как-то связано с тем, что процессор после медленной функции начинает троттлить или что-то еще.
    Сейчас сходу набросал пример, но не получилось такого поведения поймать. Но ситуация имеет место быть
  • Почему Rust должен стать функциональным языком программирования
    0
    > Про rand не понял
    Кстати, нельзя бенчмаркать «быстрые» функции, выполняющиеся после медленных. rand — медленная. Советую сгенерировать массив rand-ом и скопировать его целиком в исходник
  • Задачки по программированию — плохой способ оценки квалификации Senior Developer'а
    0
    Иногда история коммитов в системе контроля версий еще хуже, чем сам код.
    Конечно, можно воспользоваться фишкой «создать тэг с названием „до удаления функции X“, но ситуации бывают разные, иногда и это не помогает
  • Задачки по программированию — плохой способ оценки квалификации Senior Developer'а
    0
    > То есть, по второму пункту, если завтра придут и скажут, что нужно, например, только последнюю записи, то он просто в конец этого кода добавит «взять последний элемент из того, что получилось»

    Както делал на одной работе нечто похожее. Правда там не было тех разительных x10, но логика была примерно такаяже.
    Проблема в том, что если сейчас убрать весь этот код, оставить только нужное, то потом хрен найдешь, как оно там было раньше, как в эту базу ходить, да и индексы все уже давным давно потерты.
  • Задачки по программированию — плохой способ оценки квалификации Senior Developer'а
    +1
    > но это мой косяк, не посмотрел, по думал, не так понял, не уделил этому должное внимание.

    А я частенько бывал и с другой стороны этого утверждения. Сделал слишком заумную архитектуру, наложил слишком много ограничений и т.д. В результате часто от этого огребаешь. И это даже обиднее, чем просто «забил и пустил на самотек»: ты тратил время на продумывание архитектуры, крайних случаев, примеров использования, нетривиальную реализацию, а по итогу оно все также не работает.

    Вот например, у меня есть один проект, в котором основная часть кода — ну, не совсем дерьмо, но на самом деле, ничего особенного. Глазу незачто зацепиться. Я знаю, как навесить вокруг этого кода офигенную архитектуру, которую хоть в рамочку вешай и всем показывай. Но проблема в том, что эта архитектура опирается на некоторые ограничения. И почти наверняка, когда я закончю эту архитектуру писать, придет менеджер с задачей, которая эту архитектуру как раз ломает (я даже знаю такую задачу, но чтото менеджер о ней уже давно не вспоминает). И что в результате мне с этим делать?

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

    В результате, довольно часто бывают такие ситуации, когда в какой-то части проекта код — гавно, но ты об этом не знаешь. Вот когда в ту часть кода придет задача, то ты посидишь, подумаешь и исправишь. А если в ту часть кода никаких задач нет — то и исправлять там нечего
  • Задачки по программированию — плохой способ оценки квалификации Senior Developer'а
    0
    Ну да, просто обсуждалось, можно ли это реализовать на sql-е. Вроде можно, правда на порядок сложнее. Но может, в sql-е уже есть специальный индекс на эту тему, нужно бы поискать
  • Задачки по программированию — плохой способ оценки квалификации Senior Developer'а
    0
    Ну тогда получается, что это «потоковый» алгоритм, который проходит сразу все элементы. Тогда думаю, будет лучше использовать аналоги идиомы erase/remove. Или, как Вы сами предложили, перекладывать элементы в другой массив.

    > И да, конечно, работа с ArrayList/LinkedList — это где-то близко к вершине айсберга… но если вы не знаете даже этого, то каков шанс, что вы не запутаетесь в дебрях этого айсберга.

    Ага, это я понимаю. просто думал, у Вас есть какойто интересный пример работы с LinkedList
  • Задачки по программированию — плохой способ оценки квалификации Senior Developer'а
    0
    Тоже немного подумал, как это сделать в базе.
    Разобьем базу на подбазы с лимитом по 1000 элементов. Назовем из s1, s2…
    То есть в подбазе (подбаза — это просто поле в таблице рейтинга) s1 лежат люди с местами 1..1000, s2 — 1001-2000 и т.д. (вариант, когда подбаза заполнена не полностью, здесь рассматривать не будем)

    Когда нам нужно упдейтить какой-то элемент, например у него score был 40. Стал 60. Смотрим, рядом с какими элементами он будет стоять. То есть, рядом например элемент из подбазы s2 со score 59 и элемент из тойже подбазы s2 со score 61. Так как мы собираемся переместить наш элемент в подбазу s2, то получается, что из подбазы s2 лишний элемент нужно выкинуть (у нас ограничение на ровно 1000 элементов) в подбазу s3. Из подбазы s3 последний элемент нужно выкинуть в подбазу s4 и т.д.

    Таким образом, для вставки элемента потребуется порядка 300000/1000=300 действий.

    Для вычисления места, мы также знаем в какой подбазе лежит элемент. Если элемент лежит в подбазе s3, то до него 2000 + x элементов, где x можно вычислить, пересчитав все элементы с головы подбазы до нашего элемента, что не больше 1000 действий

    То есть получается порядка 300 действий на вставку и 1000 на чтение.

    Понятно, что это все равно в десятки раз медленнее велосипеда (и сложнее), просто, разминка для ума.

    Можно попробовать реализовать. Быстрее текущего решения понятно что не будет, но в ограничения можно попробовать уложиться
  • Задачки по программированию — плохой способ оценки квалификации Senior Developer'а
    0
    Для удаления в том же c++ существуют идиомы erase-remove. Для вставки тоже наверно можно чтото придумать. По моему, «портить» код LinkedList-ом только для того, чтобы чтото откудато удалить, это нехорошо. Лучше использовать другой подход

    Зависит конечно от частоты операций. Но я например не представляю, как делать предложенные Вами операции «по одиночке». То есть, как я понимаю, эти операции выполняются сразу пачкой, например «удалить все дубликаты строк». Тогда идиомой erase-remove это решается эффективнее, чем листами. А если нужно удалять по одному элементу… То как еще найти этот элемент? То есть представьте, что Вам нужно что-то удалить из середины списка. Но для этого же до этой середины еще нужно както дойти в случае листа. Получается тот самый «квадрат» (точнее линейный поиск в случае одного запроса), которого Вы так боялись
  • Задачки по программированию — плохой способ оценки квалификации Senior Developer'а
    0
    Ну хотя да, я что-то не подумал, что вычислить конкретное место в таблице будет несколько сложно. И спозиционироваться к определенному месту тоже. Хотя, базы данных сейчас умные. Может там что-то придумали специально для этого
  • Задачки по программированию — плохой способ оценки квалификации Senior Developer'а
    0
    От количества данных зависит конечно. Но вставка чегото «поближе к началу» это уже довольно странная операция на мой взгляд. Если вставлять совсем в начало, то есть ArrayDeque
  • Задачки по программированию — плохой способ оценки квалификации Senior Developer'а
    0
    Мм. Может, я чегото не понимаю, но почему бы сразу не читать из sql?
  • Задачки по программированию — плохой способ оценки квалификации Senior Developer'а
    0
    Вообще, конечно зависит от более полного описания задачи. Если мы не хотим потерять эту таблицу при перезапуске сервера, то имя такой библиотеки — *sql
  • Задачки по программированию — плохой способ оценки квалификации Senior Developer'а
    0
    Тогда да. Приличненько
  • Задачки по программированию — плохой способ оценки квалификации Senior Developer'а
    0
    А какой размер таблицы? 150-200 раз в секунду не выглядит слишком большим числом
  • Задачки по программированию — плохой способ оценки квалификации Senior Developer'а
    0
    Тоесть у вас есть реально подтвержденное поведение? Какой размер массива был? Какой тип вычислений? Я подозреваю, там еще может быть связано со сборщиком мусора, возможно удалять небольшие куски памяти ему проще, чем большие. Но было бы интересно получить этому подтверждение.

    > Ну и? От кого вы ожидаете, что он устранит протечки? От сеньора или джуниора?
    От любого наверно. То есть по вашему, синьер должен уметь устранять только протечки ArrayList-а? Никаких других протечек устранять он уметь больше не должен? Я о том, что не лучше ли выработать повторяемые методики поиска утечек, чем устранять эти самые утечки «методом тыка»?

    Я вот в яве почти не работал, но в C++ я бы ни за что не догадался бы взять std::list в качестве коллекции. За 10 лет он мне потребовался всего один-единственный раз: когда нужно было гарантировать, что элементы, добавленные в список, никуда не денутся со своего места при любых манипуляциях с этим списком.
  • Задачки по программированию — плохой способ оценки квалификации Senior Developer'а
    0
    О, вы та самая компания, которая знает, где LinkedList быстрее ArrayList-a? Расскажите пожалуйста. Мне кажется, с точки зрения явы там должно быть вообще все равно.
    (Не все равно может быть разве только в случае занимаемой памяти, ArrayList может выделить сильно больше того, что необходимо)
  • Функциональное программирование — это не то, что нам рассказывают
    0
    В одной популярной библиотеке для парсинга конфигов в случае отсутствия значения возвращается exception с телом «SettingNotFoundException» :)
    github.com/hyperrealm/libconfig/blob/master/lib/libconfigcpp.c%2B%2B#L282
  • Минкомсвязи: реклама на 10–15 млрд ₽ ушла от ТВ к блогерам
    +1
    Ну это тоже известная ловушка
    «Сказать правду» -> «Сказать правду» -> «Высказать пропаганду». На том же тв это постоянно практикуется. Мысль здесь в том, что человек, несколько раз услышав правду, автоматически согласится на любое следующее утверждение, ибо мозг человека больше предрасположен ко лжи, а не правде.
    С людьми это тоже работает. Самый простой пример — реклама. Но только в этом случае мы понимаем, что это просто реклама, человеку на что-то надо жить. А если человек внезапно выдвигает «Аляска — наш», то как узнать, это он искренне или это тоже проплачено?
  • Тесты Ryzen Threadripper 3960X и 3970X показали, что это действительно революционные CPU
    0
    Для ГТА5 помогает поднять приоритет програмы в процессах. Разница на глаз видна.
    Сам мучался несколько десятков часов, пока не раскусил
    Может и в других играх поможет
    (А я думал, приоритет вообще ни на что не влияет)
  • Проблема частого создания и удаления объектов
    0
    Просто вы писали, что заменили одни контейнеры на другие. Тут интересно, повлияло ли это както на производительность
  • Проблема частого создания и удаления объектов
    0
    А не получилось так, что за счет оптимизации одной части кода (выделение/освобождение памяти) замедлилась другая часть кода (бизнес-логика)? Как-то можно замерить, сколько времени ушло целиком на отработку всех запросов?
  • Конфигурационные файлы. Библиотека libconfig и определение неиспользуемых настроек
    0
    А как с thread safety? Как я понимаю, libconfig не thread-safe даже на чтение. Или у вас разрешено перечитывание конфига только из основного потока?
  • Конфигурационные файлы. Библиотека libconfig и определение неиспользуемых настроек
    0
    А как вы работаете с конфигами? Я в разных проектах попробовал 2 разных способа
    1) Все значения из конфига считываются в функции main. И потом раздаются всем необходимым классам. Недостаток: при сложной иерархии классов очень сложно докинуть каждую настройку до нужного класса
    2) Каждый класс берет из конфига ровно те настройки, которые ему нужны. Пока склоняюсь к такому варианту, но, возможно в нем есть какието минусы
  • Я больше не хочу работать, никогда и ни над чем. Но из меня научились выжимать результаты
    0
    А вы где живете? Москва, Питер? Регионы? Если регионы, то какие к черту кредиты с зарплатой 200 штук?