"PHP" / Говнокод #27104 Ссылка на оригинал

0

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  10. 10
  11. 11
  12. 12
  13. 13
  14. 14
  15. 15
  16. 16
  17. 17
  18. 18
  19. 19
  20. 20
  21. 21
  22. 22
  23. 23
  24. 24
  25. 25
  26. 26
  27. 27
  28. 28
  29. 29
  30. 30
  31. 31
  32. 32
  33. 33
  34. 34
https://habr.com/ru/company/vk/blog/527420/

ВКонтакте снова выкладывает KPHP 

....

Сгенерировать С++ из PHP — этого мало. Собственно говоря, это самое простое.

Во-первых, в PHP мы используем кучу функций стандартной библиотеки: header(),
 mb_strlen(), curl_init(), array_merge(). Их тысячи — и все должны быть
реализованы внутри KPHP с учётом типизации и работать так же, как в PHP.
Реализация всего PHP stdlib (а также KPHP-дополнений), всех PHP-типов с
операциями и допущениями — это называется runtime, вон там квадратик сверху.

Во-вторых, PHP-сайт — это веб-сервер. Следовательно, и в KPHP должна быть вся
серверная часть, чтобы можно было в том же nginx подменить PHP-шный upstream
на KPHP-шный — и всё продолжало работать так же. KPHP поднимает свой веб-сервер,
оркестрирует процессы, заполняет суперглобалы и переинициализирует состояние,
как и PHP… Это тоже хардкорная часть — называется server, квадратик снизу.

И только имея результирующий код C++, написанные runtime и server, всё это можно
объединить и отдать на откуп плюсовым компиляторам. Мы используем g++ — там в
диаграмме есть квадратик g++. Но не совсем так: у vk.com настолько огромная
кодовая база, что этот компилятор не справляется, и поэтому мы применяем патченный
distcc для параллельной компиляции на множестве агентов. В итоге всё линкуется в
один огромный бинарник (это весь vk.com), он раскидывается на кучу бэкендов и
синхронно перезапускается. Каждая копия запускает мастер-процесс, который порождает
группу однопоточных воркеров. Вот они на самом деле и исполняют исходный PHP-код.

Многие технические проблемы остаются за кадром — их не опишешь в статье на Хабре.
Чего стоит один только сбор трейсов при ошибках: ведь в С++ не получить
человекочитаемый стек, а хочется разработчику вообще его на PHP-код намаппить.
Гигантское количество внутренних нюансов, множество подпорок и легаси — но в итоге
продукт хорошо работает и развивается.

PHP и C++... два говна нашли друг друга

Запостил: j123123 j123123, (Updated )

