Java vs GO. Тестирование большим числом пользователей

Мотивация


Микросервисная архитектура позволяет выбирать между технологиями и языками программирования при написании REST api сервисов. Какой язык лучше выбрать, для написании REST api приложения, чтобы обеспечить большее количество одновременных пользователей быстрым и стабильным ответом на одном и том же железе? Чтобы ответить на этот вопрос было бы хорошо увидеть разницу в производительности одного и того же приложения написанного на Java и GO.

Дисклеймер


Все результаты представленные в данном эксперименте являются частным примером использования Java и GO и не должны использоваться для описания производительности этих языков в других условиях.

Условия/Ограничения


  • Никаких дополнительных настроек по увеличению производительности. Фреймворки и библиотеки должны использоваться с настройками по-умолчанию.
  • Никаких ORM фреймворков. Только драйвера баз данных и одинаковые запросы в обоих приложениях.

План


  1. Создадим два простых REST api приложения на Java и GO c PostgreSQL базой данных
  2. Создадим нагрузочные тесты при помощи Jmeter
  3. Запустим каждое приложение, базу и тесты на отдельных AWS экземплярах
  4. Прогоним тесты и соберем результаты

Тестируемое приложение


В качестве системы для тестирования я создал два приложения: bank-java и bank-go. Это наверное самое простое банк-приложение в мире. Все что оно умеет делать это создавать новых клиентов с начальным балансом, переводить средства от одного клиента другому и показывать баланс.
API:

  • Post /client/new/{balance} — создает клиента с начальным балансом
  • Post /transaction — переводит средства от одного клиента другому
  • Get /client/{id}/balance — показывает баланс

Фреймворки и библиотеки


При выборе тех стэка я использовал самые новые, популярные и простые фреймворки и библиотеки, чтобы как можно быстрее реализовать нужный функционал.
Bank-java: Java 11, spring boot 2.0.4, spring-web 5.0.8, PostgreSQL JDBC 4.2.4
Bank-go: Go 1.8, gorilla/mux, github.com/lib/pq

Тестовая среда


В качестве тестовой среды был использован AWS.

Следующие EC2 экземпляры были созданы:

  1. Bank-go t2.micro (Variable ECUs, 1 vCPUs, 2.5 GHz, Intel Xeon Family, 1 GiB memory, EBS only)
  2. Bank-java t2.micro (Variable ECUs, 1 vCPUs, 2.5 GHz, Intel Xeon Family, 1 GiB memory, EBS only)
  3. Postgres d2.xlarge (14 ECUs, 4 vCPUs, 2.4 GHz, Intel Xeon E52676v3, 30.5 GiB memory, 3 x 2048 GiB Storage Capacity)
  4. Bank-test t2.2xlarge (Variable ECUs, 8 vCPUs, 2.3 GHz, Intel Broadwell E5-2686v4, 32 GiB memory, EBS only)

Все экземпляры используют Ubuntu Server 18.04 LTS (HVM), SSD Volume Type



Тестовый проект


Jmeter тест вызывает каждый API из списка сверху, проверяет что статус ответа равен 200 и тело ответа содержит id. Для каждого приложения я запустил его с числом одновременных пользователей 1000, 2000 и т.д. до 10000.

С полным логом результатов можно ознакомиться здесь.

Агрегированные результаты








Описание результатов


Оба приложения работают отлично при числе пользователей 1000. Начиная с 2000 GO приложение начинает значительно терять в производительности и чуть-чуть в стабильности. У Java этот рубеж начинается с 3000.

Заключение


Используя одно и то же оборудование REST api приложение Java может поддерживать вдвое* больше одновременных пользователей, чем приложение GO с базой данных PostgreSQL.

*Данная цифра верна только при использовании тех же условий испытания что и в данном эксперименте
Share post
AdBlock has stolen the banner, but banners are not teeth — they will be back

More
Ads

