Background Image

BLOG

?

Shortcut

PrevPrev Article

NextNext Article

Larger Font Smaller Font Up Down Go comment Print
Written by CUBRID Community on 07/14/2017

One of the first things I stumbled upon when I started my first Node.js project was how to handle the communication between the browser (the client) and my middleware (the middleware being a Node.js application using the CUBRID Node.js driver (node-cubrid) to exchange information with a CUBRID 8.4.1 database).

I am already familiar with AJAX (btw, thank God for jQuery!!) but, while studying Node.js, I found out about the Socket.IO module and even found some pretty nice code examples on the internet... Examples which were very-very easy to (re)use...

So this quickly becomes a dilemma: what to choose, AJAX or sockets.io?

Obviously, as my experience was quite limited, first I needed more information from out there... In other words, it was time to do some quality Google search :)

There’s a lot of information available and, obviously, one would need to filter out all the “noise” and keep what is really useful. Let me share with you some of the goods links I found on the topic:

To summarize, here’s what I quickly found:

  1. Socket.IO (usually) uses the persistent connection between the client and the server (the middleware), so you can reach a maximum limit of concurrent connections depending on the resources you have on the server side (while more AJAX async requests can be served with the same resources).
  2. With AJAX you can do RESTful requests. This means that you can take advantage of existing HTTP-infrastructure like e.g. proxies to cache requests and use conditional get requests.
  3. There is more (communication) data overhead in AJAX when compared to Socket.IO (HTTP headers, cookies etc.)
  4. AJAX is usually faster than Socket.IO to “code”...
  5. When using Socket.IO, it is possible to have a two-way communication where each side – client or server - can initiate a request. In AJAX, it is only the client who can initiate a request!
  6. Socket.IO has more transport options, including Adobe Flash.

Now, for my own application, what I was most interested in was the speed of making requests and getting data from the (Node.js) server!

Regarding the middleware data communication with the CUBRID database, as ~90% of my data access was read-only, a good data caching mechanism is obviously a great way to go! But about this, I’ll talk next time.

So I decided to put up their (AJAX and socket.io) speed to test, to see which one is faster (at least on my hardware & software environment)....! My middleware was setup to run on an i5 processor, 8GB of RAM and an Intel X25 SSD drive.

But seriously, every speed test and, generally speaking, any performance test depends so much(!) on your hardware and software configuration, that it is always a great idea to try the things on your own environment, rely less on various information you find on internet and more on your own findings!

The tests I decided to do have to meet the following requirements:

  • Test:
    • AJAX
    • Socket.IO persistent connection
    • Socket.IO non-persistent connections
  • Test 10, 100, 250 and 500 data exchanges between the client and the server
  • Each data exchange between the middleware SERVER (a Node.js web server) and the client (a browser) is a 4KBytes random data string
  • Run the server in release (not debug) mode
  • Use Firefox as the client
  • Minimize the console messages output, for both server and client
  • Do each test after a client full page reload
  • Repeat each test at least 3 times, to make sure the results are consistent

Testing Socket.IO, using a persistent connection

I've created a small Node.js server, which was handling the client requests:

io.sockets.on('connection', function (client) {
    client.on('send_me_data', function (idx) {
        client.emit('you_have_data', idx, random_string(4096));
    });
});

And this is the JS client script I used for test:

1
2
3
4
5
6
7
8
9
10
11
12
13
var socket = io.connect(document.location.href);
 
socket.on('you_have_data', function (idx, data) {
    var end_time = new Date();
    total_time += end_time - start_time;
    logMsg(total_time + '(ms.) [' + idx + '] - Received ' + data.length + ' bytes.');
    if (idx++ < countMax) {
        setTimeout(function () {
            start_time = new Date();
            socket.emit('send_me_data', idx);
        }, 500);
    }
});

Testing Socket.IO, using NON-persistent connection

This time, for each data exchange, I opened a new socket-io connection.

The Node.js server code was similar with the previous one, but I decided to send back the client data immediately after connect, as a new connection was initiated every time, for each data exchange:

1
2
3
io.sockets.on('connection', function (client) {
    client.emit('you_have_data', random_string(4096));
});

The client test code was:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function exchange(idx) {
    var start_time = new Date();
    var socket = io.connect(document.location.href, {'force new connection' : true});
 
    socket.on('you_have_data', function (data) {
        var end_time = new Date();
        total_time += end_time - start_time;
        socket.removeAllListeners();
        socket.disconnect();
        logMsg(total_time + '(ms.) [' + idx + '] - Received ' + data.length + ' bytes.');
         
        if (idx++ < countMax) {
            setTimeout(function () {
                exchange(idx);
            }, 500);
        }
    });
}

Testing AJAX

Finally, I put AJAX to test...

The Node.js server code was, again, not that different from the previous ones:

1
2
res.writeHead(200, {'Content-Type' : 'text/plain'});
res.end('_testcb(\'{"message": "' + random_string(4096) + '"}\')');

As for the client code, this is what I used to test:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
function exchange(idx) {
    var start_time = new Date();
 
    $.ajax({
        url : 'http://localhost:8080/',
        dataType : "jsonp",
        jsonpCallback : "_testcb",
        timeout : 300,
        success : function (data) {
            var end_time = new Date();
            total_time += end_time - start_time;
            logMsg(total_time + '(ms.) [' + idx + '] - Received ' + data.length + ' bytes.');
             
            if (idx++ < countMax) {
                setTimeout(function () {
                    exchange(idx);
                }, 500);
            }
        },
        error : function (jqXHR, textStatus, errorThrown) {
            alert('Error: ' + textStatus + " " + errorThrown);
        }
    });
}

