Крупная корпорация, выпустившая библиотеку C ++ 11 в 2017 году, выглядит смешной неудачей, чтобы «быть в курсе всех остальных». Неожиданно Google Abseil - хорошая библиотека сама по себе, и в качестве примера некоторых передовых методов могут быть приняты другие библиотеки.

Как сделать вашу библиотеку C ++ неубедительной

Официальная страница не только пропускает некоторые сильные стороны Abseil, но и приветствует пользователя

  • Live at Head - звучит круто, я полагаю, поскольку я понятия не имею, что это значит
  • Наша библиотека для вас, если вы застряли на C ++ 11 - вау, очень интересно
  • «Контракт» между Abseil и пользователями - полезный, но увлекательный, как чтение документации
  • На основе производственного кода Google - наконец-то что-то полезное, может быть, вы могли бы поставить это выше в списке?

Трудно предположить, почему Abseil так себя представляет миру, но я предполагаю, что для людей внутри Google приоритеты выглядят иначе, чем у среднего разработчика, который рассматривает возможность использования Abseil.

Сильные стороны Abseil для разработчиков на C ++ 17

На мой взгляд, Abseil - важная библиотека, которую следует учитывать, даже если вы используете последнюю версию компилятора, поэтому в следующих нескольких главах я объясню, почему вы должны разделять мое мнение.

Примечание: это не учебник Abseil, Abseil в отличие от многих библиотек C ++ имеет хорошо документированный код (или хорошо прокомментированный код, поскольку AFAIK, например, контейнерные алгоритмы не документированы - кстати, я рекомендую их, просто попробуйте запомнить разницу между absl :: c_equal и std :: equal).

Abseil удобен для пользователя

Среди множества комплиментов С ++ получил один, который я использую (если никто этого не сказал до того, как я заявлю о создании! 😜):

C ++ похож на язык без менеджера по продукту

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

Есть еще много подобных ситуаций, когда вы можете создать что-то на C ++, но задаетесь вопросом, почему вы должны это делать (а ответ часто - «потому что никто не написал предложения» (tm) 😃).

Abseil прыгает сюда с кодом, похожим на контейнерную версию ‹algorithm›. Никакого сложного метапрограммирования, просто глупая функция absl :: c_bla, которая расширяет контейнер до двух итераторов и вызывает std :: bla.

Вы можете считать это скучным. Это скучно, но также удобно.

То же самое и со строковыми функциями, такими как absl :: StrJoin. Я могу реализовать примитивную версию чего-то подобного, когда мне это нужно. Но, наконец, мне не нужно этого делать.

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

Abseil оптимизирован

Если вы покопаетесь в исходниках Abseil, вы найдете впечатляющие приемы микроптимизации. Хотя у меня не было времени протестировать Abseil со всеми возможными конкурирующими библиотеками со всеми возможными входными данными, я выполнил тесты absl :: StrCat vs to_string для 32-битного целого числа (int). StrCat был на 20% быстрее, чем MSVC std :: to_string, и в 3 раза быстрее, чем MinGW std :: to_string (обратите внимание, что оптимизация с помощью профиля помогла моему тесту, но относительная разница осталась).

Почему я должен утверждать, что 20% - это впечатляюще? Хотя полезность ускорения зависит от того, нужно оно вам или нет (даже 5-кратное ускорение кода, который использует 0,002% вашего процессора, бесполезно), здесь absl :: StrCat впечатляет, потому что если вы знаете Стандарт, вы знаете, что std :: to_string для целое число должно использовать античную функцию C (sprintf). Если ты можешь победить в спринте, ты в моей книге крутой.

Одна любовь, одна жизнь, одна…

Время викторины 😄

Сравнительный анализ сглаживания вектора ‹string› (4M строк средней длины 50 (размеры варьируются от 0 до 100) в одну строку показал, что absl :: StrJoin в 1,5–2 раза быстрее, чем наивный цикл for, который использует + = для построения результирующей строки. Вы можете объяснить почему. [Подсказка: заголовок абзаца 😉]

В отличие от std :: string operator +, который имеет ограниченные знания о мире (этот и другие std :: string), absl :: StrJoin гораздо лучше осведомлен о мире. Он знает, как определить, как долго будет полученный std :: string до начала конкатенации. Он суммирует размеры всех входных строк и вызывает резерв для результирующей строки. Один резерв. 😃 Оператор + не имеет возможности для этого, поэтому для наших тестов происходит перераспределение.

Внимательный читатель может задаться вопросом, зачем нам указывать, что наши строки имеют определенную длину. Причина в том, что просмотр строк для вычисления общего размера имеет определенную стоимость, и это имеет смысл только в том случае, если мы сэкономим достаточно времени на выделение и перераспределение памяти. Таким образом, для очень коротких или пустых строк absl :: StrJoin работает медленнее, чем наивное выравнивание.

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

Если вам интересно, используется ли это реализацией STL, ответ - да. Например, вставка std :: vector, которая принимает 2 итератора (диапазон элементов), пройдет через этот диапазон и затем выполнит ту же оптимизацию, что и absl :: StrJoin.

Стандарт можно исправить, чтобы частично поддерживать такую ​​оптимизацию. Для выравнивания контейнера (имеющего размер во время выполнения) я понятия не имею, как язык может здесь помочь. Для конкатенации фиксированного количества строк здесь может помочь вариативный оператор + (чтобы строка могла перебирать все другие строки и получать их размеры). Но я не уверен, что это стоит затрат (любое изменение основного языка стоит дорого с точки зрения того, сколько времени требуется на его разработку и реализацию - также помните, что вы можете добавить char * в строку, поэтому это будет довольно сложно) .

Что я считаю спорным в Abseil?

  • не большой поклонник бэкпорта таких вещей, как std :: string_view, но вы можете использовать Abseil без использования absl :: string_view.
  • именование - absl :: StrJoin вместо absl :: strings :: Join. Я предпочитаю решение Abseil, но считаю его спорным.
  • синтаксис вызова функции вместо использования + для объединения 4 строк уродлив, но, как мы видели, необходим по соображениям производительности
  • Abseil небольшой - несмотря на то, что я не упомянул некоторые большие части библиотеки в этой статье, я все же считаю всю библиотеку слишком маленькой для моих жадных стандартов.

Заключительные мысли

Я очень надеюсь, что вы обнаружили, что Abseil не такой, как вы предполагали до того, как начали читать эту статью. Если вы хотите использовать его или нет, решать вам, я надеюсь, что помог вам принять осознанное решение. 😄