Comments 33

    –10
    Ставь лайк если тоже пустил скупую мужскую слезу гордости за родной язык
      +2

      Что бросается в глаза на blank-go:


      • стандартный http сервер;
      • стандартная работа с json.

      Поэтому такие низкие результаты.

      • UFO just landed and posted this here
          0
          Про json: в одном из учебных примеров easyjson давал 50-и кратный прирост производительности.
            +1

            Есть еще такая прелесть без потребности в генераторах кода https://github.com/json-iterator/go

              0

              подтвержу, на реальном проекте так и було. Не 50 конечно, но 25-35 выдавали.

            0

            Интересно было бы посмотреть на графики потребления cpu\ram во время тестирования, и на результаты с прогреввом java версии. В любом случаи спасибо!

              +8
              1. Как можно тестировать производительность, если у вас на каждый чих стоит println?
              2. Зачем каждый раз открывать/закрывать подключение к бд? Еще и формировать строку подключения тоже каждый раз.
              И пара вопросов по коду:
              1. В джаве return client; вернет json?
              2. В чем заклоючалась нестабильность? Кто и какие ошибки выдавал?
                +2
                И еще момент:
                в го у вас:
                db.SetMaxOpenConns(20) // Sane default
                db.SetMaxIdleConns(0)
                db.SetConnMaxLifetime(time.Nanosecond)
                зачем это?
                И покажите такое в джаве, а то я не нашел.
                  +1
                  Подтверждаю, в Java каждый раз создается новое подключение, никаких пулов соединений.
                    0

                    коммент не о том. в го тоже новое подключение на реквест.

                      0

                      потестили как быстро pg открывает коннект, поздравляю

                    +1
                    Интересно сравнение с ванильным NodeJs. Не планируете добавить?
                      +1
                      я использовал самые новые
                      Bank-go: Go 1.8
                        +7
                        есть же нормальные бенчмарки, зачем такое странное сравнение?
                          +4

                          Не верю. Был бы свободный день и Go приложение заработало бы в 5-10 раз быстрее как миниму.


                          Должно быть стыдно делать такие тесты и уж тем более выкладывать как статьи.

                            0
                            Грустно на такое смотреть. Подготовка SQL не используется. Это не сложно совсем, один запрос.
                              +1
                              А теперь выложите сюда pprof с go и вполне может оказаться, что ботлнек — это работа с базой.
                              Алсо, для нагрузочного тестирования есть православные ab / siege.
                                0
                                Elixir вроде как очень хорош в плане нагрузки, его не рассматривали?
                                  0
                                  Мне кажется, что не выиграет. Хотя интересно было бы потестировать. По моему опыту, Elixir больше про стабильность, а не про производительность.

                                  Можно конечно узкие места подправить, скажем нативная JSON либа (jiffy) будет раз в пять быстрее стоковой либы. Если в день через приложение проходят миллионы запросов, разница может оказаться ощутимой.
                                  +1
                                  Of course, I'd also suggest that whoever was the genius who thought it was a good idea to read things create ONE F*CKING BYTE CONNECTION AT A TIME PER REQUEST with system calls TCP handshakes for each byte request should be retroactively aborted. Who the f*ck does idiotic things like that? How did they noty die as babies, considering that they were likely too stupid to find a tit to suck on?

                                  Linus.

                                  Original
                                    0
                                    Жаль, что, скорее всего, больше такого в LKML (или где-либо ещё) не увидишь. Остаётся только перечитывать старенькое и пускать скупую ностальгическую слезу :) Это же просто бесценно.
                                    +1

                                    Вот вам бенчмарки
                                    Только Java и Go. Разные фреймворки/библиотеки. Там ещё можно попереключать тип приложения и тачки.

                                      +3

                                      Ну там же написано, что это "из песочницы", тут же видно, что это не инженерная работа, а кто-то сидел в песочнице во дворе, какой-то злой дядя дал ноут с доступом в интернет и получились такие тесты.


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


                                      А по сути, тут даже комментировать нечего.

                                        0
                                        волновало почему именно такие результаты?
                                        Совершенно правильный камент.
                                        Что очень удивляет, так это дикая разница, особенно на первых шагах (почти в 6 раз!).
                                        Хотя, по сути, здесь нечем тестировать сами языки, т.к. никакой обработки данных в самих ЯП не происходит. Только простейщий прием параметров и отправка сырого запроса в базу. Разница в конкретном тесте должна быть минимальна.
                                        Автор же нагородил целый огород из горилл и джейсонов, что в данном тесте просто съест львиную долю ресурсов, а все должно просто упереться в систему ввода-вывода и в базу.
                                        Сами ЯП тут толком и не тестируются.
                                        0
                                        Как правило такие тесты провести довольно трудно, нужно очень хорошо разбираться в обеих языках. Если же нет то и результат будет плачевным. Да и смысла этой статьи не вижу, подобных пруд пруди, да и с более правильными тестами. А так holy war на ровном месте.
                                          0
                                          Очередной пост, в котором чувак, не разобравшийся нормально в технологии, пытается что то сравнивать
                                            +1
                                            Имея опыт написания роутера для Go могу сказать совершенно точно, что роутер Гориллы по производительности совсем не айс, смысл брать его в бенчмарк не вижу вообще
                                            image
                                              0
                                              Вы бы показали код на GO человеку, умеющиму писать на GO.
                                              Зачем на каждый чих вызывать newDb()?
                                              DB.Close
                                              It is rare to Close a DB, as the DB handle is meant to be long-lived and shared between many goroutines.
                                              Вы бы и в джаве тогда BankPostgresRepository сконфигурили бы как per call.
                                                +1
                                                Вы бы и в джаве тогда BankPostgresRepository сконфигурили бы как per call.

                                                так и сконфигурен)

                                                  0

                                                  А разве спринг по дефолту не синглтоны делает?

                                                    0

                                                    Я вижу сервис и репозиторий — в них происходит инициализация на реквест.

                                                +1
                                                Bank-java: Java 11, spring boot 2.0.4, spring-web 5.0.8, PostgreSQL JDBC 4.2.4

                                                О боже! В этом мире еще остались люди, которые не пишут на Spring Boot и не ассоциируют его со словом Java?

                                                Only users with full accounts can post comments. Log in, please.