Remember, when coding together AJAX and Node.js, you need to take into account the you might be doing cross-domain requests and violating same origin policy, therefore you should use the JSONP based format!

Btw, as you can see, I quoted only the most significant parts of the test code, to save space. If anyone needs the full code, server and client, please let me know – I’ll be happy to share them.

OK – it’s time now to see what we got after all this work!

I have run each test for 10, 100, 250 and 500 data exchanges and this is what I got in the end:

Data exchanges Socket.IO NON-persistent (ms.) AJAX (ms.) Socket.IO persistent (ms.)
10 90 40 32
100 900 320 340
250 2,400 800 830
500 4,900 1,500 1,600

Looking into the results, we can notice a few things right away:

  1. For each type of test, the results behave quite linear; this is good – it shows that the results are consistent.
  2. The results clearly show that when using Socket.IO non-persistent connections, the performance numbers are significantly worse than others.
  3. It doesn’t seem to be a big difference between AJAX and the Socket.IO persistent connections – we are talking only about some milliseconds differences. This means that if you can live with less than 10,000 data exchanges per day, for example, there are high chances that the user won’t notice a speed difference...

The graph below illustrates the numbers I obtained in test:

nodejs_socketio_ajax_performance.png

...So what’s next...?

...Well, I have to figure out what kind of traffic I need to support and then I will re-run the tests for those numbers, but this time excluding Socket.IO non-persistent connections. That’s because it is obvious that I need to choose between AJAX and persistent Socket.IO connections.

And I also learned that, most probably, the difference in speed would not be as much as one would expect... at least not for a “small-traffic” web site, so I need to start looking into other advantages and disadvantages for each approach/technology when choosing my solution!

P.S. Here are a few more nice resources to find interesting stuff about Node.js, Socket.IO and AJAX:


  1. Monitoring CUBRID through Scouter

    Written by TaeHwan Seo on 01/18/2022 CUBRID users can monitor items in CUBRID through the Scouter. It was developed based on CUBRID 11.0 version. Full features are available from CUBRID 10.2.1 Version. Scouter (Server, Client) is available from version 2.15.0, bug fixes and features will be added by participating in Scouter GitHub in the future. The latest version of Scouter (as in 2022.01.18) is Scouter 2.15.0, Multi Agent support and bug fixes are currently in the PR stage. 1. What is Scouter? Scouter is an Open Source Application Performance Management (APM), it provides monitoring function for applications and OS. Scouter Basic Configuration Scouter-provided Information ​- WAS Basic Information Response speed/profiling information for each request, number of server requests/number of re...
    Read More
  2. QUERY CACHE Hint

    Written by MinJong Kim on 12/09/2021 ABOUT QUERY CACHE With the release of CUBRID 11.0, the CUBRID DBMS supports QUERY CACHE hint. In this article, we will take some time to look at QUERY CACHE. 1. What is Query Cache? Query Cache is a DBMS feature that stores the statements together with the retrieved record set in memory using the SELECT query statement and returns the previously cached values when the identical query statement is requested. The query cache can be useful in an environment where you have tables that do not change very often and for which the server receives many identical queries. Queries using the QUERY_CACHE hint are cached in a dedicated memory area, and the results are also cached in separate disk space. Query Cache Features 1. The QUERY_CACHE hint only applies to SELE...
    Read More
  3. CUBRID INSIDE: HASH SCAN Method

    Written by SeHun Park on 11/09/2021 - HASH SCAN Hash Scan is a scan method for hash join. Hash Scan is applied in view or hierarchical query. When a subquery such as view is joined as inner, index scan cannot be used. In this case, performance degradation occurs due to repeated inquiry of a lot of data. In this situation, Hash Scan is used. The picture above shows the difference between Nested Loop join and Hash Scan in the absence of an index. In the case of NL join, the entire data of INNER is scanned as many as the number of rows of OUTER. In contrast, Hash Scan scans INNER data once when building a hash data structure and scans OUTER once when searching. Therefore, you can search for the desired data relatively very quickly. Here, the internal structure of Hash Scan is written as the fl...
    Read More
  4. Converting PL/SQL to CUBRID Java SP using ANTLR and StringTemplate

    Written by Youngjin Joo on 09/30/2021 CUBRID DBMS (hereinafter 'CUBRID') does not support PL/SQL. If you want to continue your project by creating functions or subprograms with PL/SQL syntax in CUBRID, you need to convert them to Java Stored Function/Procedure (hereinafter 'Java SP'). Database developers, administrators, and engineers are often familiar with PL/SQL syntax but not with programming languages. In addition, application development depends very little on the DBMS used, but converting PL/SQL to Java SP seems difficult because it feels like you're developing a new system. Therefore, while I am looking for an easy way to convert PL/SQL to Java SP, I found out about ANTLR. ANTLR is a tool for generating parsers. With the help of contributors around the world, ANT...
    Read More
  5. CUBRID Internal: Storage Management (Disk Manager, File Manager)

    Written by Jaeeun, Kim on 08/11/2021 Introduction Database, just as its name implies, it needs spaces to store data. CUBRID, the open source DBMS that operates for the operating system allocates as much space as needed from the operating system and uses it efficiently as needed. In this article, we will talk about how CUBRID internally manages the storage to store data in the persistent storage device. Through this article, we hope developers can access the open source database CUBRID more easily. - The content of this article is based on version 10.2.0-7094ba. (However, it seems to be no difference in the latest develop branch, 11.0.0-c83e33. ) CUBRID Storage Management The CUBRID server has multiple modules that operate and manage data complexly and sophisticatedly. Among them, there are ...
    Read More
Board Pagination Prev 1 2 3 4 5 6 Next
/ 6

Join the CUBRID Project on