Techletter #50 | December 9, 2023
How does nodejs handle concurrency?
Node.js is a single-threaded, event-driven, non-blocking I/O model programming language that makes it efficient for handling multiple requests simultaneously. This is achieved by using an event loop.
Node internally uses multiple POSIX threads.
How nodejs handles concurrency & scalability?
A complete guide to threads in Node.js
Sorting Algorithms
Credits: Algomonster
Sorting is one of the most fundamental parts of computer programming. While many programming languages support inbuilt sort, understanding how the sort works can be important during its real-life applications. Some of the sorting algorithms are:
Insertion Sort:
In insertion sort, only the first item is considered sorted. Then, for each item in the sequence, we “insert” that item into the sorted list by swapping it with the item before it until it is smaller than the current item.
function sortList(unsortedList) {
for (var i = 0; i < unsortedList.length; i++) {
let current = i;
// gets the smallest element and inserts at current index
while (current > 0 && unsortedList[current] < unsortedList[current - 1]) {
const temp = unsortedList[current];
// swaps current smaller element with the element before it
unsortedList[current] = unsortedList[current - 1];
unsortedList[current - 1] = temp;
current--;
}
}
return unsortedList;
}
Selection Sort
The idea for this sorting algorithm is that we find the smallest item from the unsorted pile during each cycle and add it to the sorted pile.
function sortList(unsortedList) {
const n = unsortedList.length;
for (var i = 0; i < n; i++) {
// Assume the current position as minimum
let minIndex = i;
// Find the minimum element's index from the rest of the list
for (var j = i; j < n; j++) {
if (unsortedList[j] < unsortedList[minIndex]) {
minIndex = j;
}
}
// Swap the minimum element with the first element
[unsortedList[i], unsortedList[minIndex]] = [unsortedList[minIndex], unsortedList[i]];
}
return unsortedList;
}
Bubble Sort
In bubble sort, for each pass, we use a pointer to point at the first element of the list. For each cycle, we compare it to the next element in the list and swap them if the current item is greater, then move the pointer by one until it reaches the end of the list. We repeat this process until the list becomes sorted.
function sortList(unsortedList) {
const n = unsortedList.length;
// Iterate through all list elements in reversed order
for (var i = n - 1; i >= 0; i--) {
// Track whether a swap occurred in this pass
let swapped = false;
for (var j = 0; j < i; j++) {
// Swap if the element found is greater than the next element
if (unsortedList[j] > unsortedList[j + 1]) {
const temp = unsortedList[j];
unsortedList[j] = unsortedList[j + 1];
unsortedList[j + 1] = temp;
swapped = true;
}
}
// If no two elements were swapped, the list is sorted
if (!swapped) return unsortedList;
}
return unsortedList;
}
Merge Sort
The idea of a merge sort is divide and conquer: We divide the array into two almost equally, sort them (usually another merge sort), and merge the two sorted lists into one.
function sortList(unsortedList) {
const n = unsortedList.length;
// Base case: A list of size 1 or 0 is already sorted
if (n <= 1) return unsortedList;
// Split the list into left and right halves
const midpoint = Math.floor(n / 2);
const leftList = sortList(unsortedList.slice(0, midpoint));
const rightList = sortList(unsortedList.slice(midpoint));
const res = [];
let leftPtr = 0, rightPtr = 0;
// Merge the sorted left and right lists with two pointers
while (leftPtr < midpoint || rightPtr < n - midpoint) {
if (leftPtr === midpoint) { // If left list is empty, append element from right
res.push(rightList[rightPtr]);
rightPtr++;
} else if (rightPtr === n - midpoint) { // If right list is empty, append element from left
res.push(leftList[leftPtr]);
leftPtr++;
} else if (leftList[leftPtr] <= rightList[rightPtr]) { // Append smaller element from left
res.push(leftList[leftPtr]);
leftPtr++;
} else { // Append smaller element from right
res.push(rightList[rightPtr]);
rightPtr++;
}
}
return res;
}
Nodejs Best practices
Just writing the code isn’t enough. It should be both scalable & maintainable. For it to be both scalable & maintainable we need best practices followed by many in the industry who have already built scalable applications using nodejs. Here is one such git repository that teaches us the best practices of nodejs.
https://github.com/goldbergyoni/nodebestpractices
ML system design: 300 case studies to learn from
Recently, I have started gaining interest in Machine Learning as well. As a field artificial intelligence is a very vast subject. This site contains a database of 300 case studies from over 80 companies that share practical machine learning use cases and learnings from designing ML systems.
https://www.evidentlyai.com/ml-system-design
Upgrading database version
GitHub is a very complex software system. They updagraded nearlly 1200+ hosts and store 300+ TB of data and serve 5.5 million queries per second across 50+ database clusters. Upgrading their databases is not an easy task. But, still they successfully upgraded to MySQL 8.0
https://github.blog/2023-12-07-upgrading-github-com-to-mysql-8-0/