Често неосъзнати проблеми и решения


Борислав Станимиров / @stanimirovb

Hello, World



  #include <iostream>

  int main()
  {
      std::cout << "Здравейте, аз съм Борислав!\n";
      std::cout << "Тези слайдове са тук: https://is.gd/unrealizedv1\n";
      return 0;
  }
        

Борислав Станимиров


  • Предимно C++ програмист
  • 2006-2018 програмист на игри
  • От 2019 медицински софтуер
  • Софтуер с отворен код
  • github.com/iboB


Блог пост за това какво правим там: ibob.bg/blog

Характеристики на софтуерен проект


  • Коректност
  • Производителност
  • Ефективност на разработка

... и още

  • Сигурност
  • Дизайн
  • UX
  • ...

Характеристики на софтуерен проект


  • Коректност
  • Производителност
  • Ефективност на разработка

Аналогията с мениджърския триъгълник е възможна

Проблеми

Коректност: бъгове

Производителност: бавности

Ефективност на разработка: некачествен код

Мета-проблеми

няма да се занимаваме с тях

Често имаме от всичко по малко

😞

Осъзнати проблеми

Имаме избор

Да ги решаваме

... което не винаги е възможно или практично

Да ги оставим съзнателно

Неосъзнати проблеми

Тази презентация


  • Няколко често неосъзнати проблема
  • Arms race в неосъзнатите проблеми и презентациите
  • Когато един проблем се окаже често неосъзнат, започва да се говори повече за него и той става често осъзнат
  • Може би има до болка известни неща
  • Може би има неща, които никой не среща
  • ...по-скоро първото

But that's just, like, my opinion, man

Неосъзнати бъгове


  • Най-често срещаният проблем
  • Има безкрайно много материали по темата
    • Unit tests
    • Integration tests
    • TDD
    • ...
  • Няма да се занимаваме с тях

Неосъзнати бавности


  • Водещата подтема
  • C++ е перфектната среда за тях
  • Често бързодействието е водещо
  • Езикът може да крие много

Неосъзнат лош код


  • По-често „непризнат“ отколкото неосъзнат
    • Design patterns
    • Clean code, SOLID
    • Modern C++
    • Build times
    • Build systems
    • Package managers
  • Ще бъде слабо засегнато (но не нула)

Неволно копиране


  class big_obj {
  public:
    big_obj();
    big_obj(const big_obj&);
    big_obj& operator=(const big_obj&);
    big_obj(big_obj&&);
    big_obj& operator=(big_obj&&);
  private:
    big_data m_data;
  };
  // ...
  std::vector<big_obj> objects;
  // ...
  objects.push_back(std::move(new_object));
        

Какъв е проблемът тук?

std::vector използва std::move_if_noexcept


  class big_obj {
  public:
    big_obj();
    big_obj(const big_obj&);
    big_obj& operator=(const big_obj&);
    big_obj(big_obj&&) noexcept;
    big_obj& operator=(big_obj&&) noexcept;
  private:
    big_data m_data;
  };
  // ...
  std::vector<big_obj> objects;
  // ...
  objects.push_back(std::move(new_object));
        

Демо

За протокола:

Aз мисля, че exception от move-constructor е пълна глупост и никога не трябва да съществува

Една история със std::function


  struct simple_struct {
      std::function<void(int)> func;
      std::vector<int> data; // call func with each element in data
  };
  //...
  std::vector stuffs;
  • Дотук всичко си работи
  • Дебъгвам си нещо несвързано и изведнъж съм във vector::vector(const vector&)

😲

std::function

  • До C++20 не е задължително noexcept-move
  • Small-function optimization
    • Без алокации за малки функции
    • Move трябва да премести и всички captures
    • ... които може да не са noexcept-move
  • В нови версии на libc++ и libstdc++ работи и със C++11
    • Ползваме буфера, само ако можем да местим с noexcept
  • Демо

ufunction

itlib::ufunction


  • gh/iboB/itlib/ufunction.hpp
  • Вероятно съществуват и други имплементации
  • Тънка опаковка на std::function
  • Unique Function
    • noexcept move constructible
    • non-copyable
  • ... от което произлезе бонус: capture non-copyable data

          auto pfoo = std::make_unique<foo>
          itlib::ufunction<void()> func = [p = std::move(pfoo)]() mutable {
            // ...
            consumer.consume(std::move(pfoo));
          }
          push_task(func)
        

Демо

Според мен в почти всички случаи std::function

може да бъде заменена с ufunction

И след като говорихме за small function optimization...

small_vector

small_vector


  • Вектор със small-buffer optimization
  • boost::small_vector - супер мощна имплементация
  • itlib::small_vector
    • 90% от работата с 10% от кода
    • Без std::move_if_noexcept
  • Контейнери, които са с размер по-малък от N в 99% от времето
  • ...и тогава нямаме алокации
  • Демо – за домашно

Ами ако размерът е по-малък от N в 100% от времето?

std::array

?

std::array


  • Когато размерът е равен на N в 100% от времето
  • Фиксиран размер
  • Помощно число за реален размер?
  • Трябва да конструираме всички елементи
  • Ами ако типът е POD?
  • При копиране копираме всички елементи
  • Демо

static_vector

small_vector


  • Вектор с фиксиран капацитет
  • boost::static_vector - супер мощна имплементация
  • itlib::static_vector
    • 90% от работата с 10% от кода
    • Без std::move_if_noexcept
  • Без алокации
  • Копираме само каквото трябва
  • Демо

Ами ако размерът напълно произволен?

std::vector

?

realloc

Имаме памет:

x=malloc(3); x=realloc(x, 6); ++end x=realloc(x, 9); memcpy

std::vector и realloc


  • memcpy пропуска конструкторите и деструкторите
  • Windows-only: _expand
  • Ами ако не ни пука за конструкторите и деструкторите?

pod_vector

itlib::pod_vector


  • Когато не ни пука за конструкторите и деструкторите
  • gh/iboB/itlib/pod_vector.hpp
  • Вероятно съществуват и други имплементации
  • Паметта се джурка с realloc, memcpy и memmove
  • Значително подобрява Debug performance
  • Recast
  • Демо

Урок

При custom алокатор извън Windows: търсете _expand

optimal_alloc_vector

Ами сега?

Имаме сто вида вектор. Как да напишем алгоритъм?

void work(const std::vector<obj>& data);

вече не работи

Темплейтите, естествено, работят, но си имат цена.

span, memory_view

span, memory_view


Бонус


  • gh/iboB/itlib
    • flat_map, flat_set - map with cache locality
    • sentry - finally-type blocks
    • Има и други, по-нишови работи
  • gh/cpm-cmake/CPM.cmake - пакети с одобрение от мен™
  • gh/iboB/mscharconv - charconv за пещерняци

Край

Въпроси?

Борислав Станимиров / ibob.bg / @stanimirovb

Тези слайдове: ibob.bg/slides/unrealized-alpha/
Демо код: github.com/iboB/unrealized-problems-demo
Лиценз на слайдовете Creative Commons By 4.0
Creative Commons License