Комментарии (46) RSS

  • https://github.com/VKCOM/kphp/blob/master/runtime/datetime.cpp#L682

    if (s[0] == '-' || (s[0] == '+' || ('0' <= s[0] && s[0] <= '9'))) {
          int cnt;
          pos = -1;
          if (sscanf(s.c_str(), "%d%20s %n", &cnt, str, &pos) == 2 && pos != -1) {
            bool error = false;
            switch (str[0]) {
              case 'd':
                if (str[1] == 'a' && str[2] == 'y' && ((str[3] == 's' && str[4] == 0) || str[3] == 0)) {
                  t.tm_mday += cnt;
                  break;
                }
                error = true;
                break;
              case 'h':
                if (str[1] == 'o' && str[2] == 'u' && str[3] == 'r' && ((str[4] == 's' && str[5] == 0) || str[4] == 0)) {
                  t.tm_hour += cnt;
                  break;
                }
                error = true;
                break;
              case 'm':
                if (str[1] == 'o' && str[2] == 'n' && str[3] == 't' && str[4] == 'h' && ((str[5] == 's' && str[6] == 0) || str[5] == 0)) {
                  t.tm_mon += cnt;
                  break;
                }
                if (str[1] == 'i' && str[2] == 'n' && str[3] == 'u' && str[4] == 't' && str[5] == 'e' && ((str[6] == 's' && str[7] == 0) || str[6] == 0)) {
                  t.tm_min += cnt;
                  break;
                }
                error = true;
                break;
              case 'w':
                if (str[1] == 'e' && str[2] == 'e' && str[3] == 'k' && ((str[4] == 's' && str[5] == 0) || str[4] == 0)) {
                  t.tm_mday += cnt * 7;
                  if (!strncmp(s.c_str() + pos, "1 day", 5)) {
                    t.tm_mday += (s[0] == '+' ? 1 : -1);
                    pos += 5;
                    while (s[pos] == ' ') {
                      pos++;
                    }
                  }
                  break;
                }
                error = true;
                break;


    ухх бля, вот сразу видно, чувствуется рука вконтактовского олимпиадника
    Ответить
    • Ну напиши сам эту функцию и выложи её сюда. Посмотрим, потечём.
      Ответить
  • > if (str[1] == 'o' && str[2] == 'n' && str[3] == 't' && str[4] == 'h' && ((str[5] == 's' && str[6] == 0) || str[5] == 0))

    никогда не берите на работу олимпиадников и пыхеров

    Кстати, надо бы Ротоёбу присоветовать ВК в качестве работы: он примерно в таком же стиле пишет, правда на пхп, но там и пхп такой же ведь
    Ответить
      • там бекенд с алгоритмами на сишке, веб морда на пыхе, а потом они стали пых в сишку компилировать (по аналогии с фейсбуком)
        Ответить
      • Сам вконтакт написан-таки не совсем на пхп, а на особом подмножестве пхп, который через вот эту ебаную срань как-то компилируется в C++ и запускается. Подробности см. на хабре.
        Ответить
  • https://github.com/VKCOM/kphp/blob/04819c075f5599582f4f8780775f26a6377ca05d/runtime/string_functions.cpp#L375


    string f$html_entity_decode(const string &str, int64_t flags, const string &encoding) {
      if (flags >= 3) {
        php_critical_error ("unsupported parameter flags = %ld in function html_entity_decode", flags);
      }
    
      bool utf8 = memchr(encoding.c_str(), '8', encoding.size()) != nullptr;
      if (!utf8 && strstr(encoding.c_str(), "1251") == nullptr) {
        php_critical_error ("unsupported encoding \"%s\" in function html_entity_decode", encoding.c_str());
        return str;
      }
    
      int len = str.size();
      string res(len * 7 / 4 + 4, false);
      char *p = &res[0];
      for (int i = 0; i < len; i++) {
        if (str[i] == '&') {
          int j = i + 1;
          while (j < len && str[j] != ';') {
            j++;
          }
          if (j < len) {
            if ((flags & ENT_QUOTES) && j == i + 5) {
              if (str[i + 1] == '#' && str[i + 2] == '0' && str[i + 3] == '3' && str[i + 4] == '9') {
                i += 5;
                *p++ = '\'';
                continue;
              }
            }
            if (!(flags & ENT_NOQUOTES) && j == i + 5) {
              if (str[i + 1] == 'q' && str[i + 2] == 'u' && str[i + 3] == 'o' && str[i + 4] == 't') {
                i += 5;
                *p++ = '\"';
                continue;
              }
            }
    
            int l = 0, r = entities_size;
            while (l + 1 < r) {
              int m = (l + r) >> 1;
              if (strncmp(str.c_str() + i + 1, ent_to_num_s[m], j - i - 1) < 0) {
                r = m;
              } else {
                l = m;
              }
            }
            if (strncmp(str.c_str() + i + 1, ent_to_num_s[l], j - i - 1) == 0) {
              int num = ent_to_num_i[l];
              i = j;
              if (utf8) {
                if (num < 128) {
                  *p++ = (char)num;
                } else if (num < 0x800) {
                  *p++ = (char)(0xc0 + (num >> 6));
                  *p++ = (char)(0x80 + (num & 63));
    ...

    Не, ну что это за пиздец?
    Ответить
    • почти что число кармака по крутости, лол

      Причм мне нравится, как ловко смешана весьма "высокоуровневая" крестушня типа std::string и
      *p++ = (char)(0xc0 + (num >> 6));
      *p++ = (char)(0x80 + (num & 63));
      Ответить
      • > utf8

        Настоящий олимпиадник инлайнит функции сам, не доверяя это конпелятору.
        Ответить
    • Блядь, они серьёзно детектят utf8 по наличию цифры 8 в названии кодировки?

      За каким хуем это вообще строка, если там джва допустимых значения. А ещё этот код вызывается на каждую энтитю, заебись для пирфоманса.
      Ответить
        • Ну там заебешься все кобенации перебирать:
          UTF8
          utf8
          UTF-8
          utf-8
          Utf-8
          и так далее

          Проще на восьмерку проверить.
          Ответить
          • Ну тогда так: int is_utf8 = enc[enc.size() - 1] == '8'. И быстрее и точнее чем их говно.
            Ответить
            • Можно даже так: int is_utf8 = enc[4] == '8'

              Если судить из документации соотв. функции в "PHP", для UTF-8 кодировки корректно только "UTF-8" в качестве параметра
              А вот у "cp1251" есть псевдонимы "Windows-1251", "win-1251", "1251". Т.е. достаточно просто проверять четвертый символ на восьмерку
              Ответить
                • Тогда можно и на основе длины решить. Если длина равна 5 то тогда это "UTF-8", иначе это "cp1251". Ни один из синонимов "cp1251" не имеет длину 5
                  Ответить
              • Ну да, у koi8-r и cp866 восьмёрки в другой позиции. А остальные кодировки в русском проекте маловероятны.
                Ответить
              • switch (strchr(s, '8') - s) {
                case 2: // cp866
                case 3: // koi8-r
                case 4: // utf-8
                default: // cp1251
                }
                Ответить
        • Ну и нахуй тогда проверять на 1251 в следующей строке? И так же понятно, что раз восьмёрки нет - то 1251. А на koi8-r и cp866 всё равно глючит и не возвращает ошибку.
          Ответить
          • Отличная оптимизация. Ждем вас в команду вконтакта!
            Ответить
            • Я там выше оптимизнул лучше. Последний символ на 8 проверить. Такое вроде только в утф.
              Ответить
  • > ВКонтакте снова выкладывает KPHP

    обиделись что в прошлый раз никто не заметил?

    > KPHP берёт PHP-код и превращает его в С++

    ребят, тайпскрипт не так работает
    Ответить
    • > обиделись что в прошлый раз никто не заметил?

      Почему никто? Я заметил. На говнокод даже отправлял куски кода оттуда
      Ответить
        • Да оно просто нинужно за пределами ВК.

          Судя по статье, 99% существующего кода там тупо не взлетит т.к. все динамические фишки не поддерживаются. Не заюзать привычные экстеншены для СУБД, не запустить привычные фреймворки и ORM'ы.

          Т.е. нельзя взять и портировать свои PHP'шные наработки на K-PHP. Код нужно снуля разрабатывать специально под эту платформу.

          З.Ы. Хотя код Ротоёба, наверное, взлетит. Если поддержку mysql самостоятельно привернуть.
          Ответить
  • > мы тестируем на PHP а KPHP - для продакшена

    Заебись наверное отлаживать ситуации, когда в обычном пхп всё работает а на кпхп крашится.
    Ответить
    • Это уже забота отдела разработки кпхп.
      Ответить
    • это ж какой багор, когда твой код даже пхп нормально выполняет, а твоя поделка не может )))
      Ответить
  • - Вы далеко собрались, сын мой? - тут же вдогонку окликнул его Джим, - пойди лучше сушняка насобирай на костерок.
    Ответить

Добавить комментарий

Помни, guest, за тобой могут следить!

    А не использовать ли нам bbcode?


    8