What is fibjs?
fibjs is an application server development framework mainly designed for web backend development. It is based on the Google v8 JavaScript engine and chooses a different concurrency solution from the traditional callback. fibjs uses fiber to isolate the business complexity caused by asynchronous calls at the framework layer, greatly reducing the difficulty of development, and reducing the performance problems caused by frequent asynchronous processing in user space.
Due to historical reasons, JavaScript is mainly used for UI processing of browsers. UI development is a typical single-threaded event-driven model, so JavaScript has also formed asynchronous processing as the main programming paradigm.
With the success of JavaScript, more and more people began to apply JavaScript to other scenarios. At the same time, people are increasingly finding that asynchronous processing is not the most suitable choice in many scenarios.
Back to Basics, Agile Development
fibjs uses fiber in the framework layer to isolate the business complexity brought by asynchronous calls, and encapsulates the asynchronous processing of io into more intuitive synchronous calls. Engineers only need to write code according to the usual synchronous business logic to enjoy the benefits brought by asynchronous processing. Great convenience.
The following snippet of code is taken from the documentation for the mysql module:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32conn.beginTransaction(err => {
if (err) {
throw err;
}
conn.query('INSERT INTO posts SET title=?', title,
(error, results, fields) => {
if (error) {
return conn.rollback(() => {
throw error;
});
}
var log = 'Post ' + results.insertId + ' added';
conn.query('INSERT INTO log SET data=?', log,
(error, results, fields) => {
if (error) {
return conn.rollback(() => {
throw error;
});
}
conn.commit((err) => {
if (err) {
return conn.rollback(() => {
throw err;
});
}
console.log('success!');
});
});
});
});
In fibjs, to accomplish the same work, the code is as follows:
1
2
3
4
5
6conn.trans(() => {
var result = conn.execute('INSERT INTO posts SET title=?', title);
var log = 'Post ' + results.insertId + ' added';
conn.execute('INSERT INTO log SET data=?', log);
});
console.log('success!');
If you're after brevity, you can even write your code like this:
1
2
3
4conn.trans(() => conn.execute('INSERT INTO log SET data=?',
'Post ' + conn.execute('INSERT INTO posts SET title=?', title).insertId +
' added'));
console.log('success!');
We can clearly compare the differences brought about by the two different programming styles. Less code will bring fewer errors. With the reduction of code, the logic of the code will be clearer, and both development and maintenance will benefit from it.
embrace high energy
Although we can easily increase the response speed by expanding the server, performance should still be one of the important basis for choosing a development framework. With the introduction of ES7, async was introduced into JavaScript as a new asynchronous development pattern. However, when we enjoy the synchronous style brought by async, we also have to face its impact on performance.
We can use a piece of test code to compare the performance differences brought about by different programming styles:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39var count = 1000;
async function test_async(n) {
if (n == count)
return;
await test_async(n + 1);
}
function test_callback(n, cb) {
if (n == count)
return cb();
test_callback(n + 1, () => {
cb();
});
}
function test_sync(n) {
if (n == count)
return;
test_sync(n + 1);
}
async function test() {
console.time("async");
await test_async(0);
console.timeEnd("async");
console.time("callback");
test_callback(0, () => {
console.timeEnd("callback");
});
console.time("sync");
test_sync(0);
console.timeEnd("sync");
}
test();
Under the latest v8, the result of this code is as follows:
1
2
3async: 0.539ms
callback: 0.221ms
sync: 0.061ms
We can clearly know from the test results that when async is widely used in the project, the server will spend a lot of time processing the call and return of async functions. We also found this in some actual tests of server-side applications. And this sharp drop in performance is completely unacceptable.
Since fibjs uses fiber, it can make full use of the characteristics of the JavaScript language itself and maximize the superior performance of v8. Engineers can easily maximize the performance of the server.
Flexible choice of paradigm without being kidnapped
Choosing to use fibjs does not mean that you have to use a synchronous development style, in fact fibjs supports any asynchronous programming paradigm you have seen, and you can flexibly switch between synchronous and asynchronous styles.
Whether it is callback or async, there is a fatal flaw, that is contagion. As long as a function is callback or async, all other functions that depend on it must be callback or async. This will bring huge development costs in large-scale software development.
Take a simple server development scenario as an example. At the beginning of the project, we chose memory as session data storage. At this time, we can use the sync method to directly read and store data, and develop a complete business based on this. With the development of business scale, we need to store session data in redis or mongodb. At this time, we need to modify session-related operations to async mode.
In theory, we can modify each function in turn to make them meet the requirements of the functions they depend on, but this requires us to fully understand all modules and have the ability to modify them. This is completely impossible when multi-person collaborative development or when using third-party modules.
Therefore, all common modules need to provide both sync and async interfaces to balance the balance between asynchrony and performance. More ordinary developers will choose to only provide async interface. Thus causing a performance disaster.
In fibjs, you can easily solve similar problems, avoiding explicit asynchronous uncontrolled contagion:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17var util = require('util');
function session_get(sid) {
return sdata;
}
async function async_session_get(sid) {
return sdata;
}
function callback_session_get(sid, cb) {
cb(null, sdata);
}
data = session_get(sid);
data = util.sync(async_session_get)(sid);
data = util.sync(callback_session_get)(sid);
fibjs can use util.sync to convert a callback or async function into a sync function and call it directly. In this way, we can easily integrate modules of different programming paradigms, and transform them into sync paradigms with minimal development costs, effectively avoiding disasters caused by paradigm contagion.
start to experience
Ready to start an enjoyable development experience? So, let's start with the installation.