📜 ⬆️ ⬇️

Go for IT. Part one

Elusive Go.


Remember the joke about the elusive Joe? Exactly the exclamation “Yes, who needs it!”, Which sounded in the form of the question “ WHY? ”, Was released on Habré for the release of the first stable version of GO 1.

I want to answer this question with a series of articles designed in an unusual format for Habr - in the form of step-by-step joint development of an existing web project - with a lively discussion and addition of functionality. And in order to doubly justify the introduction of the cycle into the “High Performance” hub, we will set ourselves the task of creating not just a “hamster”, but a project that clearly demonstrates habri et orbi the ability to withstand significant natural loads.

Instead of an aperitif: the implementation of the simplest dynamic web application in the Go language works 5–20 times faster than a similar Python implementation. And just two times inferior to the rate of recoil of static Nginx.
')
In this project, in addition to the Go language itself, we will indirectly touch on other (relatively new) technologies of web development - HTML5, CSS3, Redis, MongoDB. I will also try to pull some of the tricks in the field of security and saving on matches from the corners of the long-term memory, which have accumulated a lot over the past fifteen years of work in this field. Make yourself comfortable, have patience and coffee - under the cut "many letters", but this is only the introduction :)

First of all, I want to thank the administration of Habr for the quick response and the creation of the hub dedicated to the Go language. The recognition of a favorite subject is always pleasant, so that the appearance of such a hub and the arising interest of the audience prompted me for the first time in two years of being at Habré to “take up drafts”.

In addition, I apologize in advance for a somewhat old-fashioned style of presentation, skipping bearded terms, some tongue-tied speech and skipping paraphrasing of catch phrases in a long-dead language - i.e. for the habits that I inherited from my legal background.

Hardness and prejudice

On tastes, as you know, do not argue. Therefore, I have to leave behind the scenes my exclamations about the beautiful syntax, simplicity and elegance of the Go language. The last thing I would like to see in the comments is another battle of blunt and pointed. On this basis, I propose to speak exclusively about matters that are subject to simple and understandable measurement. But even comparing numbers, I will have to compare with other languages, which can also be perceived as casus belli. I thought for a long time how to get out of this delicate situation, and the decision seems to me quite solomon. I will compare it with another favorite language, with Python. This approach, it seems to me, will relieve me from accusations of bias. So let's write it in black and white and in bold letters: I also love Python !

I do not want to repeat banal paragraphs from the documentation, describing the language itself, its philosophy and possibilities. I will proceed from the fact that you are already interested and at the same time are able to read the documentation yourself.

Go to the barrier, Go! To the barrier!

Let's start with a comparison that I intimidated you in the previous paragraph. We write two primitive dynamic applications that:

  1. launch webserver
  2. have routing and handler
  3. take variable from context
  4. substitute it in the handler and issue a personalized greeting Hello,% s.


Nothing complicated, but this is not static content, albeit with some cunning. I foresee many objections to the fact that the main brakes will still be disk operations and work with the database. And I do not argue with that. But let's remember about the announced content of the article. We’ll still get to optimize i / o and db, but for now let's look at the figures for the net speed of responses.

1. Application code for Webapp2.py - a very simple and fast Paste-based mini-framework:

  import webapp2
 class Hello (webapp2.RequestHandler):
     def get (self, name):
         self.response.write ('Hello,% s!'% name)
 app = webapp2.WSGIApplication ([
     ('/ (\ w +)', Hello),
 ], debug = False)
 def main ():
     from paste import httpserver
     httpserver.serve (app, host = '127.0.0.1', port = '8080')
 if __name__ == '__main__':
     main () 

Launch code: python habr.py

2. Go language code:
  package main
 import (
     fmt
     "net / http"
 )
 func handler (w http.ResponseWriter, r * http.Request) {
     fmt.Fprintf (w, "Hello,% s!", r.URL.Path [1:])
 }
 func main () {
     http.HandleFunc ("/", handler)
     http.ListenAndServe (": 8080", nil)
 } 

Launch code: go run habr.go

Nothing complicated, right? Notice how simple and understandable the Go code is, at least for such a simple task. Both listings show the same algorithm. We listen to the port, send all the GET / (*) handler, which turns (*) into the display name after Hello. I suppose the code should be clear to everyone who has worked with such a scheme.

3. For comparison, add another nginx, which renders a static page with the text “Hello, habr”. Attention! Nginx is launched with out-of-box settings coming in the nginx-light package. The stock for overclocking remains huge, but we'll talk about it later.

4. Test bench (it does not rotate the language to call it a server) of the following configuration:
Lenovo B460E / RAM: 2G / CPU: Celeron Dual-Core T3500 @ 2.10Ghz
OS: Lubuntu 12.04 x86, kernel: 3.2.0-20-generic

5. We will take measurements in a primitive way, using the ab utility from apache2-utils. If you want, you can check it yourself using siege or another familiar tool.

6. Run results

  Py @ ab -c10 -n1000 http: // localhost: 8080 / habr 
(with a larger value of "-n", the Python version can no longer cope)
Time taken for tests: 0.987 seconds
Requests per second: 1012.67 [# / sec] (mean)

  Go @ ab -c10 -n1000 http: // localhost: 8080 / habr 

Time taken for tests: 0.197 seconds
Requests per second: 5080.24 [# / sec] (mean)

  Nginx @ ab -c10 -n1000 http: // localhost / 

Time taken for tests: 0.101 seconds
Requests per second: 9895.50 [# / sec] (mean)

Let's complicate the task.

  Py @ ab -c100 -n1000 http: // localhost: 8080 / habr 

Time taken for tests: 1.045 seconds
Requests per second: 956.57 [# / sec] (mean)

  Go @ ab -c100 -n1000: http: // localhost: 8080 / habr 

Time taken for tests: 0.199 seconds
Requests per second: 5021.14 [# / sec] (mean)

  Nginx @ ab -c100 -n1000 http: // localhost / 

Time taken for tests: 0.110 seconds
Requests per second: 9054.77 [# / sec] (mean)

With "-c"> 1000, the python version of the test does not pass, Nginx keeps cucumber, but Go "pleases" completely unpredictable results, showing from 50 to 4000 requests per second. I cannot explain this phenomenon, because I ran into it for the first time today, on Ubuntu 12.04 and in version Go 1. Go was stable on earlier versions (r60.3). Or maybe it's a laptop, but the package bundle is clearly not for the HighLoad server :)

I suspect that the testing methodology, default settings or lack of implementation in other languages ​​will not suit anyone. I am pleased to hear your suggestions and repeat the tests. I drove a lot of different tests and with different settings for the two years of Go. And all the tests convinced me that Go is the best tool for my range of tasks. To lead and bring them all is an ungrateful occupation, because all the same, again, they will be displeased.

By asking for a word of faith, I’ll give a brief answer on the results from memory.

Java sometimes turns out to be 10-30% faster, but at the expense of much more memory consumption (both by the VM itself and by the processes). Again, the above example (without the use of frameworks, only standard libraries) quite clearly demonstrates the minimum implementation code. And the less code, the less errors.

The same can be said about the Net / Mono C # implementation.

C / C ++ no doubt allow you to create fantastically fast web-based applications with minimal resource requirements. But the speed of development suffers greatly.

Python and Ruby implementations are about the same in losing speed and load, PHP suffers a crushing defeat.

The announcement of the next part:


Thank you for attention. I hope that at least someone mastered the introduction and found something interesting for themselves.
I look forward to the discussion, preferably civilized.

Source: https://habr.com/ru/post/141426/


All Articles