📜 ⬆️ ⬇️

Backend I / O Performance: Node vs. PHP vs. Java vs. Go

image


Understanding the I / O model of your application can lead to an understanding of the differences between the application that works with the load under which it was created, and that face to face with the real way of its application. Perhaps, if your application is small and does not create a large load, then it is not so important for it. But as traffic grows, using an erroneous I / O model can plunge you into a world of pain.


As in most other situations with several possible solutions, the matter is not which of the options is better, the point is in the understanding of compromises. In this article, we will compare Node, Java, Go and PHP from under Apache, discuss input-output models in different languages, consider the advantages and disadvantages of each model, and run some simple benchmarks. If you are concerned about the I / O performance of your next web application, then this article is for you.


Basics I / O: refresh knowledge


To understand the factors related to I / O, you first need to recall some of the concepts used at the OS level. It is unlikely that you will have to deal with many of them directly, most likely, you will work with them indirectly, through the application's runtime environment. And the details play an important role.


System calls


Take first the system calls that can be described as:



image


Blocking and non-blocking calls


It was said above that system calls are blocking, and in general this is the case. However, some calls can be described as non-blocking. This means that the kernel accepts your request, puts it in a queue or some kind of buffer, and then, without any waiting, immediately returns to the currently executing I / O. So "blocking" occurs only for a very short period of time, sufficient for placing your request in the queue.


To make it clearer, here are some examples (of Linux system calls):



. 3 , - , 3 (3 ). , . , , : , 200 (1/5 ). 20 , — 200 . 10 .


image


(« »), (« , ») /. .


(Scheduling)


, , .


. , , . . , , . 300 , , : , . , / .


— - . , 100 , 1000 , , / , . .


( ), . , , .


: « , ». / .


? : , , … .


: ( , ). , (Memcache . .) , , , /, , . , / (PHP, Java), HTTP- : /, , .


. . , /, / , .


1990- Converse CGI- Perl. PHP, , -.


PHP . , PHP- .


HTTP- - Apache. , , ( , , ). Apache PHP .php-, . PHP- /. PHP file_get_contents(), read() .


, , :


<?php

// blocking file I/O
$file_data = file_get_contents(‘/path/to/file.dat’);

// blocking network I/O
$curl = curl_init('http://example.com/example-microservice');
$result = curl_exec($curl);

// some more blocking network I/O
$result = $db->query('SELECT id, data FROM examples ORDER BY id DESC limit 100');

?>

:


image


: . / . ? , . ? 20 . , / (epoll .). , , , .


: Ruby , , .


: Java


Java , , « ». Java (multithreading) — ( ).


Java - , , , .


/ Java Servlet :


public void doGet(HttpServletRequest request,
    HttpServletResponse response) throws ServletException, IOException
{

    // blocking file I/O
    InputStream fileIs = new FileInputStream("/path/to/file");

    // blocking network I/O
    URLConnection urlConnection = (new URL("http://example.com/example-microservice")).openConnection();
    InputStream netIs = urlConnection.getInputStream();

    // some more blocking network I/O
out.println("...");
}

doGet , , , . , , . , PHP. , / , . (pooled), , , , .


Java 1.4 ( 1.7) /. , - , , . Java - - , Java- , .


image


Java /, , , / - .


/: Node


Node.js /. , Node, , , /. . , , .


, Node, : : « », : « ». , /, callback-, Node .


Node / :


http.createServer(function(request, response) {
    fs.readFile('/path/to/file', 'utf8', function(err, data) {
        response.end(data);
    });
});

callback-. , . — .


, Node / callback-. : Node. , : Node callback-; /, , callback-. / callback- (event loop). .


image


. JS- V8 (JS- Chrome, Node). JS-, , . . , / , JS , . , : , , . :


var handler = function(request, response) {

    connection.query('SELECT ...', function (err, rows) {

        if (err) { throw err };

        for (var i = 0; i < rows.length; i++) {
            // do processing on each row
        }

        response.end(...); // write out the results

    })

};

Node / , , , for , . 10 , , , . .


, / — , , , . - , .


— , — , - , . Node- , .


. Node , /. , , HTTP-, , , .


: Go


Go, , . , , .


- , Go /. — . Go . , , — . , HTTP- Go, .


:


image


runtime- Go, /, // . ., , , .


runtime- Go , , Node. , / . Go , - , : Go , . :


func ServeHTTP(w http.ResponseWriter, r *http.Request) {

    // the underlying network call here is non-blocking
    rows, err := db.Query("SELECT ...")

    for _, row := range rows {
        // do something with the rows,
// each request in its own goroutine
    }

    w.Write(...) // write the response, also non-blocking

}

, , , , /.


« ». /; , . Go . , , /. , , .


Go , /.


,


. . HTTP- . , «HTTP-/» , .


, 64- , , N SHA-256 (N URL-, , .../test.php?n=100) . / .


.


(low concurrency). 2000 300 (N = 1):


image
. ,


- . , , , /. , ( , ).


N 1000, 300 — , ( ):


image
. ,


Node, , , . , PHP ( ) Java. , SHA-256 PHP , (execution path) , 1000 .


5000 (N = 1) . , . .


image
. ,


. , , PHP + Apache , , PHP. Go , Java, Node, — PHP.


, , , , .



, , , /.


, , PHP Java /, -. , , . , , . «» PHP Java - .


, , , :


vs.I/O
PHP
Java
Node.js
Go()

. , /, / . , Go.


, , , . - Node Go. / — , . 15 .


, , , , . !


')

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


All Articles