{"id":4839,"date":"2023-01-23T09:14:33","date_gmt":"2023-01-23T08:14:33","guid":{"rendered":"https:\/\/launix.de\/launix\/?p=4839"},"modified":"2023-03-02T10:26:44","modified_gmt":"2023-03-02T09:26:44","slug":"when-the-benchmark-is-too-slow-golang-http-server-performance","status":"publish","type":"post","link":"https:\/\/launix.de\/launix\/en\/when-the-benchmark-is-too-slow-golang-http-server-performance\/","title":{"rendered":"When the benchmark is too slow&#8230; (golang http server performance)"},"content":{"rendered":"\n<p>Just a shmankerl from the daily life of a developer.<\/p>\n\n\n\n<!--more-->\n\n\n\n<p>When I tested memcp performance, I ran into the problem that my benchmark tool was too slow.<\/p>\n\n\n\n<p>The goal was to test golang&#8217;s http server throughput in memcp. The setup is fairly easy: golangs net\/http library opens up a simple http server with a custom handler. The custom handler executes a scheme script that will handle the request. When the path equals &#8220;\/foo&#8221;, a handcoded query on the storage engine (indexed table scan over 9,000 items and print out of 12 result lines) is run.<\/p>\n\n\n\n<p>I decided to use Apache&#8217;s tool <code>ab<\/code> for benchmarking.<\/p>\n\n\n\n<p>This is the result of running ab with 1,000,000 requests:<\/p>\n\n\n\n<pre><font color=\"#26A269\"><b>carli@launix-MS-7C51<\/b><\/font>:<font color=\"#12488B\"><b>~\/projekte\/memcp<\/b><\/font>$ ab -n 1000000 -c 100 http:\/\/localhost:4321\/foo\nThis is ApacheBench, Version 2.3 &lt;$Revision: 1879490 $&gt;\nCopyright 1996 Adam Twiss, Zeus Technology Ltd, http:\/\/www.zeustech.net\/\nLicensed to The Apache Software Foundation, http:\/\/www.apache.org\/\n\nBenchmarking localhost (be patient)\nCompleted 100000 requests\nCompleted 200000 requests\nCompleted 300000 requests\nCompleted 400000 requests\nCompleted 500000 requests\nCompleted 600000 requests\nCompleted 700000 requests\nCompleted 800000 requests\nCompleted 900000 requests\nCompleted 1000000 requests\nFinished 1000000 requests\n\n\nServer Software:        \nServer Hostname:        localhost\nServer Port:            4321\n\nDocument Path:          \/foo\nDocument Length:        432 bytes\n\nConcurrency Level:      100\nTime taken for tests:   31.336 seconds\nComplete requests:      1000000\nFailed requests:        0\nTotal transferred:      535000000 bytes\nHTML transferred:       432000000 bytes\nRequests per second:    31912.48 [#\/sec] (mean)\nTime per request:       3.134 [ms] (mean)\nTime per request:       0.031 [ms] (mean, across all concurrent requests)\nTransfer rate:          16673.02 [Kbytes\/sec] received\n\nConnection Times (ms)\n              min  mean[+\/-sd] median   max\nConnect:        0    1   0.2      1       3\nProcessing:     0    2   0.4      2       7\nWaiting:        0    1   0.4      1       7\nTotal:          0    3   0.4      3       9\n\nPercentage of the requests served within a certain time (ms)\n  50%      3\n  66%      3\n  75%      3\n  80%      3\n  90%      4\n  95%      4\n  98%      4\n  99%      4\n 100%      9 (longest request)<\/pre>\n\n\n\n<p>30,000 requests per second sounds really great, dosen&#8217;t it? But take a closer look at <code>htop<\/code><\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/launix.de\/launix\/wp-content\/uploads\/2023\/01\/Bildschirmfoto-vom-2023-01-23-08-57-39.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"432\" src=\"https:\/\/launix.de\/launix\/wp-content\/uploads\/2023\/01\/Bildschirmfoto-vom-2023-01-23-08-57-39-1024x432.png\" alt=\"\" class=\"wp-image-4840\" srcset=\"https:\/\/launix.de\/launix\/wp-content\/uploads\/2023\/01\/Bildschirmfoto-vom-2023-01-23-08-57-39-1024x432.png 1024w, https:\/\/launix.de\/launix\/wp-content\/uploads\/2023\/01\/Bildschirmfoto-vom-2023-01-23-08-57-39-300x127.png 300w, https:\/\/launix.de\/launix\/wp-content\/uploads\/2023\/01\/Bildschirmfoto-vom-2023-01-23-08-57-39-768x324.png 768w, https:\/\/launix.de\/launix\/wp-content\/uploads\/2023\/01\/Bildschirmfoto-vom-2023-01-23-08-57-39-600x253.png 600w, https:\/\/launix.de\/launix\/wp-content\/uploads\/2023\/01\/Bildschirmfoto-vom-2023-01-23-08-57-39.png 1263w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><\/figure>\n\n\n\n<p>As you can see, <code>ab<\/code> is a single core program. They assume that one CPU core can never generate so much load a web server couldn&#8217;t handle. They were proven wrong. While <code>ab<\/code> gasps at 100% CPU, <code>memcp<\/code> bores himself at 767% CPU load while it could take at least 2,300% \ud83d\ude09<\/p>\n\n\n\n<p>Of course this benchmark does not cover the true <code>memcp<\/code>s performance. For this, the following subsystems have to be implemented first and of course will drag performance further down:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>User\/Request authentication<\/li>\n\n\n\n<li>SQL parsing<\/li>\n\n\n\n<li>SQL optimization<\/li>\n\n\n\n<li>JSON encoding of the results (in the moment, we do a simple string concatenation)<\/li>\n<\/ul>\n\n\n\n<p>What it shows indeed is that you have to take measurement results with a grain of salt. Sometimes, it&#8217;s not the system that is wrong but your measurement method.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Just a shmankerl from the daily life of a developer.<\/p>","protected":false},"author":2,"featured_media":4840,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_editorskit_title_hidden":false,"_editorskit_reading_time":0,"_editorskit_is_block_options_detached":false,"_editorskit_block_options_position":"{}","_uag_custom_page_level_css":"","footnotes":""},"categories":[129,128],"tags":[],"class_list":["post-4839","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-memcp","category-programming","single-item"],"featured_image_urls_v2":{"full":["https:\/\/launix.de\/launix\/wp-content\/uploads\/2023\/01\/Bildschirmfoto-vom-2023-01-23-08-57-39.png",1263,533,false],"thumbnail":["https:\/\/launix.de\/launix\/wp-content\/uploads\/2023\/01\/Bildschirmfoto-vom-2023-01-23-08-57-39-150x150.png",150,150,true],"medium":["https:\/\/launix.de\/launix\/wp-content\/uploads\/2023\/01\/Bildschirmfoto-vom-2023-01-23-08-57-39-300x127.png",300,127,true],"medium_large":["https:\/\/launix.de\/launix\/wp-content\/uploads\/2023\/01\/Bildschirmfoto-vom-2023-01-23-08-57-39-768x324.png",751,317,true],"large":["https:\/\/launix.de\/launix\/wp-content\/uploads\/2023\/01\/Bildschirmfoto-vom-2023-01-23-08-57-39-1024x432.png",751,317,true],"1536x1536":["https:\/\/launix.de\/launix\/wp-content\/uploads\/2023\/01\/Bildschirmfoto-vom-2023-01-23-08-57-39.png",1263,533,false],"2048x2048":["https:\/\/launix.de\/launix\/wp-content\/uploads\/2023\/01\/Bildschirmfoto-vom-2023-01-23-08-57-39.png",1263,533,false],"trp-custom-language-flag":["https:\/\/launix.de\/launix\/wp-content\/uploads\/2023\/01\/Bildschirmfoto-vom-2023-01-23-08-57-39.png",18,8,false],"xs-thumb":["https:\/\/launix.de\/launix\/wp-content\/uploads\/2023\/01\/Bildschirmfoto-vom-2023-01-23-08-57-39-64x64.png",64,64,true],"appku-shop-single":["https:\/\/launix.de\/launix\/wp-content\/uploads\/2023\/01\/Bildschirmfoto-vom-2023-01-23-08-57-39.png",620,262,false]},"post_excerpt_stackable_v2":"<p>Just a shmankerl from the daily life of a developer. When I tested memcp performance, I ran into the problem that my benchmark tool was too slow. The goal was to test golang&#8217;s http server throughput in memcp. The setup is fairly easy: golangs net\/http library opens up a simple http server with a custom handler. The custom handler executes a scheme script that will handle the request. When the path equals &#8220;\/foo&#8221;, a handcoded query on the storage engine (indexed table scan over 9,000 items and print out of 12 result lines) is run. I decided to use Apache&#8217;s&hellip;<\/p>\n","category_list_v2":"<a href=\"https:\/\/launix.de\/launix\/en\/category\/memcp\/\" rel=\"category tag\">MemCP<\/a>, <a href=\"https:\/\/launix.de\/launix\/en\/category\/programming\/\" rel=\"category tag\">Programming<\/a>","author_info_v2":{"name":"Carl-Philip H\u00e4nsch","url":"https:\/\/launix.de\/launix\/en\/author\/carli\/"},"comments_num_v2":"0 comments","uagb_featured_image_src":{"full":["https:\/\/launix.de\/launix\/wp-content\/uploads\/2023\/01\/Bildschirmfoto-vom-2023-01-23-08-57-39.png",1263,533,false],"thumbnail":["https:\/\/launix.de\/launix\/wp-content\/uploads\/2023\/01\/Bildschirmfoto-vom-2023-01-23-08-57-39-150x150.png",150,150,true],"medium":["https:\/\/launix.de\/launix\/wp-content\/uploads\/2023\/01\/Bildschirmfoto-vom-2023-01-23-08-57-39-300x127.png",300,127,true],"medium_large":["https:\/\/launix.de\/launix\/wp-content\/uploads\/2023\/01\/Bildschirmfoto-vom-2023-01-23-08-57-39-768x324.png",751,317,true],"large":["https:\/\/launix.de\/launix\/wp-content\/uploads\/2023\/01\/Bildschirmfoto-vom-2023-01-23-08-57-39-1024x432.png",751,317,true],"1536x1536":["https:\/\/launix.de\/launix\/wp-content\/uploads\/2023\/01\/Bildschirmfoto-vom-2023-01-23-08-57-39.png",1263,533,false],"2048x2048":["https:\/\/launix.de\/launix\/wp-content\/uploads\/2023\/01\/Bildschirmfoto-vom-2023-01-23-08-57-39.png",1263,533,false],"trp-custom-language-flag":["https:\/\/launix.de\/launix\/wp-content\/uploads\/2023\/01\/Bildschirmfoto-vom-2023-01-23-08-57-39.png",18,8,false],"xs-thumb":["https:\/\/launix.de\/launix\/wp-content\/uploads\/2023\/01\/Bildschirmfoto-vom-2023-01-23-08-57-39-64x64.png",64,64,true],"appku-shop-single":["https:\/\/launix.de\/launix\/wp-content\/uploads\/2023\/01\/Bildschirmfoto-vom-2023-01-23-08-57-39.png",620,262,false]},"uagb_author_info":{"display_name":"Carl-Philip H\u00e4nsch","author_link":"https:\/\/launix.de\/launix\/en\/author\/carli\/"},"uagb_comment_info":0,"uagb_excerpt":"Just a shmankerl from the daily life of a developer.","_links":{"self":[{"href":"https:\/\/launix.de\/launix\/en\/wp-json\/wp\/v2\/posts\/4839","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/launix.de\/launix\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/launix.de\/launix\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/launix.de\/launix\/en\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/launix.de\/launix\/en\/wp-json\/wp\/v2\/comments?post=4839"}],"version-history":[{"count":2,"href":"https:\/\/launix.de\/launix\/en\/wp-json\/wp\/v2\/posts\/4839\/revisions"}],"predecessor-version":[{"id":4846,"href":"https:\/\/launix.de\/launix\/en\/wp-json\/wp\/v2\/posts\/4839\/revisions\/4846"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/launix.de\/launix\/en\/wp-json\/wp\/v2\/media\/4840"}],"wp:attachment":[{"href":"https:\/\/launix.de\/launix\/en\/wp-json\/wp\/v2\/media?parent=4839"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/launix.de\/launix\/en\/wp-json\/wp\/v2\/categories?post=4839"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/launix.de\/launix\/en\/wp-json\/wp\/v2\/tags?post=4839"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}