Home Blog Page 65

Máy học Microsoft ML.NET – Mô hình hồi quy, Dự báo giá nhà (Phần 1) – Bài 2

Mô hình hồi quy – Dự báo giá nhà – phần 1

Bài viết được sự cho phép của tác giả Trần Duy Thanh

Ở bài 1 Tui đã giới thiệu về nền tảng máy học Microsoft ML.NET, các bạn chưa đọc thì chú ý đọc để nắm được sơ lược về nền tảng máy học này trước khi làm bài Dự báo giá nhà bằng mô hình hồi quy. Tui sẽ hướng dẫn từ cơ bản tới nâng cao để các bạn có thể tự tay viết được phần mềm dự báo giá nhà nên Tui chia ra làm nhiều phần, mỗi phần sẽ giúp các bạn hiểu lý thuyết cơ bản, áp dụng lý thuyết để lựa chọn các tình huống cụ thể nhằm xây dựng được phần mềm theo mục đích riêng.

Hi vọng qua mỗi phần thì nội công của các bạn sẽ thâm hậu lên, tuy nhiên đừng có chém gió quá vì các phần mềm này nó chỉ hữu ích thực sự khi chạy trong hệ thống minh bạch, nếu hệ thống không minh bạch thì nó chỉ nên là công cụ để tham khảo thôi, chứ xí xớn là Cò nó mổ cho má nhận không ra.

Mục đích của bài này sẽ giúp các bạn sẽ nắm được các kiến thức:

  • Các mô hình hồi quy trong Microsoft ML.NET
  • Các lớp huấn luyện được dùng trong bài toán hồi quy
  • Xây dựng được phần mềm dự báo giá nhà đơn giản bằng mô hình hồi quy
    • Chuẩn bị dữ liệu và mô hình hóa dữ liệu như thế nào?
    • Chia bộ dữ liệu Train-Set và Test-Set ra sao
    • Chọn giải thuật để train
    • Train/build mô hình
    • Đánh giá mô hình
    • Lưu mô hình
    • Tải mô hình
    • Sử dụng mô hình

Các bạn lưu ý là chuỗi các bài học này Tui tập trung vào ứng dụng cách sử dụng các thư viện chứ không tập trung giải thích lý thuyết về máy học. Nên nếu bạn chưa có kiến thức cơ bản về máy học thì phải tự trang bị.

Các mô hình hồi quy trong Microsoft ML.NET

Trong máy học thì họ chia mô hình hồi quy ra làm 2 loại: Hồi quy tuyến tính và hồi quy Logistic. Microsoft cung cấp hàng loạt các giải thuật Trainning liên quan tới 2 mô hình hồi quy này:

Các Trainers hồi quy tuyến tính

  • FastTreeRegressionTrainer
  • FastTreeTweedieTrainer
  • FastForestRegressionTrainer
  • GamRegressionTrainer
  • LbfgsPoissonRegressionTrainer
  • LightGbmRegressionTrainer
  • OlsTrainer
  • OnlineGradientDescentTrainer
  • SdcaRegressionTrainer

Các Trainers hồi quy Logistic:

  • LbfgsLogisticRegressionBinaryTrainer
  • SdcaLogisticRegressionBinaryTrainer
  • SdcaNonCalibratedBinaryTrainer
  • SymbolicSgdLogisticRegressionBinaryTrainer

Đây đa phần là các Extension method, và ta cũng có thể bổ sung các Trainers nếu muốn. Các lớp này được Microsoft cung cấp, và nó sẽ còn được cập nhật nhiều hơn nữa.

Việc làm Machine Learning dành cho kỹ sư ML, apply ngay!

Các lớp huấn luyện được dùng trong bài toán hồi quy

Các phần của bài dự báo giá nhà sẽ đi theo mô hình mà Tui vẽ dưới này, nó gồm 7 bước (Vui lòng trích dẫn nguồn khi dùng hình này). Tui sẽ minh họa 7 bước như trong bài 1 mà Tui đã mô tả.

Tóm tắt 7 bước trên như sau:

Bước 1:

Collect dữ liệu và chạy tạo train – test set data

Tách dữ liệu thành 2 phần 20% cho test, 80% cho train

Bước 2:

Chọn giải thuật, rút trích đặc trưng cho tập dữ liệu

Giải thuật là lớp SdcaRegressionTrainer

Bước 3:

Tiến hành train mô hình, gọi phần Train Set (80%) để train

Bước 4:

Đánh giá mô hình, dùng độ qua R-Squared và RMSE (Root Mean Squared Error)

Nếu độ đo không thỏa yêu cầu thì quay lại bước collect dữ liệu, chọn tỉ lệ train và test phù hợp rồi build mô hình lại.

Bước 5:

Lưu mô hình nếu như bước 4 thỏa yêu cầu

Bước 6:

Tải mô hình, khi sử dụng chỉ việc vào bước 6 và bước 7.

Bước 7:

Sử dụng mô hình bằng cách gọi hàm Predict để dự báo giá nhà.

Ta bắt đầu học cách sử dụng mô hình hồi quy tuyến tính, với giải thuật SdcaRegressionTrainer để làm phần 1 của dự báo giá nhà, đây là bài cơ bản để hiểu cơ chế trước, các bài sau sẽ nâng cấp dần lên.

Khởi động Visual Studio 2022, nếu chưa cài đặt thì đọc bài này.

Trong mục dự án tìm chọn Console App rồi nhấn Next

Sau khi nhấn Next:

Đặt tên là “DuBaoGiaNha” rồi bấm Next

Chọn Framework .NET 6.0 (long-term support) rồi bấm Create. Dĩ nhiên khi nó ra version mới thì có thể là 7.0, 8.0….

Giao diện của dự án sẽ như hình dưới đây:

Bây giờ ta sẽ bổ sung thư viện máy học Microsoft.NET cho dự án bằng Nuget như sau:

Bấm chuột phải vào dự án chọn/ Manage Nuget Packages…

Mục Browser tìm “Microsoft.ML”, rồi bấm Install

Nó hiển thị cửa sổ ở trên thì bấm OK.

Sau đó màn hình License Acceptance cũng xuất hiện, ta nhấn “I Accept”

Nếu cài đặt thành công thì trong dự án mục Packages sẽ xuất hiện như hình trên.

Ta bắt đầu lập trình nhé

Vì đây là phần 1, phần cơ bản để hiểu được cơ chế. Nên ta giả sử rằng ta có 1 tập các các nhà có các diện tích và giá của nó (tức là chỉ có 2 thuộc tính: Diện tích và Giá), bây giờ làm sao để chương trình nó dự báo được giá của một căn nhà mới khi biết được Diện tích? (Dĩ nhiên trong thực tế không có trường hợp này, vì giá 1 căn nhà nó lệ thuộc vào: Thành phố, quận, huyện, phường, đường, diện tích, mặt tiền, hẻm, đường lộ, số tầng, số phòng ngủ, phòng khách, bếp, nhà vệ sinh…. nhiều thông số khác…. và ở nước ta chắc là lệ thuộc vào Cò.).

Một lưu ý quan trọng trong máy học là “Garbage in Garbage out” tức là dữ liệu đầu vào là rác thì kết quả đầu ra cũng là rác, vì nó build mô hình sai. Như vậy khi thu thập dữ liệu ta phải luôn luôn có bước tiền xử lý. Ví dụ ta không thể cho máy nó học Giá của một căn nhà mà chủ nhà bị phá sản bị chủ nợ tới xiết bắt bán giá rẻ bèo, hay không thể cho nó học các dữ liệu là giao dịch giả được. Điều này là hiển nhiên thôi, chúng ta đi học cũng vậy, chúng ta phải học từ những điều đúng chứ?

Bây giờ ta tạo 1 lớp là House có 2 thuộc tính Diện tích và Giá Nhà như sau:

Bấm chuột phải vào dự án / chọn Add/ Chọn Class

Đặt tên Class là “House” rồi bấm Add, tiến hành viết lệnh như dưới đây cho lớp House

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DuBaoGiaNha
{
internal class House
{
public float Size { get; set; }
public float Price { get; set; }
}
}

Tiếp tục lặp lại bước tạo lớp House, ta tạo 1 lớp mới tên là “PredictedHouse” như dưới đây

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DuBaoGiaNha
{
internal class PredictedHouse:
{

}
}

Tiến hành bổ sung mã lệnh như bên dưới:

  • thư viện Microsoft.ML.Data;
  • thuộc tính [ColumnName(“Score”)], đó là kết quả trả về quả Predict do giải thuật ta lựa chọn trong trường hợp hồi quy tuyến tính này. Và phải viết như vậy, nó sẽ tự động Mapping kết quả trong “Score” cho thuộc tính Price
  • Lưu ý dữ liệu các thuộc tính ta khai báo là float hết nhé, thuộc tính Price ta có thể đổi tên bất kỳ
using Microsoft.ML.Data;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DuBaoGiaNha
{
internal class PredictedHouse:House
{
[ColumnName("Score")]
public float Price { get; set; }
}
}

Như vậy ta có cấu trúc lớp như hình dưới đây, đồng thời vào “Program.cs” bổ sung 5 lệnh using namespace:

using System;
using System.Text;
using DuBaoGiaNha;
using Microsoft.ML;
using Microsoft.ML.Data;
using static Microsoft.ML.DataOperationsCatalog;

Trong Máy học Microsoft ML.NET tất cả đều bắt đầu bằng đối tượng MLContext, nên ta khai báo:

using System;
using System.Text;
using DuBaoGiaNha;
using Microsoft.ML;
using Microsoft.ML.Data;
using static Microsoft.ML.DataOperationsCatalog;
//xuất dấu Tiếng Việt
Console.OutputEncoding = Encoding.UTF8;
//khai báo đối tượng MLContext 
MLContext mlContext = new MLContext();

Ta tiến hành 7 bước như sau:

Ngay bên dưới dòng lệnh 10 (dòng khởi tạo đối tượng MLContext), bổ sung các lệnh cho bước 1:

//Bước 1. Chuẩn bị dữ liệu và chạy tạo train - test set data
House[] houseData = {
new House() { Size = 1.1F, Price = 1.2F },
new House() { Size = 1.9F, Price = 2.3F },
new House() { Size = 2.8F, Price = 3.0F },
new House() { Size = 3.4F, Price = 3.7F },
new House() { Size = 4.4F, Price = 7.7F },
new House() { Size = 3.2F, Price = 3.2F },
new House() { Size = 3.4F, Price = 3.8F },
new House() { Size = 5.6F, Price = 8.1F },
new House() { Size = 1.2F, Price = 1.4F },
new House() { Size = 4.0F, Price = 6.5F },
new House() { Size = 3.8F, Price = 5.9F }};
//load dữ liệu vài IDataView
IDataView alldata = mlContext.Data.LoadFromEnumerable(houseData);
//tách dữ liệu thành 2 phần 20% cho test, 80% cho train
TrainTestData splitDataView = mlContext.Data.TrainTestSplit(alldata, testFraction: 0.2);

Ở bước 1, Tui tạo khoảng 11 dữ liệu đầu vào, xem đó là lịch sử giao dịch

Hàm LoadFromEnumerable sẽ giúp chuyển dữ liệu đối tượng House thành IDataView, đây là interface quan trọng của Microsoft Machine Learning, nó giúp chuyển các dữ liệu đầu vào thành định dạng của ML.NET

Khi có dữ liệu rồi ta cần tách làm 2 nguồn, 1 nguồn để train mô hình, 1 nguồn để test mô hình.

Hàm TrainTestSplit sẽ giúp tách dữ liệu thành 2 nguồn theo tỉ lệnh testFraction, ở trên Tui để là 0.2 có nghĩa là lấy 20% cho test, 80% cho train. Nó sẽ trả về đối tượng TrainTestData, đối tượng này sẽ tự lưu phần Train-Set và Test-Set. (các bạn cứ tưởng tượng, Giảng Viên đưa 100 đề thi cho các bạn, bạn lấy ra 80 đề để ôn thi, sau đó bạn kiểm tra xem mình ôn bài có tốt không bằng cách lấy 20 đề kia làm luôn coi như nó là đề thật. Sau khi tới ngày thi thực tế thì Giảng Viên mới đưa 1 đề thật, nếu ôn luyện tốt thì đề thi thật sẽ được điểm cao),

Tiếp tục bổ sung lệnh cho bước 2 ở cuối:

// 2. Chọn giải thuật, rút trích đặc trưng cho tập dữ liệu 
var pipeline = mlContext.Transforms.Concatenate("Features", new[] { "Size" })
.Append(mlContext.Regression.Trainers.Sdca(labelColumnName: "Price", maximumNumberOfIterations: 100));

Ở bước 2 này ta cần rút trích đặc trưng cho dữ liệu, trong trường hợp này Căn nhà chỉ có đầu vào là Size (diện tích), nếu nó có nhiều thì cứ thêm vào các thuộc tính khác như là số tầng, phòng ngủ…. còn “Features” là keyword, phải viết y chang vậy.

Ở bước 2 chọn giải thuật train là Sdca (SdcaRegressionTrainer), labelColumnName được hiểu là cột mà mình cần dự báo, ở đây là cột Price (thuộc tính Price)

Nó sẽ trả về pipline (IEstimator)

Sau đó ta bổ sung lệnh cho bước 3:

// 3. Tiến hành train mô hình, gọi phần Train Set
var model = pipeline.Fit(splitDataView.TrainSet);

Ta gọi hàm Fit , truyền vào là tập dữ liệu huấn luyện , nó được lưu trong đối tượng splitDataView ở bước 1, Ta lấy phần dữ liệu huấn luyện thôi nha splitDataView.TrainSet

Kết quả của Fit nó sẽ trả về 1 model có kiểu ITransformer.

Tiếp tục bổ sung lệnh của bước 4 để đánh giá chất lượng của mô hình

//4. train mô hình xong thì phải đánh giá nó
RegressionMetrics metrics = mlContext.Regression.Evaluate(splitDataView.TestSet,
labelColumnName: "Size", scoreColumnName: "Price");
//thông số này càng nhỏ càng tốt
Console.WriteLine("Root Mean Squared Error : " + metrics.RootMeanSquaredError);
//thông số này càng tịnh tiến tới 100% càng tốt
//trong kinh tế lượng họ cho rằng >=50% là ổn, nhưng không có nghĩa <50% là dở
//ví dụ như chứng khoán nó sẽ nhảy búa xua
Console.WriteLine("RSquared: " + metrics.RSquared);

Ở bước 4 Ta dùng 2 độ đo, R-Squared và Root Mean Squared Error

Sau khi dựa vào các độ đo này thì ta sẽ quyết định mô hình tốt hay không, nếu không tốt thì quay lại bước dữ liệu, kiểm tra xem dữ liệu có sạch sẽ và chuẩn mực không, rồi thử các trường hợp chia dữ liệu để chạy lại mô hình.

Sau khi bước 4 hoàn tất thì tiến hành viết lệnh cho bước 5 nhằm lưu mô hình này xuống ổ cứng, lưu lại để lần sau chỉ đọc ra sử dụng thôi, chứ không phải tốn thời gian với chi phí để build lại mô hình .

//5.giả sử mô hình ngon rồi thì lưu mô hình lại
mlContext.Model.Save(model, splitDataView.TrainSet.Schema, "housemodel.zip");

Như vậy mặc định nó sẽ lưu vào nơi thực thi của dự án.

Hàm Save có 3 đối số, đối số 1 là mô hình và ta muốn lưu, đối số 2 là cấu trúc của TrainSet (Schema), đối số 3 là tên mô hình được lưu xuống file, mặc định để .zip

Tiếp tục bổ sung lệnh cho bước 6:

//6. Load mô hình lên để sài
//dĩ nhiên là bước 6,7 này nó nằm riêng chỗ khác, 1->5 lưu xong thì dẹp nó đi
//khi dùng chỉ quan tâm bước 6, và 7 thôi. Nhưng vì Tui hướng dẫn để 1 lèo 1->7 cho bạn hiểu
DataViewSchema modelSchema;
// Load trained model
var modelDaLuu = mlContext.Model.Load("housemodel.zip", out modelSchema);

Hàm Load sẽ có 2 đối số: Đối số 1 là tên file của mô hình mà ta lưu ở bước 5, đối số 2 là Schema là kết quả trả về loại cấu trúc của TrainSet mà ta lưu ở bước 5.

Sau khi load được mô hình thì ta tiến hành sử dụng như trong bước 7:

//7. Gọi predict để dùng mô hình xem dự báo
var input = new House() { Size = 2.5F };
var output = mlContext.Model.CreatePredictionEngine<House, PredictedHouse>(modelDaLuu).Predict(input);

Console.WriteLine("Nhà diện tích " + input.Size + " được dự đoán có giá =" + output.Price);

Ở bước 7 ta gọi CreatePredictionEngine với House là Input, PredictedHouse là output.

Truyền mồ hình vào rồi Gọi hàm Predict nó sẽ trả về một đối tượng PredictedHouse

Như vậy tới đây Tui đã trình bày xong 7 bước của bài máy học dùng Hồi quy tuyến tính để dự báo giá nhà.

Xem ngay tin tuyển dụng .NET tại các doanh nghiệp hàng đầu trên TopDev

Dưới đây là coding đây đủ:

using System;
using System.Text;
using DuBaoGiaNha;
using Microsoft.ML;
using Microsoft.ML.Data;
using static Microsoft.ML.DataOperationsCatalog;
//xuất dấu Tiếng Việt
Console.OutputEncoding = Encoding.UTF8;
//khai báo đối tượng MLContext 
MLContext mlContext = new MLContext();
//Bước 1. Chuẩn bị dữ liệu và chạy tạo train - test set data
House[] houseData = {
               new House() { Size = 1.1F, Price = 1.2F },
               new House() { Size = 1.9F, Price = 2.3F },
               new House() { Size = 2.8F, Price = 3.0F },
               new House() { Size = 3.4F, Price = 3.7F },
               new House() { Size = 4.4F, Price = 7.7F },
               new House() { Size = 3.2F, Price = 3.2F },
               new House() { Size = 3.4F, Price = 3.8F },
               new House() { Size = 5.6F, Price = 8.1F },
               new House() { Size = 1.2F, Price = 1.4F },
               new House() { Size = 4.0F, Price = 6.5F },
               new House() { Size = 3.8F, Price = 5.9F }};
//load dữ liệu vài IDataView
IDataView alldata = mlContext.Data.LoadFromEnumerable(houseData);
//tách dữ liệu thành 2 phần 20% cho test, 80% cho train
TrainTestData splitDataView = mlContext.Data.TrainTestSplit(alldata, testFraction: 0.2);

// 2. Chọn giải thuật, rút trích đặc trưng cho tập dữ liệu 
var pipeline = mlContext.Transforms.Concatenate("Features", new[] { "Size" })
.Append(mlContext.Regression.Trainers.Sdca(labelColumnName: "Price", maximumNumberOfIterations: 100));

// 3. Tiến hành train mô hình, gọi phần Train Set
var model = pipeline.Fit(splitDataView.TrainSet);

//4. train mô hình xong thì phải đánh giá nó
RegressionMetrics metrics = mlContext.Regression.Evaluate(splitDataView.TestSet,
labelColumnName: "Size", scoreColumnName: "Price");
//thông số này càng nhỏ càng tốt
Console.WriteLine("Root Mean Squared Error : " + metrics.RootMeanSquaredError);
//thông số này càng tịnh tiến tới 100% càng tốt
//trong kinh tế lượng họ cho rằng >=50% là ổn, nhưng không có nghĩa <50% là dở
//ví dụ như chứng khoán nó sẽ nhảy búa xua
Console.WriteLine("RSquared: " + metrics.RSquared);

//5.giả sử mô hình ngon rồi thì lưu mô hình lại
mlContext.Model.Save(model, splitDataView.TrainSet.Schema, "housemodel.zip");

//6. Load mô hình lên để sài
//dĩ nhiên là bước 6,7 này nó nằm riêng chỗ khác, 1->5 lưu xong thì dẹp nó đi
//khi dùng chỉ quan tâm bước 6, và 7 thôi. Nhưng vì Tui hướng dẫn để 1 lèo 1->7 cho bạn hiểu
DataViewSchema modelSchema;
// Load trained model
var modelDaLuu = mlContext.Model.Load("housemodel.zip", out modelSchema);

//7. Gọi predict để dùng mô hình xem dự báo
var input = new House() { Size = 2.5F };
var output = mlContext.Model.CreatePredictionEngine<House, PredictedHouse>(modelDaLuu).Predict(input);

Console.WriteLine("Nhà diện tích " + input.Size + " được dự đoán có giá =" + output.Price);

Chạy phần mềm (nhấn F5) ta có kết quả:

Root Mean Squared Error : 0.2828426113221826
RSquared: -6.999914170176103
Nhà diện tích 2.5 được dự đoán có giá =3.3304372

Bạn thử các dữ liệu khác, thay đổi tỉ lệ của Train-set, test-set để đánh giá lại chất lượng lại mô hình cũng thử Predict để xem giá của các căn nhà có thông số khác.

Như vậy các bạn đã hiểu được đầy đủ cách lập trình một bài dùng máy học với mô hình hồi quy tuyến tính để dự báo giá của một căn nhà. Ráng làm lại để hiểu thêm cách gọi cũng như cách sử dụng các thông số.

Bài sau Tui sẽ tiếp tục bài dự báo giá nhà, nhưng làm trên giao diện tương tác để các bạn dễ sử dụng hơn, với lại khi đưa cho khách hàng sử dụng thì phải có giao diện tương tác chứ đúng không?

Thứ tự các bài tiếp theo gồm:

  • Dự báo giá nhà dùng giao diện
  • Dự báo giá nhà dùng giao diện + nạp dữ liệu từ text file
  • Dự báo giá nhà dùng giao diện + nạp dữ liệu từ Json file
  • Dự báo giá nhà dùng giao diện + nạp dữ liệu từ Excel
  • Dự báo giá nhà dùng giao diện + nạp dữ liệu từ SQL Server
  • Dự báo giá nhà với quy trình tổng hợp

Chúc các bạn thành công.

Mã nguồn của chương trình có thể tải tại đây:

https://www.mediafire.com/file/waqsthuxc97g6go/DuBaoGiaNha.rar/file

Bài viết gốc được đăng tải tại duythanhcse.wordpress.com

Bạn có thể xem thêm:

Đừng bỏ lỡ tin tuyển dụng IT từ các công ty hàng đầu trên TopDev nhé!

Các Công Ty IT Tại TPHCM

Những công ty IT tại TPHCM

Công nghệ thông tin hiện đang phát triển như vũ bão và IT cũng là ngành được nhiều bạn trẻ lựa chọn cho con đường sự nghiệp . Tại Việt Nam, Hà Nội và Tp HCM có thể xem là hai trung tâm công nghệ lớn nhất cả nước với hàng loạt công ty công nghệ. Bài viết này trước tiên sẽ tổng hợp cho bạn những công ty IT tại Tp HCM bao gồm cả những công ty nước ngoài và công ty Việt Nam.

*Thứ tự trong bài viết chỉ nhằm liệt kê các công ty, không nhằm mục đích xếp hạng hay đánh giá

Các công ty IT nước ngoài tại TPHCM

  • KMS Technology

Đôi chút về KMS Technology thì đây là công ty outsource (90%), là một trong những công ty hàng đầu chuyên cung cấp các dịch vụ phát triển sản phẩm và các giải pháp chuyển đổi số.

  • Hitachi Vantara Vietnam (HVN) – Global Cybersoft

Hitachi Vantara Vietnam (trước đây là Global CyberSoft), đây là công ty có nhiều năm kinh nghiệm trong việc cung cấp các giải pháp CNTT và dịch vụ tích hợp hệ thống trong các lĩnh vực chuyển đổi số, phát triển phần mềm, quản lý doanh nghiệp ERP, hệ thống nhúng và dịch vụ quản trị (managed services).

  • Harvey Nash

Harvey Nash được đánh giá rất cao trong dịch vụ thuê ngoài công nghệ thông tin/ dịch vụ nghiệp vụ doanh nghiệp, lĩnh vực tìm kiếm nhân sự cấp cao.

  • Dek technologies

Được thành lập tại Melbourne Australia vào năm 1999, DEK Technologies tự hào là một trong những công ty hàng đầu trong lĩnh vực cung cấp các giải pháp về phần cứng và phần mềm với đội ngũ kỹ sư có kinh nghiệm lên đến gần 700 người tại 5 quốc gia, trong đó có Việt Nam. DEK Technologies đã, đang và sẽ luôn cố gắng mang lại cho nhân viên quyền tự chủ và sự thoải mái nhất vì Công ty luôn tin sự cởi mở và công bằng trong môi trường làm việc là chìa khóa cho sự thành công bền vững.

  • Intel Corporation

Intel nằm trong top những công ty lớn trên thế giới về sản xuất thiết bị chất bán dẫn lớn nhất thế giới, và là nhà phát minh ra chuỗi vi mạch xử lý thế hệ x86 mà bộ xử lý tìm thấy ở các máy tính cá nhân.

  • Bosch Rexroth Vietnam

Có thể nói Bosch là chuyên gia hàng đầu về Công nghệ Truyền động và Điều khiển. Đây là một tập đoàn của Đức và gia nhập vào Việt Nam từ rất sớm. Có rất nhiều nhân viên, quản lý đến từ nhiều quốc gia khác nhau, do đó phong cách làm việc tại Bosch là sự kết hợp giữa nhiều nền văn hóa với nhau. Bên cạnh đó, benefit tại Bosch cũng rất tốt.

  • Axon Active Vietnam

Đây là một công ty đi tiên phong trong lĩnh vực phát triển phần mềm “offshore” có trụ sở đặt tại Thụy Sỹ. Axon Active phát triển phần mềm dành cho BI, ERP, mạng lưới quan hệ, GIS, hệ thống quản lý rủi ro và ứng dụng cho các thiết bị di động.

  • SHIFT ASIA

Sau nhiều năm hoạt động SHIFT ASIA đã đạt được những thành tựu nhất định trong lĩnh vực Software Testing, hiện nay SHIFT ASIA bắt đầu mở rộng kinh doanh với lĩnh vực phát triển phần mềm (Software Development, Outsourcing Solutions). 

Do đó, công ty đang chiêu mộ đồng đội cùng nhau phát triển. Mời bạn tham khảo việc làm và phúc lợi của SHIFT ASIA đang tuyển tại TopDev.

Công ty nước ngoài tại TPHCM

Công ty IT Việt Nam tại TPHCM

  • Fujinet Systems JSC

Công ty phát triển phần mềm chủ yếu cho thị trường Nhật Bản với quy mô lớn gồm nhiều kỹ sư dày dạn kinh nghiệm tại thị trường Việt Nam. Fujinet mang một phong cách làm việc hài hòa giữa nét văn hóa Việt Nam – Nhật Bản.

  • Viettel

Tập đoàn viễn thông quân đội Viettel – được đánh giá là nơi có môi trường làm việc trong lĩnh vực công nghệ hấp dẫn số 1 Việt Nam.

  • MayTech

MayTech là công ty chuyên cung cấp dịch vụ thiết kế Desktop Software, Mobile App, Web App với đội ngũ gồm những chuyên gia có nhiều năm kinh nghiệm trong ngành.

  • FPT Software Hồ Chí Minh

Một công ty công nghệ thuần Việt và hầu như các kỹ sư công nghệ nào cũng biết đến. FPT Software ra đời với mục tiêu gia công phần mềm để đáp ứng cho nhu cầu phát triển công nghệ thông tin của các hãng phần mềm và xuất khẩu phần mềm trên toàn thế giới cho các công ty nước ngoài.

  • VNG Corporation

Không thể không nhắc đến kỳ lân công nghệ VNG, với sản phẩm chính là Trò chơi trực tuyến, Nền tảng kết nối, Thanh toán điện tử và Dịch vụ điện toán đám mây. Trụ sở VNG tại Tp Hồ Chí Minh được đầu tư cơ sở vật chất hiện đại mang đến môi trường làm việc lý tưởng cho nhân viên.

  • Tinhvan Group (Công ty Cổ phần Xuất khẩu Phần mềm Tinh Vân)

Công ty có kinh nghiệm chuyên sâu trong việc triển khai các dự án gia công PM thuộc nhiều lĩnh vực khác nhau.

  • TMA Solutions -DNTN Dịch Vụ Tường Minh

Được thành lập từ năm 1997, 6 văn phòng làm việc tại Tp HCM và hơn 1500 kỹ sư TMA Solutions được xem là một trong những công ty gia công phần mềm lớn nhất tại Tp Hồ Chí Minh.

  • RIKKEISOFT

Đây là một trong những công ty hàng đầu tại Việt Nam về sản xuất phần mềm, đặc biệt là ứng dụng trên nền tảng web và smartphone

  • KiteMetric

KiteMetric là một công ty outsource ra đời với sứ mệnh mang đến sản phẩm công nghệ chất lượng cao cho khách hàng. Những lĩnh vực mà công ty cung cấp có thể kể đến như: machine learning applications, data visualization, social networks, fintech applications,….

Tuy là công ty với quy mô vừa nhưng phúc lợi tại KiteMetric rất hấp dẫn. Bạn có thể truy cập vào đây để tham khảo nhé!

  • BnK Solutions

Brilliant and kool mang đến cho khách hàng nhiều dự án có quy mô từ nhỏ đến lớn với các công nghệ mới của xu hướng 4.0 như Đám mây, Phân tích Big Data, Tính di động, AI và nền tảng Công nghiệp Internet vạn vật.

  • FABA Technology

FABA Technology là một startup Việt Nam trong lĩnh vực cung cấp dịch vụ phát triển phần mềm.

Hiện FABA đang chờ đón những Dev có kinh nghiệm về chung nhà. Tham khảo ngay tại đây nhé!

  • NaviWorld Vietnam

Naviworld Vietnam là thành viên của Naviworld Group cung cấp giải pháp hàng đầu về các ứng dụng quản lý kinh doanh end-to-end cho các doanh nghiệp tầm trung.

  • XPERC

XPERC cung cấp dịch vụ phát triển phần mềm cho tất cả quy mô công ty.

Những công ty trên đây bao gồm cả doanh nghiệp lớn, nhỏ và startup. Tất nhiên, mình không thể thu thập hết tất cả các công ty được, nên thông tin trên đây chỉ mang tính chất tham khảo thôi he.

Mời bạn theo dõi thêm nhiều blog mới tại topdev.vn/blog và cũng đừng bỏ lỡ cơ hội việc làm IT, tester, PM, vân vân và mây mây trên TopDev nhá!


Tuyển Dụng Nhân Tài IT Cùng TopDev
Đăng ký nhận ưu đãi & tư vấn về các giải pháp Tuyển dụng IT & Xây dựng Thương hiệu tuyển dụng ngay!
Hotline: 028.6273.3496 – Email: contact@topdev.vn
Dịch vụ: https://topdev.vn/page/products

Mát Máy Sau Khi Chuyển Từ InfluxDB Sang TimescaleDB

Mát máy sau khi chuyển từ InfluxDB sang TimescaleDB

Bài viết được sự cho phép của tác giả Nguyễn Hồng Quân

Làm việc trong lĩnh vực IoT (Internet of Things) nên tôi khá cần một hệ quản trị cơ sở dữ liệu chuyên dụng cho kiểu dữ liệu time-series (chuỗi thời gian), để lưu trữ dữ liệu do các thiết bị giám sát gửi lên.

Mặc dù IoT dựa trên những cơ sở công nghệ đã được phát triển từ lâu, thậm chí hệ CSDL time-series cũng không phải là khái niệm mới, nhưng mỗi nhà có một nhu cầu, nên mãi cho tới hồi đầu năm nay (2020), vẫn chưa có một hệ cơ sở dữ liệu nào thỏa mãn ý của tôi cả (khi viết bài này thì đã tìm được cái ưng ý).

Vậy nhu cầu của tôi khác với các đơn vị khác như thế nào? Đó là:

  • Lưu trữ vĩnh viễn.
  • Tự tóm tắt dữ liệu cũ.
  • Chạy ổn trong máy tính nhúng.

Đa số các hệ CSDL time-series ra đời trước đây là phục vụ cho việc theo dõi “sức khỏe” của server (CPU/RAM usage) nên nó chỉ cần giữ lại dữ liệu trong một khoảng thời gian ngắn, vì vậy nhu cầu 1) không đáp ứng được. Ban đầu, khi mới bắt tay vào làm phần mềm cho AgriConnect, tôi tạm dùng PostgreSQL cho nhu cầu này, kết hợp với mẹo tạo chỉ mục (index) để đảm bảo tốc độ truy cập những dữ liệu mới ghi (để vẽ thành biểu đồ và để tính toán ra quyết định điều khiển thiết bị). Thời kỳ đó phần mềm của tôi nhắm chạy trên board BeagleBone Black nên những hệ CSDL viết bằng Java như Cassandra bị loại từ “vòng gửi xe”, dù chúng hay được nhắc đến tên trong các platform về IoT sẵn có (các platform này cũng viết bằng Java nên cũng bị tôi bỏ qua, sorry các bạn fan của Java).

PostgreSQL kết hợp với chiến thuật tạo chỉ mục hợp lý thì khá ổn cho nhu cầu hay gặp (vẽ biểu đồ, điều khiển thiết bị dựa trên dữ liệu đo đạc), cho đến khi chúng tôi bắt đầu có nhu cầu kết xuất (export) dữ liệu cũ nhằm đánh giá hiệu quả mùa vụ. Dữ liệu cũ này không được đánh chỉ mục nên khi kết xuất thì chạy khá nặng, làm BeagleBone quá tải luôn. Vì vậy tôi bắt đầu tìm kiếm thêm, vừa lúc đó thì InfluxDB ra đời (có lẽ nó ra đời trước đó rồi nhưng vẫn đang phát triển, còn sơ khai nên tôi không tìm thấy).

  Cài đặt PostgreSQL server sử dụng Docker
  Oracle to Postgres, sự trỗi dậy của bầy voi!

Sau khi chuyển đổi từ PostgreSQL sang InfluxDB thì những ngày đầu, kết quả rất phấn khởi: Do chuyên về time-series, với cách lưu trữ phù hợp, nên việc truy xuất dữ liệu gần đây hay dữ liệu cũ đều nhanh như nhau, tôi có thể dẹp bỏ script tạo lại chỉ mục dành cho PostgreSQL trước đó. Ngoài ra InfluxDB có chức năng tự tóm tắt dữ liệu cũ nên tiết kiệm được không gian lưu trữ.

Có điều niềm vui với InfluxDB chẳng kéo dài được lâu. Khi hệ thống hoạt động một thời gian, dữ liệu tích lũy đủ nhiều và InfluxDB càng cập nhật lên phiên bản mới thì nó càng bộc lộ vấn đề: ngốn quá nhiều RAM, chạy quá nặng. Để có thể duy trì hệ thống, tôi đã làm mọi cách để tối ưu bên phần của mình: sửa lại code, cắt bỏ nhiều lớp trừu tượng (ODM/ORM), tiết giảm xuống tới mức chỉ dùng câu SQL thuần khi truy cập InfluxDB, cắt một phần chức năng export ra viết lại bằng Rust. Tuy nhiên, cố gắng bên phía mình thôi vẫn chưa đủ, InfluxDB vẫn ục ịch ì ra đấy như trêu ngươi. Theo tôi, InfluxDB có một số quyết định công nghệ khiến “chúng ta không thuộc về nhau”:

  • InfluxDB dường như hướng đến việc truy cập từ front-end, nên chọn HTTP 1 làm giao thức truyền tải. Giao thức HTTP không những là dạng text (InfluxDB không dùng HTTP/2) mà còn bắt buộc kèm theo một mớ header, khiến tăng overhead: không những nội dung truyền đi nặng thêm mà cả hai phía đều phải tốn thêm công parse các header HTTP nữa (ngoài ra, là một giao thức dạng text đồng nghĩa với việc thêm bước encode/decode base64 khi cần truyền dữ liệu nhị phân). Để ý là hệ CSDL phía backend như PostgreSQL dùng giao thức dạng binary cho tinh gọn. Hậu quả của việc dùng HTTP là như kết quả profile dưới đây, các phần code khác của tôi đã được tối ưu và chạy còn nhẹ hơn thư viện client để truy cập InfluxDB:profiling
  • Dùng ngôn ngữ Go. Nói câu này có lẽ sẽ gây tranh cãi nơi fan của Go. Nhưng thực tình, tôi đã bắt gặp tâm sự của tác giả InfluxDB đâu đó rằng, anh ta lỡ chọn Go vì khi bắt tay vào xây dựng, anh ta chưa biết đến Rust. Ngoài ra, việc chọn Go hình như cũng vì InfluxDB muốn tốc độ ra sản phẩm nhanh. Chỉ trong vài năm mà công ty đằng sau InfluxDB đã cho ra một bộ nhiều sản phẩm liên quan chứ không phải mỗi database, có thể thấy ưu tiên của họ không phải là hiệu năng cao, nên việc chọn Go là hợp lý với hướng đi đó.InfluxData products

Khi tìm kiếm phương án thay thế InfluxDB, tôi đã bắt gặp TimescaleDB. TimescaleDB ra đời sau InfluxDB nên lúc tôi biết về nó thì nó vẫn chưa đủ tính năng để tôi có thể đem về dùng. Tuy nhiên, tôi đã thấy ngay triển vọng về hiệu năng cao, vì:

  • TimescaleDB được viết dưới dạng extension của PostgreSQL, nên cũng viết bằng C.
  • Cũng vì là extension của PostgreSQL nên giao tiếp với nó bằng giao thức của PostgreSQL, không đụng phải overhead như HTTP của InfluxDB.
  • Khi dùng giao thức của PostgreSQL thì tôi có cơ hội dùng một thư viện tốc độ rất cao của Python là asyncpg (theo benchmark trong link thì nó còn ăn đứt cả Go).

TimescaleDB

Khi nhìn thấy tiềm năng đó thì tôi rất háo hức, và chờ đợi. Chờ đợi mãi khi PostgreSQL chuyển dần dần từ 9.6 lên 10, 11 thì mới thấy TimescaleDB có đủ tính năng tôi cần. Cũng phải mất hơn nửa năm để tôi sắp xếp công việc, thời gian để có thể bắt tay vào thực hiện một sự thay đổi lớn về cấu trúc công nghệ bên trong platform IoT của AgriConnect.

Ban đầu có một trở ngại suýt nữa khiến tôi phải đình chỉ công việc, đó là TimescaleDB không cung cấp gói *.deb cho BeagleBone Black. May thay tôi tìm được script đóng gói cho Ubuntu của họ trên PPA, đem về chỉnh chọt một hồi cũng ra được script đóng gói dành cho BeagleBone. Các gói *.deb dành cho BeagleBone đang được lưu trên kho của AgriConnect.

Khi tôi viết bài này, phần mềm của AgriConnect đã chạy với TimescaleDB được 3 tuần trên các server của khách hàng. Sau 3 tuần quan sát thì thấy sự khác biệt thật rõ rệt. Nếu như trước đây tôi phải dành riêng một server chỉ để chạy mỗi InfluxDB, giảm tải cho khác server khác thì nay server đó phải thất nghiệp ngồi không. Ngay cả khi lần này đã mang lớp ORM trở lại thì vẫn chạy nhẹ hơn cả khi dùng InfluxDB với lớp ORM/ODM bị lược bỏ.

Bài viết gốc được đăng tải tại quan.hoabinh.vn

Bạn có thể xem thêm:

Top Developers đừng bỏ lỡ Top việc làm IT trên TopDev nhé!

VIETNAM MOBILE DAY 2022 – We Connect, Sân Chơi Quen Thuộc Của Cộng Đồng Công Nghệ Việt Nam Đã Trở Lại

thumbnail vmd 2022

Theo Báo cáo di động mới nhất của Ericsson (Ericsson Mobility Report) phát hành tháng 11/2021 cho biết, năm 2027 sẽ là năm mà sự phát triển của 5G thực sự rõ ràng trên toàn cầu. Thuê bao 5G sẽ là “xu hướng chủ đạo ở mọi khu vực”, chiếm 49% tổng số thuê bao di động toàn cầu và đạt 4,4 tỷ thuê bao.  Đại dịch Covid-19 đã cho chúng ta thấy mọi thứ có thể thay đổi nhanh như thế nào và cơ sở hạ tầng kỹ thuật số quan trọng như thế nào đối với xã hội. 5G đang bước vào một giai đoạn mới, nơi không chỉ người tiêu dùng sẽ được hưởng lợi từ các ứng dụng mới mà cả các doanh nghiệp và ngành công nghiệp sẽ tận dụng các khả năng mới. 

Sự phát triển về công nghệ, được hỗ trợ bởi mạng 5G sẽ mở rộng hệ sinh thái di động sang các ngành công nghiệp mới. Nền kinh tế kỹ thuật số toàn cầu được dự báo sẽ đạt giá trị 13,1 nghìn tỷ đô la Mỹ vào năm 2035. Phần lớn sự tăng trưởng của nền kinh tế kỹ thuật số toàn cầu sẽ được thúc đẩy bởi kết nối 5G và sự phát triển tại thị trường công nghệ di động Việt Nam cũng sẽ không thể nằm ngoài xu hướng đó.

vmd 2022

Cùng với sự phát triển & phủ sóng của công nghệ 5G, chiến lược đầu tư và tập trung phát triển, vận hành xoay quanh các thiết bị di động ngày càng trở thành trọng điểm tăng trưởng của các doanh nghiệp và toàn xã hội. Hơn thế nữa, những năm dịch Covid-19 & hậu đại dịch sẽ tiếp tục tạo ra nhiều ảnh hưởng và thay đổi đáng kể lên các hoạt động phát triển, kinh doanh & tiếp thị trên nền tảng di động.

ĐẶT VÉ NGAY!

Xu hướng Mobile-First

Thị trường ứng dụng dành cho thiết bị di động tại Việt Nam đã có từ lâu, nhưng chỉ thực sự nở rộ & nhận sự chú ý đầu tư trong 5 năm trở lại đây. Nếu trước đây thị trường Mobile Việt Nam bị “độc chiếm” bởi mảng Game thì hiện tại, dự kiến trong giai đoạn 2021-2025, các doanh nghiệp sẵn sàng tăng 653,91 tỷ USD để phát triển ứng dụng Mobile cho các mảng y tế, giáo dục, mua sắm, giải trí (theo PRNewswire).

Không nằm ngoài xu hướng thế giới Megatrend, Việt Nam đang thích nghi rất nhanh trong mảng ứng dụng di động:

  • Tổng doanh thu trên thị trường Ứng dụng di động dự kiến đạt 914,30 triệu đô la Mỹ vào năm 2022
  • Tổng doanh thu dự kiến sẽ có tốc độ tăng trưởng hàng năm (CAGR 2022-2026) là 9,47%, dẫn đến khối lượng thị trường dự kiến đạt 1.313,00 triệu đô la Mỹ vào năm 2026
  • Số lượt tải xuống trong Chợ ứng dụng dự kiến đạt hơn 3 tỷ lượt tải xuống vào năm 2022 và duy trì tốc độ tăng trưởng 21%

Phát triển ứng dụng trên di động đã trở thành một ưu tiên hàng đầu của rất nhiều doanh nghiệp trong trạng thái “bình thường mới” và trải rộng trên tất cả các lĩnh vực từ Y tế, Vận tải, Giáo dục, Giải trí… Nếu không đầu tư các giải pháp tối ưu hóa cho di động, các công ty chắc chắn có nguy cơ mất một lượng khách hàng đáng kể và tụt hậu so với đối thủ cạnh tranh.

Sự tăng trưởng của Mobile Commerce / Mobile Business

Theo báo cáo Digital Vietnam 2022 bởi WeAreSocial:

  • Hiện tại, Việt Nam có hơn 156 triệu thuê bao di động. 97.6% người dùng Internet 16 – 64 tuổi sở hữu Smartphone
  • Trong tổng trung bình 6 tiếng 38 phút sử dụng Internet, 3 tiếng 32 phút (hơn 50% thời gian) được thực hiện trên thiết bị di động
  • 12.4 tỷ đô la Mỹ được thực hiện thông qua mua bán trực tuyến và 50% lượng giao dịch đến từ thiết bị di động

Điện thoại thông minh, máy tính bảng và các thiết bị di động khác đang mở ra cơ hội kinh doanh mới. Vì khách hàng cần sự thuận tiện, tự do và nhiều sự lựa chọn, họ mong muốn có thể truy cập các dịch vụ thông qua thiết bị di động bằng trình duyệt Web sẵn có hoặc thậm chí sẵn sàng tải ứng dụng về máy. Tuy nhiên, không phải ứng dụng nào cũng hấp dẫn tất cả người dùng. Để đáp ứng nhu cầu của khách hàng và duy trì tính cạnh tranh trong điều kiện như vậy, chủ doanh nghiệp cần tập trung đầu tư nhiều hơn vào trải nghiệm và chuyển đổi nhóm đối tượng thường xuyên sử dụng sản phẩm của mình thông qua thiết bị di động, khi mà cuộc đua đã và tiếp tục diễn ra chỉ trong tầm mắt chứ không còn là câu chuyện xa vời trong tương lai.

Các điểm chạm quan trọng của Mobile Marketing

Sự xuất hiện của đại dịch Covid-19 xét theo khía cạnh tích cực là động lực khiến hoạt động Marketing trong lĩnh vực Mobile cũng ngày càng được quan tâm, đầu tư nhiều hơn với rất nhiều thách thức nhưng cũng không thiếu các cơ hội. 

Đứng trước sự thay đổi trên trong hành vi của người dùng do tác động của đại dịch, thương mại điện tử sẽ chuyển đổi tất yếu từ Digital sang Mobile, các công ty cũng buộc phải cải thiện hiệu suất & chi tiêu nhiều hơn cho Mobile App của họ. Bên cạnh đó, Marketer cần phối hợp nhiều hơn với đội ngũ kỹ thuật đảm bảo hiệu suất di động (Mobile Performance) và tạo ra nhiều trải nghiệm thiết bị chéo thuận tiện và liền mạch, tận dụng nhiều điểm chạm với người dùng để giao tiếp & giữ chân người dùng hiệu quả. 

kv vmd 2

Qua hơn 10 năm tổ chức, với sự góp mặt của Microsoft, Google, Facebook, Nielsen, Mastercard, Leveno, AppsFlyer, TikTok, VNPAY… đã tạo nên thành công vang dội cho “tên tuổi” Vietnam Mobile Day cũng như liên tục khẳng định mức độ uy tín của sân chơi này dành cho cộng đồng Công nghệ và Digital tại Việt Nam. 

Trở lại với lần thứ 12 này, VIETNAM MOBILE DAY 2022 với chủ đề “WE CONNECT” mô hình offline hội thảo kết hợp triển lãm được tổ chức bởi TopDev sẽ có hơn 80 chủ đề từ hơn 60 diễn giả đầu ngành liên quan đến các nhóm cốt lõi 5G, Mobile-first Technology, Mobile Business và Mobile Marketing cũng như các từ khóa nóng nhất hiện nay phải kể đến như GameFi, NFT, Blockchain, Metaverse… với mong muốn giúp cộng đồng nắm bắt những thông tin đáng giá và trang bị cho mình đầy đủ nhất để cạnh tranh hiệu quả trong thị trường Mobile hiện nay.

Sự kiện mang lại một sân chơi hấp dẫn, phong phú, dự kiến thu hút hơn 10.000 người tham dự; với 500 doanh nghiệp chắc chắn đây sẽ là một bữa tiệc thịnh soạn dành cho cộng đồng lập trình, doanh nghiệp và khởi nghiệp quan tâm đến lĩnh vực công nghệ.

THỜI GIAN & ĐỊA ĐIỂM DIỄN RA SỰ KIỆN

  • TP. Hồ Chí Minh: 03/06/2022 tại Melisa Center, 83 Thoại Ngọc Hầu, Hòa Thanh, Q. Tân Phú, Tp.HCM
  • TP. Hà Nội: 10/06/2022 tại CTM Palace, 131 Nguyễn Phong Sắc, Dịch Vọng Hậu, Cầu Giấy, Hà Nội

CÁC CHỦ ĐỀ DỰ KIẾN TẠI VIETNAM MOBILE DAY 2022

Về các hạng mục hợp tác tại sự kiện: 

Mr. Minh Phạm 

Mobile:  0933 331 604

Email: minh.pham@topdev.vn hoặc event@topdev.vn 

Renoleap DevOps Bootcamp – Khóa Học Miễn Phí Trong 13 Tuần Tại Việt Nam.

Renoleap DevOps Bootcamp – Khóa Học Miễn Phí Trong 13 Tuần Tại Việt Nam.

Renoleap DevOps Bootcamp, được xây dựng với sự hợp tác của Amazon Web Services (AWS), nhằm tìm kiếm và bồi dưỡng những tài năng DevOps mới và tạo ra cộng đồng kỹ thuật hàng đầu tại Việt Nam.

Renova Cloud – công ty dịch vụ đám mây hàng đầu trân trọng giới thiệu khóa học Renoleap DevOps Bootcamp. Chương trình là sự kết hợp giữa học tập thực hành cấp tốc nhằm tuyển chọn các ứng viên phù hợp và giúp họ đặt nền móng vững chắc cho sự nghiệp DevOps & Điện toán đám mây của mình.

Khóa học kéo dài 13 tuần này dành cho những ai muốn theo đuổi hoặc bắt đầu hành trình nghề nghiệp của mình với công nghệ đám mây. Renoleap tập trung hướng đến những người thực sự đam mê phát triển sự nghiệp trong DevOps, không ngoại trừ những sinh viên chưa tốt nghiệp và những người không có kiến ​​thức chuyên sâu về công nghệ.

Renoleap và AWS sẽ hợp tác chặt chẽ để đảm bảo các học viên của Trung tâm sẽ nhận được trải nghiệm học tập chất lượng tốt nhất. Chương trình đào tạo được xây dựng dựa trên sự kết hợp các tài liệu và nội dung tốt nhất từ AWS & The Cloud Native Computing Foundation Training and Certification. Cùng với trải nghiệm trên các mô hình thực tế của khách hàng Renoleap, và chương trình giảng dạy gồm nhiều chủ đề devops phong phú chắc chắn sẽ mang đến cho học viên kiến thức và trải nghiệm đa dạng.

Doron Shachar, doanh nhân người Israel & Người sáng lập Renoleap DevOps Bootcamp Doron Shachar, doanh nhân người Israel & Người sáng lập Renoleap DevOps Bootcamp chia sẻ: “Chúng tôi tự hào cho ra mắt Renoleap DevOps Bootcamp với mục đích tạo ra hàng trăm con đường phát triển nghề nghiệp DevOps thú vị cho các ứng viên có nền tảng kiến thức & học vấn đa dạng, không phụ thuộc đó có phải ngành CNTT hay không. Dựa trên kinh nghiệm nhiều năm về Cloud & DevOps của mình, chúng tôi xây dựng một chương trình đào tạo 13 tuần nhằm đảm bảo các học viên nhận được sự kết hợp hoàn hảo giữa giáo dục chính quy, thực tế kỹ thuật và nhu cầu của khách hàng để tạo ra một thế hệ kỹ thuật viên lập trình tài năng. ”

Kinh nghiệm ứng viên

Renoleap đang tìm kiếm những ứng viên chia sẻ chung các giá trị của chúng tôi, những người thể hiện được niềm đam mê và ham học hỏi về công nghệ cũng như giải quyết các vấn đề với mã code. Công ty đang mở rộng đội ngũ nhân tài của mình để tiếp cận những ứng viên tiềm năng nhưng chưa tìm được chỗ đứng của mình trong ngành.

Không ngoại trừ đó là những người có kỹ năng công nghệ cũ đang tìm cách chuyển sang đám mây, những người trở lại làm việc sau thời gian nghỉ việc, những người đam mê công nghệ hiện không làm việc trong ngành CNTT và những sinh viên tốt nghiệp ngành kỹ thuật đang tìm kiếm một bước tiến triển nghề nghiệp vượt bậc.

Các ứng viên sẽ có được tham gia vào một nhóm hỗ trợ tại Renoleap, gồm các nhà tuyển dụng, chuyên gia kỹ thuật và cố vấn luôn sẵn sàng giúp họ tiến bộ và giúp họ tiếp cận gần hơn với các nhu cầu của khách hàng trong công ty. Renoleap DevOps Bootcamp sẽ tuyển dụng các ứng viên tham gia hơn 100 vai trò kỹ thuật mà Renoleap đang triển khai trên các dự án với khách hàng.

Renoleap DevOps Bootcamp hiện đang chiêu sinh cho khóa học sắp tới sẽ bắt đầu vào ngày 30 tháng 5! Hiện đã mở đơn đăng kí tại Việt Nam! 

Để tìm hiểu thêm và chương trình, bạn có thể điền vào mẫu đăng ký tại đây hoặc gửi email cho chúng tôi tới bootcamp@renoleap.io

Tìm hiểu thêm về chúng tôi: https://renoleap.io/

Đăng ký ngay hôm nay!

Top Developers đừng bỏ lỡ việc làm IT hấp dẫn trên TopDev nhé!

Giới thiệu nền tảng máy học ML.NET của Microsoft

Giới thiệu nền tảng máy học ML.NET của Microsoft

Bài viết được sự cho phép của tác giả Trần Duy Thanh

ML.NET là gì?

ML.NET là thư viện máy học Mã nguồn mở và chạy cross-platform (Windows, Linux, macOS) của Microsoft. Ta có thể lập trình được thư viện này trên các nền tảng như Desktop, Web, hay build các Service. Nó được đánh giá là mạnh mẽ có thể làm được những gì một số thư viện khác làm được (chẳng hạn như scikit-learn viết bằng Python) và làm được những thứ mà thư viện khác không làm được.

Với việc sở hữu các nền tảng công nghệ mạnh mẽ nhất, khách hàng sẵn có trải rộng khắp thế giới nên ML.NET được kỳ vọng rất lớn sẽ tạo ra được cơn sốt về công nghệ liên quan tới máy học viết bằng C#/F# và tạo ra thị trường lao động ở phân khúc này là rất khả thi.

Theo thông tin từ hãng thì ML.NET bắt đầu khởi động từ 05/2018 và hiện nay bản chạy ổn định là 1.7.0 (tính tới 02/2022), và Microsoft cùng cộng đồng đang tiếp tục bổ sung tính năng cũng như cải tiến hiệu suất của các giải thuật.

Linh hồn của ML.NET là một mô hình học máy (machine learning model). Mô hình này chỉ định các bước cần thiết để chuyển đổi dữ liệu đầu vào của ta thành các kết quả dự đoán của mô hình, nó tùy vào giải thuật mà chúng ta lựa chọn. Với ML.NET, Ta có thể tùy chỉnh mô hình bằng cách lựa chọn các thuật toán machine learning của ML.NET (dĩ nhiên nó phải lệ thuộc vào bài toán ta muốn làm là gì để chọn giải thuật cho phù hợp) hoặc ta cũng có thể import các mô hình của TensorFlow hay ONNX đã được đào tạo trước để sử dụng. Ngoài ra ML.NET cũng cung cấp hàm cho ta lưu mô hình để tái sử dụng cũng như chia sẻ model cho cộng đồng.

Xem ngay tin tuyển dụng lập trình viên .NET tại các doanh nghiệp hàng đầu trên TopDev

Về cơ bản thì 1 bài toán Machine learning nó sẽ hoạt động như hình dưới đây (hình nguồn Microsoft):

ví dụ bài toán Machine learning

Đại khái tui tóm tắt các bước trong 1 bài toán Machine learning như sau (dĩ nhiên tùy vào kỹ thuật, kinh nghiệm của mỗi người mà ta tiến hành các bước cho riêng mình, ở đây Tui nói tổng quan):

  • Bước 1: Chuẩn bị dữ liệu, bước này cần chuẩn hóa dữ liệu do thường ban đầu các dữ liệu nó bị “ô nhiễm” tức là nó chứa các dữ liệu không đúng, dữ liệu chứa rác không đáp ứng được nhu cầu. Ví dụ như nếu dữ liệu text thì có các ký tự viết tắt, ký tự lạ, biểu tượng… Dữ liệu hình thì có các hình mờ không thể nhận dạng, dữ liệu Video thì có Video bị lỗi.
  • Bước 2: Rút trích đặt trưng, cứ hiểu là bước vector hóa dữ liệu, các dữ liệu thường được mã hóa về các ma trận dạng số, bước này giờ đã dễ dàng hơn, ta chỉ cần nạp cấu trúc đối tượng và truyền các mảng thuộc tính tương ứng, ML.NET sẽ làm giúp ta điều này. Ở bước này đôi khi sẽ được làm đồng thời với việc chia dữ liệu ra làm 2 phần: Train set và Test set. Và nó tùy thuộc vào tỉ lệ lấy dữ liệu thì mô hình chạy có thể cho ra chất lượng khác nhau. Các bạn tưởng tượng có 100 đề thi thì 100 đề này là dữ liệu, nếu lấy 80 đề thi ra để luyện tập (nó gọi là Train Set), sau khi luyện tập xong ta lấy 20 đề kia ra để làm xem được hay không (20 đề đó gọi là Test set). Trong máy học có thêm khái niệm về Over-fit, nếu bạn lấy 100 đề đó ra luyện tập, sau đó lại lấy 1 đề trong 100 đề đó ra để làm bài test, thì lúc này đa phần bạn làm điểm cao nhưng mà điểm cao trong tự sướng (Over fit vì bạn tưởng nhầm là mình đã được train giỏi, nhưng là do bạn đã làm trước đó rồi, dẫn tới khi đi thi thực tế ra 1 đề lạ hoắc có thể bạn sẽ bị rớt.
  • Bước 3: Tiến hành Build/Train mô hình: Tùy vào bài toán phân lớp, gom cụm… thì ta sẽ dùng các giải thuật khác nhau để build mô hình. Ví dụ như có 1 dữ liệu Comment của khách hàng, hỏi xem comment này là tích cực hay tiêu cực thì nó thuộc bài toán phân lớp, như vậy ta sẽ dùng các giải thuật phân lớp. Hay nếu có một tập dữ liệu các căn nhà và giá của nó, giờ muốn dự báo xem 1 căn nhà bất kỳ có giá bao nhiêu thì nó lại thuộc bài toán hồi quy. Bước 3 sẽ chọn đúng giải thuật để build mô hình cho đúng
  • Bước 4: Đánh giá mô hình, mọi mô hình được build xong cần được đánh giá nó xem chất lượng của nó tới đâu (không có mô hình đúng hay sai chỉ có mô hình chất lượng hay không), và chất lượng hay không nó lệ thuộc vào các thang đo, ví dụ như trong các bài hồi quy thì nó các thang đo R-Squared, MSE, RMSE, MAE, và hầu như các giải thật cũng có Loss Function. R-Squared càng cao (tịnh tiến tới 100%) thì mô hình càng tốt, (dĩ nhiên với các bài về chứng khoán thì chưa chắc do nó nhảy múa, thông thường R-Squared >=50% là ổn, nhưng không có nghĩa là <50% là tệ), còn MSE, RMSE, MAE, Loss function thì thấp sẽ càng tốt. Việc quyết định chọn mô hình nào là tùy thuộc vào kinh nghiệm của người build mô hình và có tham khảo các độ đo này. Và lưu ý là ứng với mỗi loại giải thuật máy học thì độ đo sử dụng sẽ khác nhau, Tui chỉ ví dụ về giải thuật hồi quy để các bạn hiểu sơ lược vậy
  • Bước 5: Sử dụng mô hình, ở bước này thường là sau khi bước 4 đánh giá xong, thì ta sẽ lưu mô hình xuống ổ cứng và có thể chia sẻ lên cloud, lưu lại để lần sau chỉ lấy ra sài thôi, không phải tốn công chạy lại (tiết kiệm thời gian và chi phí), khi khi lưu xong muốn sài thì load mô hình lên để sài. Còn sài như thế nào nó tùy thuộc vào bài toán của mình để gọi hàm Predict cho phù hợp.

ML.NET hỗ trợ các bài toán nào liên quan tới Máy Học?

  • Classification: Ví dụ các bài toán về phân loại cảm xúc khách hàng tích cực hay tiêu cực từ các feedback của họ
  • Clustering : Ví dụ các bài toán về gom cụm khách hàng, giả sử có N khách hàng ta cần phải gom thành k cụm, các cụm này chứa các đặc trưng khác nhau của khách hàng.
  • Regression/Predict continuous values: Ví dụ các bài toán về hồi quy như dự đoán giá nhà, giá taxi …. từ một tập dữ liệu giao dịch trong quá khứ, hãy dự đoán giá của nó là gì khi có một số dự kiện mới.
  • Anomaly Detection: Các bài toán về phát hiện bất thường, chẳng hạn như Phát hiện các giao dịch gian lận trong ngân hàng
  • Recommendations: Các bài toán về khuyến nghị, ví dụ như làm sao quảng cáo được sản phẩm tới đúng khách hàng có nhu cầu, làm sao khi vào tiki thì nó gợi ý được các cuốn sách mà người này quan tâm.
  • Time series/sequential data: các bài toán như dự báo thời tiết hay doanh số bán sản phẩm
  • Image classification: các bài toán về phân loại hình ảnh
  • Object detection: Các bài toán về Phát hiện đối tượng

Dưới đây là hình minh họa sự khác biệt giữa Image classification và Object detection (hình nguồn Microsoft)

hình minh họa sự khác biệt giữa Image classification và Object detection

Cơ chế hoạt động của ML.NET như thế nào?

Ở trên Tui đã nói các bước hoạt động chung của một phần mềm liên quan máy học rồi, còn với ML.NET, khi sử dụng các thư viện của Microsoft thì cơ chế hoạt động như thế nào? về cơ bản là nó đúng với các bước cơ bản chung, Tui có vẽ lại workflow mà Microsoft cung cấp (hình gốc Tui thấy mờ và không đẹp nên Tui đã vẽ lại cho rõ và đẹp hơn).

Cơ chế hoạt động của ML.NET

Ở hình trên như các bạn thấy thì sẽ có 7 bước hoàn chỉnh trong quá trình sử dụng thư viện máy học ML.NET của Microsoft. Tui tóm tắt lại như dưới đây (các coding chi tiết Tui sẽ trình bày ở các bài sắp tới):

  • Bước 1: là bước chuẩn bị dữ liệu, ở bước này tùy vào bài toán mà ta thu thập dữ liệu khác nhau, dữ liệu sau khi thu thập phải được làm sạch/ chuẩn hóa. Vì nguyên tắc vàng các bạn phải nhớ “garbage in garbage out”, dữ liệu có thể được lưu dạng text, csv, sql server…. ứng với mỗi loại file ML.NET sẽ cung cấp các thư viện phù hợp để ta có thể tải dữ liệu đồng thời tự động mô hình hóa dữ liệu này thành mô hình hướng đối tượng. ở bước 1 thường sẽ làm công đoạn tải dữ liệu xong thì ta làm luôn công đoạn chia dữ liệu ban đầu thành 2 phần: Train set để huấn luyện mô hình (dùng cho bước 3), Test set để đánh giá mô hình (dùng cho bước 4). các dữ liệu được lưu vào IDataView object
  • Bước 2: Tùy vào mục đích bài toán máy học mà ta dùng các giải thuật khác nhau, có thể dùng Binary classification, Multiclass classification, Regression…. (giải thuật nào là do mục đích nên khnog thể liệt kê hết, khi nào gặp thì tìm hiểu từng trường hợc cụ thể cho nó đỡ rắc rối). Bước này đại khái là chỉ định một quy trình hoạt động để trích xuất các đặc trưng và áp dụng thuật toán học máy cho phù hợp. Đối tượng tạo ra ở bước này là IEstimator
  • Bước 3: Tiến hành train mô hình bằng cách gọi phương thức Fit() của IEstimator. kết quả của phương thức Fit() sẽ trả về một mô hình có kiểu ITransformer. Dữ liệu train là lấy Train set ở bước 1.
  • Bước 4: Sau khi train mô hình xong thì chưa có sài ngay (thường là vậy), vì thường các bài toán máy học nó sẽ có kết quả dự đoán sai khác với thực tế, vấn đề là sự sai khác này có được chấp nhận hay không? có được tiếp tục sử dụng và tiếp tục cải tiến mô hình nữa hay không. Do đó khi train mô hình xong thì ta cần đánh giá mô hình này chất lượng ra sao. Ta sẽ lấy Test set ở bước 1 để đánh giá. Hàm đánh này tên là Evaluate() nó nằm trong các lớp giải thuật mà ta sử dụng để train mô hình, train mô hình dùng giải thuật nào thì khi đánh giá cũng dùng giải thuật đó. Ví dụ khi train mà ta dùng MulticlassClassification để train, thì khi đánh giá cũng dùng MulticlassClassification để đánh giá. Kết quả của hàmg Evaluate() sẽ trả về một object XYZMetrics. Với XYZ là giải thuật mà ta dùng để đánh giá, ví dụ dùng MulticlassClassification để đánh giá thì nó trả về MulticlassClassificationMetrics, dùng Regression để đánh giá thì nó lại trả về kết quả là RegressionMetrics… Nên sau khi gọi hàm đánh giá xong thì dựa vào các đối tượngkết quả trả về này mà ta quyết định xem có dùng mô hình này được hay không (trong máy học không có mô hình sai chỉ có mô hình phù hợp hay không). Ví dụ như mô hình đó dự đoán giá bán căn nhà là 1 tỉ, nhưng thực tế là 5 tỉ mới đúng giá, thì ráng mà chịu ai biểu không xem chất lượng mô hình có hợp lý hay không, với lại bán 1 tỉ cũng được mà chỉ là ít tiền thôi (nhưng là kỹ sư phần mềm cùng với am hiểu về cuộc sống thì chúng ta cũng điên điên có giới hạn thôi, nhường người khác điên với). Nếu bước 4 đánh giá mô hình mà không thấy nó ổn thì quay lại bước 1. 
  • Bước 5: Lưu mô hình, sau khi đã đánh giá mô hình chất lượng ở bước 4 rồi thì lưu lại để lần sau chỉ tải mô hình ra sài thôi, không phải chuẩn bị lại dữ liệu và train lại (vì các bước này rất tốt chi phí). File mô hình được lưu mặc định có đuôi .zip . ta gọi phương thức Save() để lưu
  • Bước 6: Load mô hình đã được lưu ở bước 5. Ví dụ hôm qua lưu xong tắt máy, hôm nay mở máy lên thì chỉ cần tải lại mô hình đã chạy thôi, hoặc nhiệm vụ của ta là build model và đánh giá mô model cho chất lượng, rồi gửi model tới team khác sử dụng, thì muốn gửi đi được phải lưu được mô hình xuống ổ cứng đã chứ. Ta gọi hàm Load() để tải mô hình. Sau khi tải nó sẽ mô hình hóa ngược lại đối tượng ITransformer
  • Bước 7: là gọi hàm CreatePredictionEngine().Predict() để sử dụng mô hình nhằm tìm ra kết quả dự báo của chương trình. Truyền đối tượng ITransformer ở bước 6 vào sài thôi.

Vậy bạn nắm quy trình 7 bước trước nha. sau khi lưu rồi thì lúc sử dụng ta chỉ cần làm 2 bước đó là bước 6 và bước 7. Rất tiện lợi.

Ví dụ code (hiển nhiên bạn xem để nắm cơ chế các bước Tui trình bày ở trên thôi, chứ giờ chưa cần hiểu code, Tui sẽ trình bày cách code chi tiết ở bài sau):

using System;
using System.Text;
using Microsoft.ML;
using Microsoft.ML.Data;
using static Microsoft.ML.DataOperationsCatalog;
 
class Program
{
    public class HouseData
    {
        public float Size { get; set; }
        public float Price { get; set; }
    }
 
    public class Prediction
    {
        [ColumnName("Score")]
        public float Price { get; set; }
    }
 
    static void Main(string[] args)
    {
        Console.OutputEncoding= Encoding.UTF8;   
        MLContext mlContext = new MLContext();
 
        //Bước 1. Chuẩn bị dữ liệu và chạy tạo train - test set data
        HouseData[] houseData = {
               new HouseData() { Size = 1.1F, Price = 1.2F },
               new HouseData() { Size = 1.9F, Price = 2.3F },
               new HouseData() { Size = 2.8F, Price = 3.0F },
               new HouseData() { Size = 3.4F, Price = 3.7F },
               new HouseData() { Size = 4.4F, Price = 7.7F },
               new HouseData() { Size = 3.2F, Price = 3.2F },
               new HouseData() { Size = 3.4F, Price = 3.8F },
               new HouseData() { Size = 5.6F, Price = 8.1F },
               new HouseData() { Size = 1.2F, Price = 1.4F },
               new HouseData() { Size = 4.0F, Price = 6.5F },
               new HouseData() { Size = 3.8F, Price = 5.9F }};
        //load dữ liệu vài IDataView
        IDataView alldata = mlContext.Data.LoadFromEnumerable(houseData);
        //tách dữ liệu thành 2 phần 20% cho test, 80% cho train
        TrainTestData splitDataView = mlContext.Data.TrainTestSplit(alldata, testFraction: 0.2);
         
        // 2. Chọn giải thuật, rút trích đặc trưng cho tập dữ liệu 
        var pipeline = mlContext.Transforms.Concatenate("Features", new[] { "Size" })
            .Append(mlContext.Regression.Trainers.Sdca(labelColumnName: "Price", maximumNumberOfIterations: 100));
 
        // 3. Tiến hành train mô hình, gọi phần Train Set
        var model = pipeline.Fit(splitDataView.TrainSet);
 
        //4. train mô hình xong thì phải đánh giá nó
        RegressionMetrics metrics = mlContext.Regression.Evaluate(splitDataView.TestSet, 
            labelColumnName: "Size", scoreColumnName: "Price");
        //thông số này càng nhỏ càng tốt
        Console.WriteLine("Root Mean Squared Error : " + metrics.RootMeanSquaredError);
        //thông số này càng tịnh tiến tới 100% càng tốt
        //trong kinh tế lượng họ cho rằng >=50% là ổn, nhưng không có nghĩa <50% là dở, nó có thể là số âm vô cùng
        //ví dụ như chứng khoán nó sẽ nhảy búa xua
        Console.WriteLine("RSquared: " + metrics.RSquared);
         
        //5.giả sử mô hình ngon rồi thì lưu mô hình lại
        mlContext.Model.Save(model, splitDataView.TrainSet.Schema, "housemodel.zip");
 
        //6. Load mô hình lên để sài
        //dĩ nhiên là bước 6,7 này nó nằm riêng chỗ khác, 1->5 lưu xong thì dẹp nó đi
        //khi dùng chỉ quan tâm bước 6, và 7 thôi. Nhưng vì Tui hướng dẫn để 1 lèo 1->7 cho bạn hiểu
        DataViewSchema modelSchema;
        // Load trained model
        var modelDaLuu = mlContext.Model.Load("housemodel.zip", out modelSchema);
 
        //7. Gọi predict để dùng mô hình xem dự báo
        var input = new HouseData() { Size = 2.5F };
        var output = mlContext.Model.CreatePredictionEngine<HouseData, Prediction>(modelDaLuu).Predict(input);
 
        Console.WriteLine("Nhà diện tích "+ input.Size +" được dự đoán có giá ="+ output.Price);        
    }
}
Kết quả chạy ta được:
Root Mean Squared Eror : 0.2828426113221826
RSquared: -6.999914170176103
Nhà diện tích 2.5 được dự đoán có giá =3.3892932

Kiến trúc lớp của ML.NET gồm những gì?

Để sử dụng ML.NET ta sẽ bắt đầu với đối tượng MLContext. Đối tượng này chứa các hàm/đối tượng để tải, lưu dữ liệu, chuyển đổi dữ liệu , trình huấn luyện và các thành phần vận hành mô hình. Mỗi đối tượng sẽ có các phương thức để tạo các loại thành phần khác nhau như:

Chức năng Lớp sử dụng
Data loading and saving DataOperationsCatalog
Data preparation TransformsCatalog
Binary classification BinaryClassificationCatalog
Multiclass classification MulticlassClassificationCatalog
Anomaly detection AnomalyDetectionCatalog
Clustering ClusteringCatalog
Forecasting ForecastingCatalog
Ranking RankingCatalog
Regression RegressionCatalog
Recommendation RecommendationCatalog
TimeSeries TimeSeriesCatalog
Model usage ModelOperationsCatalog

Như vậy Ta lưu ý ứng với loại chức năng khác nhau thì ta dùng các lớp cho phù hợp, dĩ nhiên cũng không quan trọng lắm chỗ này, đừng ráng nhớ nhiều làm gì mệt óc, khi nào gặp tường hợp nào thì ta cắm đầu vào trường hợp đó mà tìm hiểu thôi. Tui do đi dạy cùng với đi làm nên phải ráng biết càng nhiều càng tốt.

Có những cách nào để lập trình được với ML.NET?

Hiện ta có khoảng 3 cách để lập trình với ML.NET, chúng gồm (hình nguồn Microsoft):

Như vậy ta có thể dùng ML.NET API (code)ML.NET Model Builder (dùng Visual Studio UI, xem bài), và ML.NET CLI (Cho cross platform)

Trong các bài hướng dẫn tới tui sẽ dùng chủ yếu cách số 1 ML.NET API (code)

Chúc các bạn thành công.

Bài viết gốc được đăng tải tại duythanhcse.wordpress.com

Có thể bạn quan tâm:

Ứng tuyển ngay nhiều việc làm IT hấp dẫn có trên TopDev

Tất Cả Những Gì Bạn Cần Biết Khi Làm User Avatar Trong React

Tất cả những gì bạn cần biết khi làm user avatar trong React

Bài viết được sự cho phép của tác giả Lưu Bình An

Tạo avatar mặc định

Trong trường hợp user chưa upload avatar, chúng ta sẽ hiển thị một avatar mặc định, sử dụng jdenticon nó sẽ cho chúng ta bộ hình sau:

import { ComponentProps, FC, useState } from 'react';

export const AutoAvatar: FC<
  ComponentProps<'img'> & { userId: number; size: number }
> = ({ userId, size, ...imgProps }) => {
  const [base64, setBase64] = useState(undefined as string | undefined);

  // dùng dynamic import để tối ưu
  import('jdenticon').then(({ toSvg }) => {
    const svgString = toSvg(userId, size);
    const base64 = Buffer.from(svgString).toString('base64');
    setBase64(base64);
  });

  return base64 ? (
    <div style={{ backgroundColor: 'rgb(225,225,225)', display: 'flex' }}>
      <img
        {...imgProps}
        src={`data:image/svg+xml;base64,${base64}`}
        alt={'User Avatar'}
      />
    </div>
  ) : (
    <div style={{ width: size, height: size, display: 'inline-block' }}>
      Loading...
    </div>
  );
};

Thư viện này khoản 45kb, để webpack dynamic load khi cần thiết cho tiết kiệm Giá trị base64 trả về chúng ta có thể gán cho src của thẻ <img />

Cho user upload avatar

Nếu chỉ dùng <input type="file" /> UI nó sẽ khá xấu, chúng ta dấu nó đi và thay bằng một <button /> để dễ chỉnh CSS hơn. Sử dụng ref để trigger sự kiện click trên input

import React, {createRef} from "react";

export const ImageSelect = () => {
  const fileRef = createRef<HTMLInputElement>();

  const onFileInputChange: React.ChangeEventHandler<HTMLInputElement> = (e) => {
    console.log(e.target?.files?.[0]);
  }

  return (
    <>
      <input
        type="file"
        style={{display: 'none'}}
        ref={fileRef}
        onChange={onFileInputChange}
        accept="image/png,image/jpeg,image/gif"
      />
      <button
        onClick={() => fileRef.current?.click()}
      >Cool Button
      </button>
    </>
  )
}

Top tin tuyển dụng React đang chờ các Developers ứng tuyển!

Crop ảnh

Trước khi gửi ảnh xuống backend để lưu lại, chúng ta sẽ cho phép user crop ảnh bằng cropper.js và react-cropper

import React, {createRef} from "react";
import {Cropper, ReactCropperElement} from "react-cropper";
import 'cropperjs/dist/cropper.css';

export const ImageCrop = () => {
  const cropperRef = createRef<ReactCropperElement>();

  return (
    <Cropper
      src="<the iamge src>"
      style={{height: 400, width: 400}}
      autoCropArea={1}
      aspectRatio={1}
      viewMode={3}
      guides={false}
      ref={cropperRef}
    />
  )
}

Một số thiết đặt

  • autoCropArea = 1 mặc định là chọn toàn bộ hình
  • aspectRatio = 1 tỉ lệ crop mong muốn, chọn 1:1, vuông
  • viewMode = 3 không cho phép chọn vào vùng nằm ngoài hình
  • guides = false không hiển thị mấy đường grid
import React, {createRef, useState} from "react";
import {Cropper, ReactCropperElement} from "react-cropper";
import 'cropperjs/dist/cropper.css';

export const ImageCrop = () => {
  const cropperRef = createRef<ReactCropperElement>();
  const [cropped, setCropped] = useState(null as string | null);

  const onSaveClick = () => {
    const imageElement: any = cropperRef?.current;
    const cropper: any = imageElement?.cropper;
    setCropped(cropper.getCroppedCanvas().toDataURL())
  }

  return (
    <>
      <Cropper
        src={"https://picsum.photos/500/300"}
        style={{height: 400, width: 400}}
        autoCropArea={1}
        aspectRatio={1}
        viewMode={3}
        guides={false}
        ref={cropperRef}
      />
      <button onClick={onSaveClick}>Crop</button>
      {cropped &&
        <img src={cropped} alt={"It's cropped"}/>
      }
    </>
  )
}

Để lấy image cho việc upload, sử dụng blob. Còn nếu chỉ cần hiển thị thì dùng dataUrl như ở trên

cropper.getCroppedCanvas().toBlob()

Toàn bộ source code

import React, {createRef, useState} from 'react';
import './App.css';
import {Cropper, ReactCropperElement} from "react-cropper";
import 'cropperjs/dist/cropper.css';
import './roundedCropper.css';

// chuyển file qua base64
const file2Base64 = (file: File): Promise<string> => {
  return new Promise<string>((resolve, reject) => {
    const reader = new FileReader();
    reader.readAsDataURL(file);
    reader.onload = () => resolve(reader.result?.toString() || '');
    reader.onerror = (error) => reject(error);
  });
};

const App = () => {
  // ref đến file input
  const fileRef = createRef<HTMLInputElement>();

  // hình được chọn
  const [uploaded, setUploaded] = useState(null as string | null);

  // kết quả của image sau khi crop
  const [cropped, setCropped] = useState(null as string | null);

  // ref đến crop element
  const cropperRef = createRef<ReactCropperElement>();

  const onFileInputChange: React.ChangeEventHandler<HTMLInputElement> = (e) => {
    const file = e.target?.files?.[0];
    if (file) {
      file2Base64(file).then((base64) => {
        setUploaded(base64);
      });
    }
  }

  const onCrop = () => {
    const imageElement: any = cropperRef?.current;
    const cropper: any = imageElement?.cropper;
    setCropped(cropper.getCroppedCanvas().toDataURL())
  }

  return (
    <>
      <div className="App">
        {
          uploaded ?
            <div>
              <Cropper
                src={uploaded}
                style={{height: 400, width: 400}}
                autoCropArea={1}
                aspectRatio={1}
                viewMode={3}
                guides={false}
                ref={cropperRef}
              />
              <button onClick={onCrop}>Crop</button>
              {cropped && <img src={cropped} alt="Cropped!"/>}
            </div>
            :
            <>
              <input
                type="file"
                style={{display: 'none'}}
                ref={fileRef}
                onChange={onFileInputChange}
                accept="image/png,image/jpeg,image/gif"
              />
              <button
                onClick={() => fileRef.current?.click()}
              >Upload something!
              </button>
            </>}
      </div>
    </>
  );
}

export default App;

Bài viết gốc được đăng tải tại vuilaptrinh.com

Bạn có thể xem thêm:

Đừng bỏ lỡ Top việc làm IT trên TopDev nhé

IT Manager Là Gì? Những Điều Bạn Cần Biết Về IT Manager

IT Manager Là Gì? Những Điều Bạn Cần Biết Về IT Manager

Có thể nói, IT hiện đang là một ngành nghề phát triển như vũ bão, thu hút rất nhiều bạn trẻ. Bên cạnh công việc là một lập trình viên, nhiều bạn còn định hướng đi lên các vị trí Senior IT, cụ thể đó là IT Manager. Vậy, IT Manager là gì? Công việc của họ có phải chỉ cần code? Hãy cùng tìm hiểu bài viết dưới đây.

IT Manager là gì?

IT Manager là người chịu trách nhiệm quản lý hệ thống và thông tin của toàn tổ chức, doanh nghiệp. Vai trò của họ liên quan đến việc duy trì sự ổn định và bảo mật các hoạt động công nghệ, theo dõi và quản lý hệ thống phần cứng/phần mềm của công ty. IT Manager thường là người quản lý bộ phận (phòng ban) IT của doanh nghiệp.

Sau đại dịch Covid-19, xu hướng làm việc từ xa ngày càng phổ biến, đặc biệt trong lĩnh vực công nghệ thông tin. Tuy nhiên, IT Manager thường sẽ làm việc tại công ty, một số ít có thể làm việc từ xa. Mặt khác, không giống như lập trình viên, một IT Manager thường tham gia vào những cuộc họp nhiều hơn là chỉ chuyên tâm code. Cụ thể như thế nào, ta cùng tìm hiểu về công việc của họ.

  Xu hướng tuyển dụng IT năm 2024 mà mọi HR Manager cũng như IT Manager cần biết!

IT Manager là gì

Những công việc của một IT Manager

Bạn đã hiểu IT Manager là gì. Hãy thử đoán công việc của họ để xem những điều mình nói sau đây có giống với hình dung của bạn không nhé!

IT Manager là những chuyên gia công nghệ thông tin, người thường xuyên lên kế hoạch, chỉ đạo và giám sát các hoạt động liên quan đến máy tính và hệ thống thông tin của công ty. Họ sẽ phải đảm bảo các hoạt động và dự án công nghệ của doanh nghiệp đang phát triển tốt. Điều này bao gồm nhiều nhiệm vụ khác nhau như:

  • Đánh giá nhu cầu của tổ chức, xem xét nguồn lực hiện tại và lên kế hoạch cải tiến sản phẩm, hệ thống của công ty nhằm nâng cao năng suất, mang lại hiệu quả.
  • Đề xuất đến ban lãnh đạo các phương án cải tiến và nâng cấp, làm rõ những lợi ích chính của các khoản đầu tư dựa trên công nghệ mới đối với doanh nghiệp.
  • Phát triển và giám sát chính sách CNTT, các biện pháp bảo mật và các thông lệ tốt nhất cho công ty.
  • Lên lịch và giám sát các dự án công nghệ như nâng cấp, di chuyển, cập nhật hệ thống hay ngừng hoạt động.

Bên cạnh những công việc mang tính kỹ thuật, IT Manager làm việc với con người khá nhiều. Bởi, họ là người quản lý bộ phận IT của phòng ban và là người chỉ đạo thực hiện các dự án công nghệ. Nhiệm vụ quản lý con người chẳng hạn như:

  • Phân bổ các dự án của công ty cho những nhóm lập trình viên dưới quyền của họ. Bên cạnh đó, người quản lý phải đảm bảo mọi người đang làm việc tốt và cùng nhau đạt được mục tiêu đặt ra.
  • Một công việc khác của IT Manager là đảm bảo nhân viên của công ty có thể làm việc hiệu quả và hoàn thành công việc. Tùy thuộc vào quy mô công ty mà họ sẽ chọn phần mềm hoặc phần cứng để cập nhật mọi thứ từ nhân viên.

Tham khảo việc làm IT manager lương cao trên TopDev

Kỹ năng của IT Manager

IT Manager có phải là vị trí cao nhất?

Trong những tổ chức nhỏ, IT Manager được xem là vị trí cao nhất trong bộ phận  công nghệ. Với những công ty có quy mô lớn hơn, IT Manager thường sẽ báo cáo cho CIO (chief information officer) hoặc IT Director. Do đó, từ vị trí IT Manager bạn có thể xem xét đi lên CIO hoặc IT Director, đây là những chức vụ cao nhất trong bộ phận công nghệ của tổ chức.

  Mẫu CV IT Manager hoàn hảo cho ứng viên ngành IT

Làm thế nào để trở thành một IT Manager?

Bạn có yêu thích làm việc với máy tính không? Bạn có thể làm việc tốt với mọi người không? Nếu câu trả lời là có thì bạn có thể cân nhắc theo đuổi con đường trở thành một IT Manager.

Có nhiều cách để trở thành một IT Manager, bạn có thể xuất phát với tư cách là một Developer, một nhà phân tích kinh doanh hay đơn giản là một người làm việc trong lĩnh vực công nghệ thông tin. Cơ bản, một IT Manager cần phải có bằng cử nhân cộng với kinh nghiệm quản lý một loạt hệ thống CNTT từ hệ thống mạng đến hệ thống phần mềm máy tính để bàn. Bên cạnh đó, bạn cần rèn luyện những kỹ năng như quản lý dự án, kỹ năng lập ngân sách và quản lý nhóm. 

  Program Manager là gì? Học gì để trở thành Program Manager

Hầu hết, trước khi bạn thực sự bước lên vị trí cao nhất bạn sẽ phải bước dần lên từ việc lãnh đạo một nhóm nhỏ hoặc đảm nhiệm một dự án quan trọng. Đảm nhiệm những nhiệm vụ quản lý nhỏ này sẽ giúp bạn quen với ý tưởng điều hành các dự án và hướng dẫn mọi người. Bạn có thể cải thiện kỹ năng quản lý của mình thông qua các chương trình đào tạo nội bộ và hoặc những khóa học bên ngoài.

Tùy thuộc vào quy mô công ty mà họ có thể yêu cầu bạn có những chiến lược và tầm nhìn công nghệ rộng hơn, khi đó bạn có thể xem xét đến bằng MBA. Đặc biệt, nếu bạn định hướng IT Manager là bước đệm cho vị trí CIO, thì MBA là một bằng cấp hữu ích.

Trên đây là định nghĩa IT Manager là gì và những thông tin liên quan đến công việc cũng như cách để trở thành một nhà quản lý công nghệ thông tin. Hi vọng sẽ giúp bạn hình dung được bức tranh tổng quát vị trí này và có thêm định hướng việc làm cho bản thân.

Bạn có thể tham khảo thêm:

Việc làm IT cho Top Developers có ở TopDev nè!

Hướng Dẫn Xây Dựng Trang Đăng Nhập Trong WordPress

Hướng Dẫn Xây Dựng Trang Đăng Nhập Trong WordPress

Bài viết được sự cho phép của tác giả Võ Quang Huy

Bạn cảm thấy giao diện đăng nhập mặc định của WordPress đã quá quen thuộc. Bạn muốn tạo một trang đăng nhập theo style của riêng mình? Bài viết hôm nay, mình sẽ hướng dẫn các bạn các xây dựng một trang đăng nhập trong WordPress.

Tạo trang đăng nhập WordPress

Đầu tiên, bạn phải tạo cho mình một trang đăng nhập. Việc tạo một trang mới trong WordPress chắc mọi người cũng đã biết rồi nhỉ.

Page mình tạo mới trong trường hợp này có tiêu đề là Đăng nhập, và có đường dẫn là domain/dang-nhap.

Tiếp theo, các bạn hãy tạo một file PHP mới có cú pháp page-{slug}.php vào theme đang sử dụng. Cụ thể ở trường hợp của mình là page-dang-nhap.php.

Ngoài ra, bạn còn có thể custom page bằng phương pháp tạo Page Template. Bạn có thể xem lại video hướng dẫn tạo custom page trong wordpress này nếu chưa nắm được nhé.

Hãy thêm đoạn code dưới này vào file PHP bạn mới vừa tạo nhé.

Khởi Đầu Dự Án Python Như Thế Nào Để Thuận Tiện Phát Triển Lên

Khởi đầu dự án Python như thế nào để thuận tiện phát triển lên

Bài viết được sự cho phép của tác giả Nguyễn Hồng Quân

Thỉnh thoảng mình có mối duyên ghé mắt qua các dự án Python, thấy cách sắp đặt vẫn còn chuệch choạc, không có lợi lắm cho việc phát triển tiếp diễn. Nên sau đây mình chia sẻ một số cách thức, công cụ, thư viện mà bạn nên chuẩn bị từ đầu, để công việc sau đó trở nên thoải mái hơn. Cách sắp đặt này có thể coi là chuẩn trong những năm 2020 này (nhưng có thể trở thành lạc hậu sau 5 năm nữa).

1. Quản lý các gói phụ thuộc

Gói phụ thuộc (dependency) là các thư viện / công cụ bên ngoài mà dự án của bạn cần. Các gói này phải được cài trước khi phần mềm của bạn có thể chạy. Ví dụ bạn làm về khoa học dữ liệu thì sẽ cần NumPy, làm web thì sẽ cần Django v.v… Việc một dự án phụ thuộc vào hàng chục gói thư viện khác là chuyện bình thường.

Thông thường các gói này sẽ được liệt kê trong file requirements.txt để khi sao chép dự án sang máy khác thì biết cần cài cái gì. Tuy nhiên, file requirements.txt chỉ là hình thức tối thiểu để quản lý gói phụ thuộc. Nó không đủ để hỗ trợ tình huống phức tạp hơn.

Ví dụ dự án của bạn sử dụng thư viện A phiên bản v1 và B phiên bản v2. Sau vài tháng, nhu cầu nảy sinh, bạn cần thêm tính năng mới, và để làm tính năng mới, bạn cần đến thư viện C. Tuy nhiên thư viện C này cũng lại phụ thuộc thư viện A, và thư viện C đang có nhiều phiên bản, v1 đến v5, mỗi phiên bản của C sẽ thương thích với một phiên bản A khác nhau. Nếu bạn nhắm mắt chọn phiên bản mới nhất của C thì nó sẽ yêu cầu A v3. Bạn không thể mù quáng nâng cấp A lên v3 vì có thể phần mềm của bạn không tương thích và đứt gãy. Nhưng trong 5 phiên bản của C mà thử từng cái một thì rất cực. Đó là lúc bạn cần một thứ nâng cao hơn file requirements.txt.

Một công cụ hiện đại mà mình hay dùng, và khuyên dùng cho tình huống này là Poetry. Khi bạn cần thêm C vào danh sách phụ thuộc, chỉ cần chạy:

$ poetry add C

thì Poetry sẽ tính toán để chọn phiên bản C phù hợp nhất.

  Python call by gì?

Trước khi Poetry ra đời thì có một công cụ khác cũng khá nổi tiếng là Pipenv. Tuy nhiên cá nhân mình không thích Pipenv vì nó tạo thư viện môi trường ảo virtual environment ngay bên trong thư mục dự án. Việc đặt môi trường ảo ngay bên trong dự án này có một phiền phức là khi bạn cần chạy công cụ gì cần quét tất cả các file mã nguồn, nhiều khi nó vô tình quét trúng các file trong thư mục môi trường ảo, nhẹ nhất là làm nhiễu kết quả, nặng nhất là chạy luôn các code trong đó và bắn ra lỗi tùm lum không biết đường nào mà lần.

Việc đặt môi trường ảo ở đâu cũng là một “kinh nghiệm” đáng lưu tâm khi khởi tạo dự án.

Để sử dụng Poetry ngay từ đầu thì bạn có thể dùng các lệnh poetry newpoetry init để nó tạo ra các file cần thiết và cấu trúc thư mục mẫu.

Khi dùng Poetry, có một cái lợi khác là nó sẽ áp dụng file pyproject.toml cho dự án của bạn. Đây là một chuẩn file mới của Python, sẽ là nơi tập trung để lưu cấu hình của các công cụ bổ trợ (kiểm tra code, làm sạch code) trong quá trình phát triển dự án.

ghi log

2. Ghi log

Khi ứng dụng của bạn đã đem ra triển khai, chạy thật, rồi vào một ngày đẹp trời bạn nhận được phản ánh là nó có lỗi, thậm chí có thể nó đang bị lỗi ngay trước mặt bạn. Nhưng bạn không biết chuyện gì xảy ra bên trong phần mềm, chẳng hạn nó đang đọc dữ liệu từ một nguồn nào đó nhưng gặp phải nội dung không mong muốn, không phân tích được và đổ bể. Hoặc là nó đang thực hiện phép toán chia giữa hai biến, và chẳng may biến mẫu số đang là 0, thế là sập.

Để chuẩn bị trước cho những tình huống này, bạn cần làm cho phần mềm ghi ra log, “kể lại” những diễn biến, để sau này khi có sự cố, bạn đọc lại log và có manh mối để biết phải sửa chỗ nào.

Ưu điểm của Python là nó có sẵn thư viện logging trong bộ thư viện chuẩn để các phần mềm tận dụng cho việc ghi log. Nhờ nó là “chuẩn”, các thư viện đều dùng nó nên bạn có thể tùy ý bật tắt log của các thư viện bên dưới mà ứng dụng của bạn đang sử dụng.

  Điều khiển luồng trong Python

Ví dụ, ứng dụng của bạn đang dùng thư viện requests bên dưới, có tình huống mà log từ ứng dụng của bạn ghi ra vẫn không tiết lộ được gì về chuyện gì sai xảy ra bên trong. Bạn cần kiểm tra dữ liệu HTTP mà requests thu nhận được có đúng đắn không. Khi đó bạn chỉ cần tăng cấp độ log (log level) của requests mà không cần đụng vào code của nó, để thấy được chi tiết hơn.

Việc bạn cần làm, chỉ đơn giản thế này:

logger = logging.getLogger('requests')
logger.setLevel(logging.DEBUG)

Thậm chí, bạn có thể điều khiển một module con nào đó của thư viện thôi, để giấu bớt log của các module khác:

logging.getLogger('requests').setLevel(logging.WARNING)
logging.getLogger('requests.api').setLevel(logging.DEBUG)

Khi tham gia làm việc trên một ngôn ngữ khác không có thư viện logging chuẩn như thế này, ví dụ NodeJS, nơi mà mỗi thư viện, mỗi ứng dụng tự chế một cách ghi log riêng, bạn sẽ thấy cách làm của Python hữu ích thế nào.

Tuy nhiên, việc kèm sẵn một thư viện logging trong bộ thư viện chuẩn cũng có bất cập riêng. Đó là Python sẽ không dễ dàng nâng cấp nó, vì sợ sẽ làm đổ bể hàng loạt thư viện / ứng dụng khác. Ví dụ, để chèn nội dung biến vào log, logging trước giờ vẫn dùng cú pháp “%” như sau:

user = get_user_from_facebook()
logger.debug('Got user with name %s and age %d', user.name, user.age)

Vấn đề là, format chuỗi bằng “%s” là phương pháp cũ kĩ, thời v2.5 về trước. Từ v3 (và được backport vào v2.6), Python có cách format chuỗi đơn giản hơn là “{}“. Nếu áp dụng được “{}” vào logging thì code trên sẽ trở thành:

user = get_user_from_facebook()
logger.debug('Got user with name {} and age {}', user.name, user.age)

Vừa nhìn thoáng hơn mà lại không phải lăn tăn suy nghĩ chọn “%s” hay “%d“, “%f“. Tuy nhiên, thư viện logging không thể cải tiến chỗ này, vì sợ thay đổi cái là toàn bộ các thư viện có dùng logging trong hệ sinh thái sẽ sập hết.

Ghi chú: logging có cho phép cấu hình lại để sử dụng “{}“, nhưng việc thực hiện khá rườm rà và trong một dự án phức tạp thì chưa biết độ tương thích với các thư viện khác ra sao.

Ngoài vấn đề dùng “%s” ra thì logging có một điểm trừ là phong cách code với chữ hoa, ví dụ getLoggersetLevel không đồng bộ với phong cách chuẩn PEP8 của Python. Nhìn hơi ngứa mắt nên thực tế, khi làm phần mềm ở tầng “ứng dụng” (application) thì mình dùng logbook thay cho logging. Với logbook thì ngay từ đầu đã có thể dùng “{}” và có phong cách chuẩn PEP8 rồi, ví dụ:

from logbook import Logger

logger = Logger(__name__)


# Some code
# ...

user = get_user_from_facebook()
logger.debug('Got user with name {} and age {}', user.name, user.age)

Tuy nhiên, logbook không phải là thuốc tiên, nếu dùng sai liều là nó sẽ thành thuốc độc, bạn sẽ vò đầu bứt tai cả buổi mà không hiểu tại sao không thấy log đâu. Có một vài điều bạn cần lưu ý khi dùng logbook:

  • logbook có cách chuẩn bị rất khác với logging, với bước gọi handler.push_application(). Với một dự án đồ sộ có nhiều điểm khởi động, ví dụ Django, có các lệnh khác nhau để chạy dev server, WSGI server, job queue, nếu đặt push_application() sai chỗ, bạn sẽ thấy log hiện ra khi chạy từ lệnh này, nhưng lại không hiện khi chạy lệnh kia.
  • logbook được điều khiển độc lập với logging, không dùng chung cấu hình. Nghĩa là nếu bạn điều chỉnh “độ lắm lời” của module nào đó qua logging, nó sẽ không tác động gì đến logbook và ngược lại.
  • Bạn cần quan tâm tới nơi thu gom log cuối cùng (ví dụ ghi vào file hay gửi lên một dịch vụ online nào đấy), và trả lời câu hỏi rằng log từ logbook có cần chảy về chung đầu mối với log sinh ra từ logging hay không. Nếu không, coi chừng khi xem nơi lưu trữ cuối cùng, bạn sẽ hoang mang khi thấy log của hệ này mà không thấy hệ kia.
  • Nếu bạn muốn quy về một mối chung, dùng logbook.compat.LoggingHandler, bạn cần lưu ý một hạn chế của handler này là khi redirect logbook, nó không quan tâm log đó của module con nào, dồn về hết root logger của logging. Tôi đã gửi một pull request để sửa lỗi này nhưng tác giả của logbook không mặn mà nên tôi tự tạo thư viện riêng, chameleon-log để cung cấp handler đã sửa.

Lưu ý: Tôi đã thấy nhiều lập trình viên dùng log rất sai lầm, ví dụ:

user = get_user_from_facebook()
logger.debug(f'Got user with name {user.name} and age {user.age}')
logger.debug('Got user with name {} and age {}'.format(user.name, user.age))
logger.debug('Got user with name ' + user.name + ' and age ' + str(user.age))

Tức là bạn ấy chèn thẳng biến vào chuỗi tham số đầu tiên chứ không phải truyền gián tiếp qua tham số thứ 2, 3. Lý do là chuỗi ở tham số đầu tiên chỉ đóng vai trò “giữ chỗ”. Nếu đang bật cấp độ (log level) phù hợp thì chuỗi đó mới được format với các tham số phía sau để tạo ra message cuối cùng và xuất ra thành log. Nếu bạn chèn thẳng biến vào chuỗi, chuỗi đó sẽ được tính toán, các biến sẽ được xử lý trước khi log level được kiểm tra, làm lãng phí công sức của ứng dụng.

Tham khảo việc làm python Hà Nội lương cao

Thêm một “bí kíp” nữa, là việc chọn điểm thu gom log cuối cùng. Cách cổ điển là khi ra file, nhưng đó không phải là cách hay đâu. Nếu ứng dụng của bạn chạy trên Linux (server hay máy tính nhúng), nên cho nó ghi ra journald, bộ phận quy tập log của systemd. Ưu điểm của việc chuyển log cho journald là:

  • Journald gom log của mọi dịch vụ về một chỗ. Khi bạn đang quản lý hệ thống với nhiều phần mềm, sẽ thật nhức đầu nếu phần mềm này xem log ở chỗ này, phần mềm kia xem log ở chỗ kia. Quy về một mối thì bạn chỉ cần dùng lệnh journalctl -u ten-app là xem được log ứng dụng của bạn rồi.
  • Journald có nhiều phương thức để rà soát log một cách tiện lợi, ví dụ bạn muốn xem kiểu “bám đuổi”, log ghi ra tới đâu, xem ngay tới đó thì dùng lệnh journalctl -fu ten-app (-f nghĩa là “follow”).
  • Nếu bạn không cần bám đuổi mà muốn nó đứng một chỗ (để soi kĩ hơn), nhưng muốn “nhảy cóc” xuống dòng cuối cùng (dòng mới nhất) thì dùng lệnh journalctl -eu ten-app (-e nghĩa là “end”).
  • Khi bạn đang xem log bằng journalctl, bạn có thể tìm chuỗi để nhảy tới nhảy lui, bằng lệnh “/” (tìm xuôi) hoặc “?” (tìm ngược). Thực ra là bạn có thể dùng bất kì lệnh / phím tắt nào của less ở đây.
  • Journald cho phép chọn lọc theo ngày tháng. Chẳng hạn bạn biết rằng 9h tối hôm qua có sự cố. Bạn muốn xem log xung quanh thời điểm đó thôi, bạn có thể dùng --since--until để cắt bớt, ví dụ journalctl -u ten-app --since '2021-08-13 21:00'.
  • Journalctl xác định thời gian bằng thời điểm nó nhận được log, chứ không phải ngày tháng kèm trong log, nên nó “miễn nhiễm” với sự điều chỉnh múi giờ. Chẳng hạn 9h tối qua xảy ra sự cố nhưng thời điểm đó server đang bị cấu hình nhầm múi giờ UTC+8, đến 11 giờ bạn nhận ra múi giờ sai nên vào server chỉnh lại thành UTC+7. Sáng nay bạn cần xem lại log thì không cần tính toán lại giờ theo múi giờ của tối qua.

Dưới đây là hình ảnh log được xem bằng journalctl của một ứng dụng IoT của chúng tôi. Để ý là journalctl tô màu dòng log theo độ nghiêm trọng (log level) để giúp tập trung dễ hơn.

log được xem bằng journalctl của một ứng dụng IoT

Mặc dù bây giờ cũng có phương án là gửi lên các dịch vụ cloud (như StackDriver của Google, CloudWatch của AWS), nhưng tôi không thích dùng chúng, vì thao tác tìm kiếm / nhảy cóc trên journalctl nhanh ra kết quả hơn. Các dịch vụ kia là giao điện web nên mỗi lần tìm kiếm bạn phải chờ trang web tải, rồi bấm vào link này link nọ, rồi lại chờ. Các dịch vụ đó chỉ có giá trị cho việc cài đặt cảnh báo, thống kê . Vì vậy khi cấu hình logging, tôi sẽ dùng hai “handler”, một ghi xuống journald, một để gửi log lên dịch vụ cloud.

Trên đây là một số kinh nghiệm khi tạo dựng từ đầu một dự án Python, nhưng chắc nó cũng đáng giá với các ngôn ngữ khác nữa (chỉ thay đổi phần mềm tương ứng). Kinh nghiệm còn nhiều nhưng hôm nay chỉ ghi ra tới đây thôi. Mốt nhớ ra kể tiếp.

Bài viết gốc được đăng tải tại quan.hoabinh.vn

Xem thêm bài viết:

Hàng loạt công ty tuyển dụng developers trên TopDev

Cobol Là Gì? Tìm Hiểu Về Ngôn Ngữ Lập Trình Cobol

Cobol là gì

Trái với sự phổ biến trong quá khứ, hiện nay ngôn ngữ lập trình Cobol được khá ít người biết đến. Tuy nhiên, có thể nói Cobol là một ngôn ngữ lập trình mang tính khả dụng và hữu ích cao. Để hiểu rõ Cobol là gì, bạn hãy theo dõi nội dung bên dưới.

1. Cobol là gì?

Cobol (Common Business-Oriented Language) là một ngôn ngữ lập trình máy tính thế hệ thứ ba, chủ yếu tập trung vào giải quyết một vấn đề kinh doanh. Ngôn ngữ này thường được sử dụng trong hệ thống kinh doanh, tài chính và hành chính của các công ty và cả chính phủ. 

Cobol được phát triển bởi Hội nghị Ngôn ngữ Hệ thống Dữ liệu (Conference of Data System Languages – CODASYL). Ban đầu, Cobol là lập trình hướng thủ tục (Procedural), nhưng kể từ năm 2002, nó trở thành lập trình hướng đối tượng (Object-oriented).

Cơ bản bạn đã hiểu được Cobol là gì, ứng dụng trong môi trường nào. Vậy, Cobol có những đặc điểm hay ưu nhược điểm gì mà lại được sử dụng phổ biến trong những môi trường như vậy?

2. Đặc điểm ngôn ngữ lập trình Cobol

Những đặc điểm nổi bật của Cobol có thể kể đến như:

  • Tính đơn giản và tiêu chuẩn hóa: Cobol là một ngôn ngữ chuẩn, dễ học. Nó có thể được biên dịch và thực thi trên nhiều loại máy tính. Bên cạnh đó, Cobol còn hỗ trợ lượng lớn từ vựng cấu trúc và có một phong cách mã hóa logic.
  • Khả năng định hướng kinh doanh: Khả năng xử lý tệp nâng cao của Cobol cho phép nó xử lý lượng dữ liệu khổng lồ. Cobol xử lý hơn 70% giao dịch kinh doanh trên thế giới. Từ những báo cáo đơn giản đến các giao dịch phức tạp, việc sử dụng Cobol đều phù hợp và mang lại hiệu quả.
  • Tính phổ quát: Cobol đã thích nghi với sự thay đổi và hoạt động kinh doanh trên nhiều nền tảng và thiết bị. Ngôn ngữ này cung cấp các công cụ gỡ lỗi và kiểm tra cho hầu hết các nền tảng máy tính.
  • Cấu trúc và khả năng mở rộng: Các cấu trúc điều khiển logic có sẵn trong Cobol giúp bạn dễ dàng đọc, sửa đổi và gỡ lỗi. Cobol cũng có khả năng mở rộng, đáng tin cậy và khả năng di động trên các nền tảng.

Không có một ngôn ngữ lập trình nào hoàn hảo tính đến thời điểm hiện tại. Bên cạnh những ưu điểm vượt trội, Cobol cũng có những hạn chế cần phải xem xét:

  • Vì có Source Code lớn nên khi maintain hay chỉnh sửa đọc code sẽ tiêu tốn khá nhiều thời gian và công sức.
  • Hiện Cobol đang dần bị lãng quên do ít người dùng và dường như không còn được phát triển, cải tiến.

Tại đây có Top việc làm IT hấp dẫn cho Top Developers, apply ngay!

3. Cấu trúc chương trình Cobol

Một chương trình Cobol được tổ chức phân cấp theo thứ bậc. Không nhất thiết phải bao gồm tất cả các thành phần trong một chương trình. Mỗi thành phần sẽ bao gồm một hệ hay nhiều thành phần con khác nhau cùng hoạt động như:

  • Division: là phân vùng chính có khối mã lệnh bao gồm một hay nhiều vùng. Trong đó, vị trí bắt đầu là vị trí sau tên gọi phân vùng và vị trí kết thúc là điểm bắt đầu một phân vùng tiếp theo hoặc kết thúc chương trình.
  • Section: một vùng cũng là một khối mã lệnh (nhưng nhỏ hơn phân vùng) thường bao gồm một hoặc nhiều đoạn khác nhau.
  • Paragraph: là một đoạn lệnh của chương trình chính bao gồm một hoặc nhiều câu lệnh.
  • Sentence, Statement: câu lệnh bao gồm một hoặc nhiều mệnh đề khác nhau và kết thúc bằng dấu chấm. Trong đó, một mệnh đề bao gồm một động từ / lệnh Cobol và một hoặc nhiều operand.

Cấu trúc một chương trình Cobol sẽ bao gồm 4 phân vùng (division). Ta có thể lược bỏ một số phân vùng, tuy nhiên phải tuân theo thứ tự như sau:

  • Identification Division: cung cấp thông tin về chương trình cho lập trình viên và trình biên dịch.
  • Environment Division: giúp xác định các tệp đầu vào và đầu ra cho chương trình.
  • Data Division: bao gồm các thông tin khai báo biến dữ liệu
  • Procedure Division: bao gồm các mã lệnh sử dụng dùng để thao tác trên các thành phần dữ liệu đã được khai báo trong Data Division.

Ví dụ Hello World

4. Ví dụ với chương trình “Hello World”

Một ví dụ quen thuộc với tất cả các lập trình viên khi bắt đầu học một ngôn ngữ mới – “Hello World”. Mã chương trình Cobol hiển thị “Hello World” như sau:

000100 IDENTIFICATION DIVISION.
000200 PROGRAM-ID. HELLO.
000300 ENVIRONMENT DIVISION.
000400 DATA DIVISION.
000500 PROCEDURE DIVISION.
000600
000700 PROGRAM-BEGIN.
000800     DISPLAY "Hello world".
000900
001000 PROGRAM-DONE.
001100     STOP RUN.

Bạn có thể hình dung cụ thể như này:

  • Dòng 000100 và 000200: phân vùng Identification Division dùng để nhận diện những thông tin cơ bản về chương trình, ở đây nó chỉ bao gồm PROGRAM-ID, HELLO.
  • Dòng 000300: vùng Environment Division dùng để nhận diện môi trường khi chương trình được thực thi. Cobol có thể chạy được trên nhiều nền tảng, nhiều loại máy khác nhau, và vùng này thường dùng để điều khiển và kiểm soát sự khác nhau giữa những loại máy đó. Trong ví dụ này, chương trình không chỉ ra yêu cầu của một loại máy cụ thể, do đó vùng Environment Division được bỏ trống.
  • Dòng 000400 là vùng dữ liệu Data Division bao gồm những dữ liệu của chương trình. Chương trình này không có dữ liệu nêu vùng Data Division được bỏ trống.
  • Dòng 000500 đến dòng 001100 là các dòng trong vùng Procedure Division. Vùng Procedure Division bao gồm hai đoạn (paragraph) từ dòng 000700 (PROGRAM-BEGIN) và từ dòng 001000 (PROGRAM-DONE). Thuật ngữ paragraph trong Cobol gần như là một hàm hay chương trình con trong một số ngôn ngữ lập trình khác. Tất các những công việc thực sự của chương trình là thực hiện câu lệnh ở dòng 000800.

Một số lưu ý về cách trình bày Code khi lập trình Cobol

  • Mỗi chương trình Cobol có 80 ký tự mỗi dòng
  • Vùng đánh số dòng (line numbers area) : gồm 6 ký tự (cột) đầu tiên của mỗi dòng trong chương trình được sử dụng để đánh số thứ tự các dòng code của chương trình.
  •  Vùng chỉ thị (indicator area) : nằm ở ký tự thứ 7, mô tả phần tiếp theo bằng dấu ‘- hoặc một nhận xét bằng dấu ‘* hoặc dấu ‘/.
  • Vùng A (Area A) : 4 ký tự tiếp theo (8-11) chứa các phân vùng (Division) và các đoạn (Sections). Thông thường vị trí bắt đầu tốt cho phân vùng này là bắt đầu từ cột thứ 8 thay vì các vị trí khác trong vùng A.
  • Vùng B (Area B): gồm các ký tự có vị trí từ 12 đến 72. Các câu lệnh phải bắt đầu và kết thúc trong vùng B này.
  • Vùng không chỉ định: bao gồm các ký tự từ vị trí 73. Những ký tự này sẽ không được xét trong chương trình.

Trên đây là những kiến thức tổng quan xoay quanh khái niệm Cobol là gì. Cobol không phải là một ngôn ngữ lập trình hợp thời như Python nhưng nó là một ngôn ngữ quan trọng. Hi vọng những thông tin trên sẽ giúp ích cho bạn trong việc đưa ra quyết định có nên học Cobol.

Những bài viết này cũng hay nè:

Đừng bỏ lỡ Top việc làm IT trên TopDev nhé!

3 Cách Làm Border Gradient Trong CSS Mà Bạn Nên Biết

3 Cách Làm Border Gradient Trong CSS Mà Bạn Nên Biết

Bài viết được sự cho phép của tác giả Trần Anh Tuấn

Ở bài viết này mình sẽ chia sẻ cho các bạn 3 cách code border gradient trong CSS, không giới thiệu dài dòng, mình đi thẳng vào từng cách một luôn nhé ⚡️

Chúng ta sẽ có HTML và CSS cơ bản như sau

<div class="boxed"></div>
.boxed{
width: 300px;
height: 300px;
background-color: black;
}

Border image slice

Với cách này thì chúng ta sẽ sử dụng 2 thuộc tính trong CSS đó chính là border-image-slice và border-image-source, cách này nhanh gọn lẹ nhất, tuy nhiên có một nhược điểm đó chính là không dùng được với border-radius(khi làm bo góc)

.boxed {
width: 200px;
height: 200px;
border: 10px solid;
border-image-slice: 1;
border-image-source: linear-gradient(to right bottom, #6a5af9, #f62682);
}

Chúng ta sẽ có kết quả như sau

Sử dụng border image để tạo border gradient
Sử dụng border image để tạo border gradient

Dùng thêm thẻ con bên trong

Trường hợp này thì chúng ta sẽ dùng một trick đó chính là tạo background gradient cho .boxed bình thường, sau đó thêm padding tương ứng cho độ dày của border, và bên trong tạo thêm 1 thẻ html ví dụ là .boxed-child chẳng hạn và cho nó màu nền trùng với màu nền của body

<div class="boxed">
<div class="boxed-child"></div>
</div>
.boxed {
width: 200px;
height: 200px;
background-image: linear-gradient(to right bottom, #6a5af9, #f62682);
padding: 10px;
border-radius: 10px;
}
.boxed-child {
width: 100%;
height: 100%;
background-color: #191a28;
border-radius: inherit;
}

Chúng ta sẽ có kết quả như dưới đây kèm bo góc luôn, tuy nhiên cách làm này không hay, vì đôi khi chúng ta không được phép thêm HTML vào bên trong thì sao, vì thế sẽ có cách số 3 đó chính là sử dụng lớp giả :before hoặc :after để xử lý.

Sử dụng thêm thẻ html để tạo border gradient
Sử dụng thêm thẻ html để tạo border gradient

Sử dụng before hoặc after

Nếu buộc phải có bo góc thì mình nghĩ dùng cách này là ổn áp nhất và chúng ta sẽ có code CSS như sau, các bạn chú ý những thuộc tính quan trọng đó chính là background-clip: padding-box và chỗ margin: -10px nó sẽ tương ứng cho border: 10px ví dụ border 20px thì margin sẽ là -20px nhé.

.boxed {
width: 200px;
height: 200px;
position: relative;
background-clip: padding-box;
border: 10px solid transparent;
background-color: #191a28;
border-radius: 20px;
} .boxed:before {
content: "";
position: absolute;
inset: 0;
z-index: -1;
margin: -10px;
background-image: linear-gradient(to right top, #2979ff, #07a787);
border-radius: inherit;
}

Và đây là kết quả

Sử dụng before để tạo border gradient
Sử dụng before để tạo border gradient

Trên đây là 3 cách tạo border gradient trong CSS mà mình biết, hi vọng sẽ có ích cho các bạn nhé.

Bài viết gốc được đăng tải tại evondev.com

Những bài viết này cũng hữu ích lắm nè:

Top Developers đừng bỏ lỡ cơ hội việc làm IT trên TopDev nhé!

 SHIFT ASIA Quản Lý Dự Án Hiệu Quả Với Công Cụ GITLAB

QUẢN LÝ DỰ ÁN HIỆU QUẢ VỚI CÔNG CỤ GITLAB

Là công ty IT outsourcing năng động với nhiều dự án đa ngành mang tầm quốc tế, việc quản lý hiệu quả các dự án của khách hàng và tăng tính kết nối, làm việc nhóm giữa các lập trình viên luôn là ưu tiên hàng đầu tại SHIFT ASIA. Nhằm mang đến sự hiệu quả và thuận tiện trong việc quản lý dự án, SHIFT ASIA đã và đang sử dụng GitLab như một công cụ cần thiết khi phát triển phần mềm. Ngoài ra, các lập trình viên tại SHIFT ASIA còn sử dụng GitLab như một kỹ năng không thể thiếu trong công việc của mình. Hãy tìm hiểu xem tại sao GitLab có vai trò quan trọng như vậy và SHIFT ASIA đang sử dụng GitLab hiệu quả như thế nào với bài chia sẻ từ anh OTIS HỒ – Senior Software Developer tại SHIFT ASIA nhé.

Anh OTIS – Senior Software Developer từ SHIFT ASIA
Anh OTIS – Senior Software Developer từ SHIFT ASIA với nhiều năm kinh nghiệm về lập trình qua nhiều môi trường làm việc khác nhau. 

GitLab là gì?

GitLab là một hệ thống quản lý phát triển và triển khai phần mềm tự động. Lõi của GitLab là phần mềm Git, một phần mềm giúp quản lý phiên bản mã nguồn và lịch sử thay đổi mã nguồn. GitLab còn cung cấp công cụ quản lý yêu cầu kết hợp chặt chẽ với công cụ Git để giúp nhà phát triển dễ dàng theo dõi mã nguồn được phát triển tương ứng với yêu cầu nào. Với GitLab, mọi thành viên trong dự án có một công cụ chung để theo dõi tiến độ, review code và triển khai môi trường. GitLab giúp mọi thành viên trong dự án có thể tập trung vào chuyên môn của mình.

Các tính năng nổi bật của GitLab

Issues Management

GitLab cung cấp tính năng quản lý yêu cầu/công việc, các yêu cầu có thể được viết dưới định dạng Markdown, thuận tiện cho các lập trình viên và người quản lý dự án có thể đọc hiểu nội dung của dự án. Tính năng quản lý yêu cầu có bảng phân công công việc theo chuẩn quy trình Scrum Master, giúp dễ dàng quản lý, phân phối công việc, hoàn thành dự án lập trình chất lượng hơn. Các yêu cầu có thể liên kết với nhau (Linked issues), giúp cho quản lý có thể dễ dàng nhận ra blocker issues, duplicated issues. Mỗi một yêu cầu sẽ được tương ứng với một nhánh (Branch) do lập trình viên thực thi, và thời gian lập trình viên thực thi trên branch đó có thể được lưu lại dễ dàng với command-line được cung cấp bởi GitLab.

Code Review – Teamwork

GitLab cung cấp giao diện thân thiện giúp trưởng nhóm kỹ thuật (Technical Leader) có thể đánh giá mã nguồn của các thành viên một cách dễ dàng và nhanh chóng. Việc đánh giá mã nguồn và xử lý các phản hồi diễn ra nhanh chóng và được lưu lại cho việc truy hồi trong tương lai.

GitLab CI/CD

Là công cụ giúp phần mềm được triển khai (Continuous Development) và tích hợp (Continuous Integration) một cách liên tục. Trước đây, bạn phải có một công cụ CI/CD riêng lẻ (Jenkins, Circle CI, TravisCI), thì với GitLab CI/CD bạn dễ dàng cập nhật liên tục phiên bản mới nhất của phần mềm. Ngoài ra, công cụ GitLab CI/CD còn giúp bạn có thể chạy nhiều tác vụ xử lý tuần tự (Pipeline), bao gồm xây dựng (Build), kiểm tra tự động (Automation Test) và triển khai (Deployment) phần mềm lên môi trường production.

Minh họa quy trình CI/CD trên GitLab
Minh họa quy trình CI/CD trên GitLab

Code Analytics

GitLab CI/CD còn cung cấp công cụ phân tích mã nguồn giúp nhà phát triển có thể phát hiện những mã nguồn thiếu chất lượng, có thể tạo ra lỗi tiềm tàng trong tương lai.

Tại SHIFT ASIA GitLab đang được sử dụng như thế nào?

Hiện tại SHIFT ASIA đang sử dụng GitLab cho hầu hết các dự án của mình.

  1. SHIFT ASIA xây dựng một phiên bản GitLab trên hệ thống máy chủ nội bộ của SHIFT ASIA và chỉ có những thành viên của dự án mới có thể truy cập vào mã nguồn của dự án.
  2. GitLab tích hợp các tính năng cần thiết cho bất kỳ yêu cầu dự án nào:
  • CI/CD: tự động xây dựng và chạy kiểm thử đơn vị (Unit Test) khi có yêu cầu tổng hợp mã nguồn từ một nhánh đang phát triển vào nhánh chính (master branch). Việc này giúp cho mã nguồn được đảm bảo về mặt chất lượng trước khi được bàn giao.
  • Issues Management: GitLab hỗ trợ việc quản lý yêu cầu/công việc của dự án với các tính năng vượt trội như liên kết các thay đổi trên mã nguồn với lại công việc tương ứng, thông báo trạng thái mã nguồn đã được tổng hợp vào nhánh chính giúp việc theo dõi và quản lý task được thuận tiện hơn.

Với việc sử dụng GitLab trong hầu hết các dự án của mình, SHIFT ASIA mang đến những dịch vụ phát triển phần mềm với chất lượng tốt nhất. GitLab giúp SHIFT ASIA có “SHIFT LEFT” một cách hiệu quả trong việc phát triển phần mềm. Với việc ưu tiên “SHIFT LEFT”, công ty luôn tạo cơ hội cho các lập trình viên được học hỏi và trao dồi thêm các kiến thức không chỉ liên quan đến phát triển phần mềm mà còn liên quan đến kiểm thử (Testing), triển khai liên tục (CI/CD) và hạ tầng (Infrastructure). Chính việc này một lần nữa khẳng định slogan của công ty: Crazy For Quality!

Bài viết mới cập nhật:

Đừng bỏ lỡ Top tin tuyển dụng IT hấp dẫn tại TopDev nhé!

 

Lạm Bàn Về Mindset

Làm bàn về mindset

Bài viết được sự cho phép của tác giả Nguyễn Văn Trọng

Mindset là gì thì chắc ai cũng nghe tới, nhưng có thực sự hiểu rõ về nó không thì cũng cần phải đào sâu một chút. Trong bài viết này mình sẽ đi vào các tình huống thường gặp trong công việc để các bạn có cái nhìn gần hơn về tác động tốt-xấu của nó.

Vì Sao Mindset Lại Cần Thiết

ví dụ về mindset tệ

Hãy cùng xem ví dụ về mindset tệ. Có thể mọi người sẽ cười nhưng trong thực tế thì không hiếm đâu, thậm chí nhiều là đằng khác. Ai cũng nói về đam mê, nhưng ít khi nào thành công tách rời với trách nhiệm. Một người có mindset sai, thiếu tinh thần trách nhiệm sẽ để lại hậu quả cực kỳ nghiêm trọng không chỉ cho bản thân mà còn “đào hố” đồng đội.

Riêng trường hợp ngồi chơi 4 ngày làm 1 ngày thì đôi khi lại do tính chủ quan, tự tin thái quá. Đúng ra nếu tự tin làm trong 1 ngày thì nên nói với PM/Team Lead là “task này dễ quá, cho em thêm vài cái nữa làm cho vui”. Sợ bị bốc lột? kệ chứ, còn trẻ ai muốn bốc gì bốc. Cứ cắm đầu làm chả lo thiệt thân đâu. Với leader giỏi thì họ nhìn là biết ngay ai chăm chỉ, tất nhiên là được việc nữa chứ chỉ chăm thôi thì chưa đủ. Còn gặp leader tệ quá, họ không thấy bản thân ưu tú thì bảo họ nhường chỗ cho mình lên thay muahaaaa … giỡn chứ đôi lúc người ta nhiều cái để lo nên không để ý, mình nhắc khéo, không được mới tìm phương án khác như … nhảy việc.

ví dụ về mindset tốt

Đây mới gọi là tốt. Thực ra trong ví dụ này mình chỉ đưa ra có vài ý tiêu biểu, đằng sau đó còn nhiều nữa các bạn cứ tự suy nghĩ cách đối ứng sao cho phù hợp. Trong các ý trên thì nên làm lần lượt, đầu tiên là phân tích – tự ước lượng công việc (estimate), kỹ năng này sẽ giúp ích rất nhiều cho công việc BrSE sau này khi phải estimate dự án lớn. Vì có lớn cỡ nào mình cũng bẻ nhỏ ra được, ước lượng từng cái một rồi ghép lại là xong, ai bảo estimate khó thì chắc họ chỉ tỏ ra nguy hiểm thôi.

Như trên là tình huống trong công việc, còn to tát hơn như sự nghiệp thì phải làm sao ?
Dạo trước có nói chuyện với một cậu DEV, em nó bảo ước mơ sau này sẽ trở thành kỹ sư công nghệ hàng đầu, tạo ra một sản phẩm thật hoành tráng. Nhưng khi mình hỏi lại một số câu cơ bản thì câu trả lời hầu như là không/chưa.

C1. Em có chắc chắn với hướng đi của mình là đúng không ? CÓ

C2. Em đã có kế hoạch gì với việc đó chưa ? CHƯA

C3. Em hiểu thế nào là kỹ sư công nghệ hàng đầu, họ là người như thế nào, mỗi ngày họ làm gì/học gì, bằng cách nào họ trở thành số 1 (từ số 0) chưa ? CHƯA

C4. Thế theo em một sản phẩm hoành tráng là như thế nào ? và làm sao/mất bao lâu để tạo ra nó ? ẤP ÚNG

C5. Em có đang làm tốt những thứ cơ bản của lập trình như đặt tên biến, comment mô tả xử lý, optimize source, commit source hàng ngày lên GIT … cũng như những thứ cao cấp hơn xíu xíu như SOLID/Design Patterns chưa ? cái cơ bản thì có nhưng vụ khai báo biến hơi loạn, còn SOLID là cái gì thì em chưa nghe qua.

C6. Ngoài công việc ra em có code thêm gì để luyện tay hoặc tham gia khoá học nào để nâng cao không ? Việc làm không hết thời gian đâu mà luyện với học thêm anh.

Cách làm đúng như hình bên dưới.

plan phát triển sự nghiệp

Việc hiểu sở trường – sở đoản của bản thân nói thì dễ, thực tế không nhiều người nhận ra được, thậm chí ngộ nhận. Biết là ai sinh ra cũng có điểm mạnh yếu riêng, các “diễn giả” dạy làm giàu nói hoài. Bởi vậy nên chúng ta cần kiểm chứng bằng cách thử – sai – thử lại – sửa … cho tới lúc cảm nhận được mình muốn gì, mình cần gì và mình mạnh yếu chỗ nào. Khi đã hiểu rõ (có thể mất vài năm thậm chí hàng chục năm) thì già cmn rồi :))) , giỡn chứ lúc ấy mình quyết tâm đi theo nó tới cùng ắt sẽ để lại thành tựu gì đấy.

Định Nghĩa – Phân Loại

mindset là gì

Mindset đơn giản là tư duy. Đối với mỗi tình huống cụ thể, mỗi người sẽ có một cách xử lý khác nhau, có tốt có xấu. Và điểm khác nhau được tạo ra bởi mindset. Ví dụ thì như trên, còn nếu các bạn chưa hiểu rõ lắm thì mình đưa ra thêm tình huống này cho dễ hình dung:

Bạn A được giao cho làm module login trong 3 ngày, bạn cắm đầu làm rất chăm chỉ nhưng tới gần lúc giao hàng thì báo lại là “anh ơi ! em làm không kịp”, chắc phải thêm 3 ngày nữa mới xong, ông PM B mắng mỏ làm bạn bỏ luôn không làm nữa.

Các bạn nghĩ mình đang nói tới bạn A hả, nhầm rồi :))) đang muốn nhắm tới ông PM B. Việc đầu tiên không phải là mắng mem của mình, mà tìm cách khắc phục, đầu tiên là tìm nguyên nhân chậm, sau đó check lại coi thêm 3 ngày nữa có kịp không hay là 4-5 ngày. Check các dữ kiện cần thiết và báo lại cho các bên liên quan, sau khi xử lý sự cố ổn thoả thì mới quay lại khiển trách và bảo bạn A rút kinh nghiệm, lần sau nhớ báo sớm để anh còn xử lý. Hình như đọc ví dụ xong không hình dung được thêm gì, mà thôi kệ.

Tiếp theo là phân loại, theo sách vở thì có 2 loại như bên dưới.

phân loại mindset

Nhìn hình cũng hiểu rồi đúng không ? Growth và Fixed. Cái khó ở đây là phần đông mỗi người rơi vào trạng thái lấp lửng, chả biết mình thuộc loại nào, đôi khi tự nhận là Growth mà thực tế hay bị Fixed (Xin lỗi mình dùng tiếng anh đoạn này vì là thuật ngữ). Và việc loại bỏ cảm giác tự ti về xuất phát điểm là cực khó, nó ăn sâu thành nếp rồi nên không thể bảo bỏ là bỏ ngay được, cần thời gian.

Cách tốt nhất để thay đổi tư duy là tiếp xúc với những người đẳng cấp, có cơ hội gặp gỡ, nói chuyện hỏi han với họ là bắt lấy, đừng có ngại, lớn rồi ai chơi trò ngại ngùng. Sau mỗi lần như vậy ta sẽ thay đổi vì muốn được như họ, và những người đó thường có nguồn năng lượng (nội công) rất mạnh mẽ có thể truyền sang bản thân mình (kể cả online) <= Đoạn này nói xạo đấy, đừng tin.

Các Bước Nâng Cao Mindset

Phần 1 và 2 mình đã phân tích thông qua các vị dụ, mặc dù hơi xạo xíu xíu nhưng nhìn chung cũng giúp các bạn tới gần hơn bản chất và tác động của mindset lớn như thế nào. Bây giờ vấn đề là làm sao để nâng cao nó.
Việc tiếp xúc với người đẳng cấp – hào hoa phong nhã xinh đẹp ngời ngời (mình chỉ được duy nhất cái đẹp trai, buồn!) thì khó, và có gặp cũng chỉ 1 vài lần nó chả thấm vào đâu. Vậy nên quay về với thực tại với 2 đối tượng : 1 là bản thân, 2 là “những người sống quanh tôi”.

sơ đồ các bước nâng cao mindset

“Bất kể tuổi tác”, nói thì dễ, mấy ông lớn lớn tuổi chút là coi mấy đứa em không ra gì, chuyên áp đặt suy nghĩ và còn khinh thường vì người ta ít trải nghiệm. Thực tế là vậy. Hiếm người nào 30 40 mà lại đi học hỏi cậu em 20 – 25.

Nhìn nhận sự việc theo hướng đa chiều – tích cực. Ví dụ như này : làm việc với ông khách khó tính suốt ngày soi mói chửi rủa. Vậy điểm sáng ở đây là gì : Tại ông khó quá nên mình sẽ có trải nghiệm làm với khách khó, sau này gặp người khác bớt khó hơn thì coi như là dễ. Nghĩ theo cách đấy đời tươi sáng hẳn.

Tiếp theo là nhìn nhận bản thân, đánh giá định kỳ mỗi 6 tháng – 1 năm – 2 năm, chu kỳ anh em tự đặt tuỳ mục tiêu lớn hay nhỏ. Rồi tự đặt ra thật nhiều câu hỏi, tự trả lời không được thì mang đi hỏi. Nhớ hay hỏi câu nào cho có giá trị tí chứ mấy câu mà google 1 phát đầy ra thì khỏi cần.

Và bước cuối cùng, củng cố – nâng cao tư duy thông qua học tập – hành động. Học thì có nhiều cách, học qua công việc – qua cuộc sống, thậm chí tham gia khoá học kỹ năng cũng không phải lựa chọn tồi. Mình không có ác cảm gì với các ông thầy dạy làm giàu cả, chỉ trêu cho vui, nhiều cái họ nói không sai (cũng có cái bốc phét), nghe và kiểm chứng rồi kết luận. Rồi qua hành động, chính là công việc thường ngày, sau mỗi quyết định thì chờ kết quả nó “nổ” ra rồi rút kinh nghiệm sâu sắc, lần sau làm khác đi. Có thể tiếng “nổ” sẽ to hoặc nhỏ hơn, nếu to quá thì lại tìm cách khác cho tới khi hài lòng. Đó chính là việc nâng cấp bản thân thông qua trải nghiệm : thử – sai – sửa …

Kết

Lâu ngày không viết cứng tay quá. Tính ra cũng cả năm trời rồi chứ có ít đâu, từ ngày ra sách cái vênh mặt lên bỏ luôn blog, tội lỗi. Mình sai thì nhận, và tìm cách sửa sai bằng việc hàng tháng 1 bài blog ra đều đặn.

Nói về mindset thì còn nhiều lắm, ví dụ đưa ra cả ngày không hết. Trong mỗi tình huống đều có nhiều đáp án, không có cái nào đúng hoàn toàn và sai hoàn toàn cả, ở mức tương đối. Điều quan trọng nhất là mình cần phải dẹp bỏ ngay thái độ tự ti về xuất phát điểm (địa vị, kỹ năng, hoàn cảnh gia đình), phải luôn nghĩ rằng dù đang đứng ở đâu đi chăng nữa thì nếu muốn tới đích hãy nhấc chân lên và đi. Cho dù khó khăn cỡ nào cũng không dừng lại (dừng nghỉ chút thì được). Cho tới 1 ngày nhìn lại mình đã cách xa đích hơn, nhầm… mình càng tới gần đích hơn, và lấy đó làm động lực để đi tiếp. Thành công = 10% Đam mê + 90% trách nhiệm = 10% năng khiếu + 90% khổ luyện, cái này cũng là của mấy ông thầy dạy làm giàu nè. Vậy nhé, khi nào nghĩ ra cái gì hay thì mình lại viết tiếp.

Bài viết gốc được đăng tải tại kysubrse.com

Bài viết liên quan

Top Developers đừng bỏ lỡ Top việc làm IT trên TopDev nhé!

Cách Sử Dụng Middleware Trong NextJS

Cách sử dụng Middleware trong NextJS

Bài viết được sự cho phép của tác giả Phạm Minh Khoa

Middleware là những đoạn mã trung gian nằm giữa các request và response, nó nhận các request, thi hành các mệnh lệnh tương ứng trên request đó. sau khi hoàn thành nó sẽ response (phản hồi) hoặc chuyển kết quả ủy thác cho 1 Middleware khác trong hàng đợi.

Middleware là gì

Trong NextJS, middle mới chỉ được thêm vào từ version 12.0.0 (cho bản beta), tài liệu chính thức của nó được mô tả trên trang chủ của NextJS tại link: https://nextjs.org/docs/middleware

Bài viết này mình sẽ giải thích qua cách sử dụng của nó và tạo thử 1 ví dụ cho các bạn dễ hình dung.

Cách sử dụng

Để sử dụng middleware thì chúng ta tạo file _middleware.ts nằm trong thư mục pages của dự án.

Sau khi tạo xong chúng ta sẽ copy đoạn code typescript như dưới đây vào:

// pages/_middleware.ts

import type { NextFetchEvent, NextRequest } from 'next/server'

export function middleware(req: NextRequest, ev: NextFetchEvent) {
  return new Response('Hello, world!')
}

Nếu bạn thích viết bằng javascript thì dùng đoạn code dưới đây

// pages/_middleware.js

const middleware = (req, ev) => {
  return new Response('Hello, world!');
};

export default middleware;

Dev chốt ngay Top việc làm Front-end tại TopDev

API

Middleware API dựa trên các đối tượng gốc:

  • FetchEvent: https://developer.mozilla.org/en-US/docs/Web/API/FetchEvent
  • Response: https://developer.mozilla.org/en-US/docs/Web/API/Response
  • Request: https://developer.mozilla.org/en-US/docs/Web/API/Request

Các bạn nên quan tâm đến thằng NextResponse, nó cung cấp cho chúng ta 4 phương thức trong middleware:

  1. redirect(): chuyển hướng request từ route này đến 1 route khác
  2. rewrite(): viết lại response của bạn
  3. next(): tiếp tục sang 1 middleware khác trong chuỗi (middleware chain)
  4. json(): trả về JSON response hoặc dữ liệu
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

export function middleware(req: NextRequest) {
  // if the request is coming from New York, redirect to the home page
  if (req.geo.city === 'New York') {
    return NextResponse.redirect('/home')
    // if the request is coming from London, rewrite to a special page
  } else if (req.geo.city === 'London') {
    return NextResponse.rewrite('/not-home')
  }

  return NextResponse.json({ message: 'Hello World!' })
}

Chi tiết các bạn có thể xem thêm doc của NextJS dưới đây:

https://nextjs.org/docs/api-reference/next/server

Ví dụ sử dụng

Giả sử chúng ta muốn xây dựng 1 trang thông báo với user rằng trang web hiện tại đang trong quá trình xây dựng (hoặc đang bảo trì, .. coming soon).

Để giải quyết bài toán, chúng ta sẽ tìm cách điều hướng tất cả các request đến website sang 1 trang thông báo trang đang xây dựng.

Trước hết chúng ta tạo 1 pages là underConstraction.js. Source code các bạn tự tùy biến theo ý bạn thích nhé (đơn giản là hiển thị thôi mà)

Tiếp đó chúng ta sẽ thực hiện logic điều hướng trong middleware

import type { NextFetchEvent, NextRequest } from "next/server";
import { NextResponse } from "next/server";
// In rewrite method you pass a page folder name(as a string). which // you create to handle underConstraction  functionalty.
export function middleware(req: NextRequest, ev: NextFetchEvent) {
  return NextResponse.rewrite("/underConstraction");
}

Ở đây các bạn cũng có thể dùng phương thức redirect, khác nhau ở chỗ nó sẽ thay đổi path (đường dẫn) hiển thị trên trình duyệt thôi.

Khi nào các bạn đã hoàn thiện website, không cần thông báo cho user nữa thì chỉ cần chỉnh sửa lại middleware của mình chút là được.

// you just call next() method to contious middlerware chain or call nextjs default middleware. your blog website file.
export function middleware(req: NextRequest, ev: NextFetchEvent) {
return NextResponse.next();
}

Đơn giản và tiện dụng đúng không ạ. Ngoài ví dụ đơn giản trên thì các bạn có thể xem thêm các ví dụ sử dụng middleware trong NextJS từ examples trên trang chủ:

https://github.com/vercel/examples/tree/main/edge-functions

Cảm ơn các bạn đã đọc.

Bài viết gốc được đăng tải tại anywayblogs.com

Theo dõi những bài viết mới của TopDev nhé

Đừng bỏ lỡ tin tuyển dụng IT lương cao trên TopDev!

Mechanical Sympathy Là Gì? Lập Trình BackEnd bằng Java

Mechanical sympathy là gì

Bài viết được sự cho phép của tác giả Trần Văn Dem

Khi lập trình backend bằng ngôn ngữ Java, nếu muốn chương trình chạy nhanh hơn chúng ta sẽ sử dụng khái niệm multithreading để tăng hiệu năng tổng thể của chương trình. Tuy nhiên khi sử dụng multithreading cũng sẽ gây ra các sai lầm về mặt dữ liệu nên chúng ta sẽ sử dụng các kỹ thuật như lock , synchronized để đảm bảo việc đó. Nhưng sử dụng các cơ chế này sẽ gây giảm hiệu năng chương trình của bạn xuống.

Các CPU hiện nay hỗ trợ rất tốt cho lập trình đa luồng nhưng hiểu rõ cách hoạt động của CPU sẽ giúp chương trình của bạn sẽ nhanh và chính xác hơn. Việc hiểu cách hoạt động của CPU để viết phần mềm tận dụng hết khả năng của phần cứng được biết đến với tên mechanical-sympathy. Bài này sẽ giúp mọi người hiểu rõ hơn về CPU, cách lập trình đa luồng tốt hơn.

Cách CPU xử lý dữ liệu

Sau đây là kiến trúc cơ bản của một CPU

kiến trúc cơ bản của một CPU

Tại đây chúng ta thấy một CPU sẽ sử dụng chung một bộ nhớ cache L3. Các bộ nhớ L1,L2 sẽ là của riêng các core trong cpu. Tốc độ cpu truy cập các bộ nhớ L1,L2,L3 sẽ giảm dần và độ lớn của bộ nhớ cache L1,L2,L3 sẽ tăng dần. CPU sẽ không Load dữ liệu trực tiếp từ RAM để xử lý vì hành động này sẽ rất tốn thời gian. Khi cần thao tác với 1 biến thì CPU sẽ tìm tại bộ nhớ L1L2L3 nếu không có thì mới load từ RAM vào các bộ nhớ cache trên.

CPU sẽ không load dữ liệu cơ bản mà sẽ load theo dạng Cache lineCache line này thường sẽ là 64b

Ví dụ Cache line

Lý do CPU load dữ liệu theo Cache line bởi vì nó có thể tận dụng được 1 lần load được nhiều dữ liệu hơn và nếu các phép tính toán cần sử dụng các loại dữ liệu này thì sẽ không được load lại.

Ví dụ khi chúng ta duyệt giá trị trong 1 Array thì các phần tử Array sẽ được xếp cạnh nhau trong memory nên khi load vào để tính toán sẽ được load theo Cache line điều đó sẽ tăng performance của CPU. Với Java khi chúng ta khai báo biến nguyên thủy trong 1 Object thì các biến đó sẽ được xếp cạnh nhau trên RAM, với các biến Object thì chỉ chứa Reference chứ nội dung của nó sẽ được lưu ở chỗ khác tại memory*.

Xem tin tuyển dụng Java mới nhất trên TopDev

False Sharing

Nếu 2 biến X,Y cùng nằm trên 1 Cache line , Thread 0 sử dụng và thay đổi giá trị của biến X và xảy ra trước khi Thread 1 sử dụng biến Y. Điều này sẽ khiến Cache line bị CPU sẽ đánh dấu là Invalid và điều đó sẽ khiến Core 2 bắt buộc phải Load lại Cache line trước khi sử dụng biến Y. Điều trên được gọi là False Sharing.

False Sharing thực sự sẽ ảnh hưởng đến hiệu suất chương trình của bạn vì nó khiến Core load lại CacheLine nhiều lần điều đó sẽ càng phức tạp nếu nhiều hơn 2 luồng và mỗi luồng sẽ lại thay đổi 1 biến trên cache line. Vậy nên trước khi tăng tài nguyên thì hãy chắc chắn rằng chương trình bạn viết không bị False Sharing. Các bộ profile của intel sẽ cho bạn biết chương trình có đang bị False Sharing hay không nhưng có 1 cách đơn giản hơn khi lập trình MultiThread là hãy cố thiết kế hệ thống sao cho các Thread của bạn không sử dụng chung các object. Mỗi luồng sẽ có 1 bộ dữ liệu riêng để truy cập thay vì chia sẻ chung 1 ArrayMapObject,…

Tham khảo tại link dưới dây để đo hiệu năng khi chương trình bị False Sharing :

  • mechanical-sympathy.blogspot.com/2011/07/fa..
  • mechanical-sympathy.blogspot.com/2011/08/fa..

duration false sharing

Race condition

Khái niệm race condition thì chắc hẳn ai code multi threading cũng biết và biết các cách chống lại điều này. Nhưng chắc cũng không ít anh em đọc đến False Sharing sẽ thấy lú là sao đã có False Sharing rồi nhưng lại có thể race condition được. Các CPU của intelamd sẽ có 1 giao thức để thực hiện invalid cachelineMESI Protocol tham khảo tại:

  • cs.utexas.edu/~pingali/CS377P/2018sp/lectur…
  • people.cs.pitt.edu/~melhem/courses/2410p/ch..

Protocol này được mô tả rất kỹ trong 2 link trên hoặc mọi người hãy search google để tìm đọc thêm về protocol này. Tóm tắt lại Protocol này sẽ đánh dấu cache line có 4 state sau :

  • Invalid (uncached)
  • Shared
  • Exclusive
  • Modified

Đây là mô tả chương trình của chúng ta khi bị race condition

CYCLE # CORE 1                        CORE 2
0   reg = load(&counter);   
1   reg = reg + 1;                reg = load(&counter);
2   store(&counter, reg);         reg = reg + 1;
3                                 store(&counter, reg);

0 reg = load(&counter);

CORE1 load counter vào bộ nhớ cache. Đánh dấu Cacheline là Exclusive

1 reg = reg + 1; reg = load(&counter);

CORE1 tăng biến regCORE2 load biến counter vào cache. Tại thời điểm này cả 2 Cacheline là Shared

2 store(&counter, reg); reg = reg + 1;

CORE1 lưu giá trị mới cho biến counterCORE2 thực hiện tính toán. Tại thời điểm này CORE1 đánh dấu cache line là Modified, ngay sau đó CORE 2 sẽ nhận được cacheline đã bị thay đổi và đánh dấu cho Cache line là Invalid.

3 store(&counter, reg); Vì Cache line đã bị invalid nên CORE2 thực hiện load lại biến counter trước khi thực hiện hành động store. Và biến counter đã được CORE1 lưu lại trước đó nên tại đây CORE2 sẽ thực hiện lưu lại giá trị của CORE1 đã lưu.

Sau cùng cacheline của CORE1 sẽ là Invalid và CORE2 sẽ là Modified. Vì CORE1 đã thực hiện xong hành động nên khi được mark là Invalid lần tính toán sau CORE1 sẽ load lại cacheline này.

Vậy khi sảy ra trường hợp race condition chương trình chúng ta sẽ đưa ra một kết quả sai và tệ hơn nữa nó lại gây cho CORE thực hiện load lại nhiều lần cacheline vào trong bộ nhớ cache của mình.

Happens-before relationship Java

Trong Lập trình đa luồng của Java cung cấp cho chúng ta khái niệm happens-before relationship.

Trước khi tìm hiểu Happens-before relationship ta sẽ tìm hiểu về cách CPU thực hiện Instruction Reordering.

Các CPU hiện nay có khả năng sắp xếp thứ tự thực hiện các instruction để có thể thực thi chúng song song(parallel).

Ví dụ:

    a = b + c
    d = a + e

    l = m + n
    y = x + z

Sau khi CPU thực hiện Instruction Reordering

    a = b + c
    l = m + n
    y = x + z

    d = a + e

Với các instruction trên được sắp xếp lại, CPU có thể thực hiện 3 instruction đầu tiên song song vì chúng không phụ thuộc lẫn nhau trước khi thực thi instruction thứ 4 -> tăng performance.

Tuy nhiên trong vài trường hợp khi thực hiện thì Instruction Reordering sẽ dẫn đến việc chương trình thực hiện không đúng trên nhiều luồng như ví dụ sau đây:

    Thread1

    (1) this.balance += 10000;
    (2) this.isDepositSuccess = true;

    Thread2
    (3) if (this.isDepositSuccess) {
    (4)    getBalance();
        }

Nếu CPU sắp xếp lại thứ tự thực hiện instruction (2) trước (1) thì ở Thread2 có thể xảy ra trường hợp điều kiện (3) đúng nhưng giá trị balance chưa được update -> chương trình sẽ không hoạt động đúng, vẫn lấy ra giá trị balance cũ. Ở đây Happens-before relationship sẽ giải quyết vấn đề đó, nó đảm bảo thứ tự thực hiện được giữ nguyên. Tất cả thay đổi xảy ra ở Thread1 trước khi ghi isDepositSuccess sẽ được nhìn thấy và cập nhật ở Thread2 khi đọc isDepositSuccess.

Trong Java, Happens-before relationship được đảm bảo khi sử dụng volatitesynchronized và java.util.concurrent.atomic.

Tham khảo link này về cách volatitesynchronized đảm bảo Happens-before relationship.

ví dụ về happend before

Nếu hành động X, Y được thực hiện trên 2 luồng khác nhau nhưng hành động X xảy ra trước khi hành động Y thì mọi thay đổi của X sẽ được luồng thực hiện hành động Y nhìn thấy và cập nhật. Theo cơ chế này chúng ta không cần nhất thiết phải sử dụng locksynchronized để chia sẻ dữ liệu giữa các luồng chỉ cần đảm bảo một một quan hệ Happens-before-relationship thì dữ liệu sẽ được đồng bộ(sử dụng volatile trong trường hợp chỉ có duy nhất 1 luồng ghi).

Trong trường hợp có nhiều hơn 1 luồng sửa đổi dữ liệu chúng ta sẽ sử dụng các cơ chế locksynchronized . Trong Java thì các hoạt động này cũng sẽ là happens-before relationship.

Concurrent is hard and lock is bad

context-switching.png

Lập trình đa luồng là rất khó đối với tất cả developer để tránh race condition chúng ta thường sử dụng cơ chế lock. Đây là một cách dễ dàng nhất nhưng nó lại mang lại hiệu năng thấp nhất.

Lý do lock mang lại hiệu năng thấp hơn các thuật toán chia sẻ tài nguyên khác là khi sử dụng lock sẽ gây lên context switching trong CPU.

Khi CPU chuyển từ thực hiện logic của luồng hiện tại sang thực hiện logic của luồng khác, CPU cần phải lưu lại dữ liệu cục bộ, trạng thái,… của luồng hiện tại và load dữ liệu, con trỏ,… của luồng khác để thực hiện logic. Quá trình chuyển đổi này được gọi là context switching, quá trình này thực sự không hề rẻ nên bạn cần tìm cách tránh nó khi lập trình.

Bạn có thể thay thế bằng cách sử dụng cơ chế CAS trong Java đại diện là các lớp Atomic. Trên thực tế cũng có các thuật toán lock free xây dựng trên cơ chế CAS khi sử dụng các thuật toán này mọi người lưu ý code tránh bị trường hợp False Sharing. Có một thư viện xây dựng queue rất nổi tiếng dựa trên cơ chế CAS có hiệu năng cực cao trên Java là LMAX Disruptor. Nếu bạn đọc được code Java bạn nên đọc qua mã nguồn của thư viện này. Sau khi hiểu được cơ chế cũng như cách hoạt động của LMAX Disruptor thì khẳng định bạn sẽ dùng nó để tăng chương trình Multithreading của mình.

Kết Luận

Khi lập trình concurrency chúng ta cần cố gắng thiết kế các luồng đọc các dữ liệu khác nhau, hạn chế sử dụng lock vì sẽ gây context switching ảnh hưởng đến hiệu năng của hệ thống. Nếu làm được như vậy thì hệ thống của bạn đã làm theo một khái niệm mechanical-sympathy phần cứng sẽ giúp chương trình của bạn chạy nhanh nhất có thể. Lập trình concurrency là rất khó và để lập trình concurrency hiệu quả nhất thì lại càng khó hy vọng sau bài viết này các bạn sẽ có những keyword để phục vụ trong quá trình làm việc.

Bài viết gốc được đăng tải tại demtv.hashnode.dev

Bài viết liên quan:

Đừng bỏ lỡ hàng loạt việc làm IT hấp dẫn trên TopDev nhé!

Money Forward Vietnam mở rộng chi nhánh tại Hà Nội – Từng bước chinh phục mục tiêu “Trở thành Công ty phát triển Fintech x SaaS số 1 tại Châu Á

Ngay lúc này, hãy theo chân TopDev để gặp gỡ và trò chuyện cùng anh Takenaka Kazumasa – Hà Nội Branch Director và nghe anh chia sẻ về tầm nhìn, định hướng phát triển và cả những điều tuyệt vời tại chi nhánh mới này nhé!

Có ba lý do chính để chúng tôi đưa ra lựa chọn này :

Điều thứ hai nằm ở sự tương đồng về văn hóa. Chúng tôi tìm thấy ở người Việt Nam nhiều nét tính cách tương đồng hơn so với một số khu vực khác. Và hơn thế nữa, trụ sở Money Forward Nhật Bản hiện đang có khá nhiều thành viên đến từ Việt Nam.

Về việc lựa chọn mở rộng chi nhánh tại Hà Nội, một phần là vì chúng tôi muốn thử sức với nhiều thị trường khác nhau tại Việt Nam để mở rộng quy mô cho tập đoàn Money Forward. Và ở thời điểm hiện tại thì tốc độ phát triển của Money Forward đang rất nhanh và điều đó đòi hỏi chúng tôi phải mở rộng thêm chi nhánh. Vì thế chúng tôi quyết định “cập bến” tại Hà Nội – một trong những thị trường CNTT lớn nhất Việt Nam. 

Đây là một mảnh đất màu mỡ, rất tiềm năng và có nhiều cơ hội để phát triển. Về mặt vĩ mô, nền kinh tế Việt Nam đang trên đà phát triển mạnh mẽ, đây chính là môi trường lý tưởng cho sự vươn lên của các doanh nghiệp Fintech. Ngoài ra, như đã đề cập thì Việt Nam là quốc gia sở hữu nguồn lực tuyệt vời về Developer, vậy nên cả môi trường và năng lực đều phù hợp cho lĩnh vực Fintech. Đó cũng là lý do mà nhiều công ty nước ngoài và start-up Việt Nam hướng tới phát triển lĩnh vực Fintech tại đây. Tôi cũng có một người bạn Nhật Bản đang kinh doanh mảng Fintech tại Việt Nam nữa đấy!

Và hơn hết, chúng tôi, Money Forward Việt Nam, đang hướng tới phát triển các sản phẩm Fintech tại thị trường Việt Nam trong tương lai chứ không chỉ riêng ở Nhật Bản.

Điểm tôi đặc biệt chú ý về các Lập trình viên Việt Nam là họ vô cùng tâm huyết với nghề. Nhiều người đã có thể vạch ra được kế hoạch và có tầm nhìn riêng về sự nghiệp của chính mình. Vì thế mà họ có động lực phát triển mạnh mẽ và có vốn kinh nghiệm hoặc kỹ năng khá vững. 

Chúng tôi mong muốn trở thành lợi thế cạnh tranh của tập đoàn Money Forward và cung cấp nhiều giá trị hơn nữa đến cho người dùng. Cá nhân tôi hi vọng có thể xây dựng Money Forward Vietnam tại Hà Nội trở thành chi nhánh công nghệ hàng đầu của tập đoàn có thể cung cấp các giải pháp cho bất kì hệ thống phức tạp nào. Và đồng thời, chúng tôi muốn nhân rộng những văn hóa trong đội ngũ ở Hà Nội đến các đội nhóm của Money Forward trên khắp thế giới.

Hình ảnh khai trương tại chi nhánh Money Forward Vietnam tại Hà Nội

Money Forward Việt Nam là công ty Product, chúng tôi không chỉ tập trung vào công nghệ mà còn quan tâm đến các giá trị cho người dùng. Với quan hệ hợp tác PdM, các Lập trình viên có thể thoải mái đề xuất ý tưởng để làm cho mỗi sản phẩm ngày càng hoàn thiện hơn. Chúng tôi tạo điều kiện để họ xem những thành phẩm ấy như thể sản phẩm của chính mình. Sau khi nhận được sự tin tưởng từ Money Forward Nhật Bản, các dự án của chúng tôi sẽ ngày càng nhiều thách thức hơn.

Văn phòng đang được hoàn thiện từng ngày nhưng chắc chắn sẽ là điểm đến lý tưởng cho các Lập trình viên đấy! Văn phòng sẽ được đặt trong điều kiện ánh sáng phù hợp, không gian rộng mở với thiết kế tương tự như trụ sở chính và chi nhánh Hồ Chí Minh.

Ngoài ra công ty cũng lắp đặt máy pha cà phê espresso và bàn chơi bida để các thành viên nhóm có thể thư giãn và còn nhiều hoạt động khác cùng công ty nữa.

Điều đầu tiên chính là kỹ năng về thiết kế và viết code để phát triển các sản phẩm chất lượng cao. Vì người dùng Nhật Bản rất khắt khe đối với chất lượng sản phẩm đặc biệt là trong lĩnh vực B2B. Họ yêu cầu cao về các lỗi và cả hiệu suất sản phẩm, cho nên bạn cần phải có kỹ năng xây dựng sản phẩm thật vững để xử lý lượng lớn dữ liệu mà không xảy ra lỗi. Và kĩ năng làm việc cùng đội nhóm, tất nhiên cũng là một trong những điều quan trọng để xây dựng văn hóa doanh nghiệp nữa.

Đây hẳn là một câu hỏi khó nhằn đấy! Nhưng cũng có vài điều tôi muốn chia sẻ. Thứ nhất là về kỹ năng chuyên môn, chúng tôi không chỉ tập trung vào những công nghệ mới nhất, bởi với Money Forward thì mang lại giá trị cho người dùng thông qua việc phát triển sản phẩm chính là mục tiêu quan trọng. Ngoài ra, để phát triển một sản phẩm tốt, kỹ năng đối với các công nghệ mới nhất là chưa đủ, lập trình cũng cần quan tâm đến cả quá trình thực hiện, teamwork nữa. Chưa hết, việc học các kiến thức nền như DB, storage,… cũng cực kì quan trọng, giúp ích rất nhiều trong việc sử dụng công nghệ một cách chính xác. Và chúng ta cũng cần xem xét về điều gì phù hợp với bản thân chứ không nên bị ảnh hưởng bởi các xu hướng mới.

Cảm ơn những chia sẻ hữu ích từ anh Takenaka Kazumasa về những điều tuyệt vời tại Money Forward Việt Nam. Hi vọng Money Forward Việt Nam chi nhánh Hà Nội sẽ đạt được những khát vọng của mình và ngày càng phát triển vững mạnh hơn nữa. Rất mong nhận được những chia sẻ thú vị hơn nữa từ anh trong thời gian tiếp theo.

  Đừng quên tham khảo thêm một số việc làm IT lương cao HOT nhất tại Money Forward Việt Nam nhé:

Cách Trình Duyệt Hiển Thị Website Của Bạn

Cách trình duyệt hiển thị website của bạn

Bài viết được sự cho phép của tác giả Phạm Minh Khoa

Anh em làm frontend web thường xuyên làm việc với HTML CSS, khi các bạn viết xong code và thực hiện chạy nó trên browsers (trình duyệt), chúng sẽ được xử lý qua 1 chuỗi các bước để xây dựng và hiển thị trang web đó lên. Các bạn có bao giờ lăn tăn xem trình duyệt cụ thể là làm những gì đối với file .html của chúng ta không? Bài viết này sẽ giới thiệu với các bạn các bước xử lý của trình duyệt. Trước tiên thì chúng ta sẽ sử dụng file html sau (có chứa có css và script)

<!DOCTYPE html>
<html>
  <head>
    <title>The "Click the button" page</title>
    <meta charset="UTF-8">
    <link rel="stylesheet" href="styles.css" />
  </head>
  
  <body>
    <h1>
      Click the button.
    </h1>
    
    <button type="button">Click me</button>
    
    <script>
      var button = document.querySelector("button");
      button.style.fontWeight = "bold";
      button.addEventListener("click", function () {
        alert("Well done.");
      });
    </script>
  </body>
</html>

Khi trình duyệt nhận được file HTML, nó sẽ thực hiện luồng các bước xử lý như sau:

  1. Sử dụng file HTML để tạo DOM (Document Object Model)
  2. Sử dụng CSS để tạo CSSOM (CSS Object Model)
  3. Chạy Script xử lý DOM và CSSOM kết hợp để tạo thành Render Tree
  4. Sử dụng Render Tree để Layout (xác định size và position của toàn bộ phần tử trên trang web)
  5. Paint tất cả các pixel (hiển thị lên màn hình)

Cụ thể chúng ta sẽ đi vào từng bước nhé:

Bước 1: HTML

Trình duyệt đọc file HTML từ trên xuống dưới và sử dụng nó để tạo ra các node từ file HTML. Như file HTML đầu bài, các node sẽ được sinh ra như hình trên, từ đó sẽ tạo thành cây DOM.

Lưu ý: từ việc tạo DOM trên thì chúng ta nên đặt style ở ngay trên đầu và script ở cuối file vì style luôn cần được load sớm, còn script thì ngược lại càng muộn càng tốt (vì phải có HTML với CSS thì script mới chạy).

Bước 2: CSS

// External stylesheet
<link rel="stylesheet" href="styles.css">

// Internal styles
<style>
  h1 {
    font-size: 18px;
  }
</style>

// Inline styles
<button style="background-color: blue;">Click me</button>

CSSOM cũng được tạo ra 1 cách tương tự như DOM

Ở đây chúng ta thấy rằng Trình duyệt sẽ chỉ Render Tree được khi DOM và CSSOM được tạo hoàn chỉnh, vì thế CSSOM sẽ chặn quá trình render trang web và chúng ta có 1 khái niệm gọi là “Render Blocking” để chỉ những node liên quan đến style dùng để tạo CSSOM. Cũng vì thế mà chúng ta nên giảm kích thước style và load chúng càng sớm càng tốt, ngược lại những style dư thừa (hoặc chưa cần thiết) thì nên cắt bớt hoặc trì hoãn tải tối đa có thể.

Cơ hội việc làm cho Web developer trên TopDev

Bước 3: JavaScript

Nếu trình duyệt tìm thấy những javascript node (external hoặc internal) như dưới đây

// An external script
<script src="app.js"></script>

// An internal script
<script>
  alert("Oh, hello");
</script>

lúc đó việc parse file HTML và tạo DOM/CSSDOM node sẽ bị dừng lại để chờ xử lý. Từ đó chúng ta lại có thêm 1 thuật ngữ là “Parser blocking” để chỉ những đoạn JavaScript trên. Ví dụ ta có 1 đoạn script như sau:

var button = document.querySelector("button");
button.style.fontWeight = "bold";
button.addEventListener("click", function () {
  alert("Well done.");
});

Nó sẽ ảnh hưởng đến DOM và CSSOM như sau:

Vì những script có thể cần đến HTML hoặc style để xử lý, do vậy chúng ta nên chạy script khi những phần tử đó đã sẵn sàng. Nếu có nhiều external script thì trình duyệt sẽ tải về và chạy lần lượt theo thứ tự trước sau.

Lưu ý: chúng ta có thể sử dụng attribute “async” để tải script về 1 cách không đồng bộ trên 1 thread khác và tiếp tục parse trang, khi nào việc tải về hoàn tất thì nó sẽ được chạy.

<script src="async-script.js" async></script>
<script src="defer-script.js" defer></script>

async và defer đều là trì hoàn việc tải script về để không chặn việc load trang; điểm khác nhau là defer sẽ chỉ chạy khi HTML parse xong và chạy theo thứ tự, còn async thì có thể chạy ở bất kỳ thời điểm nào khi nó load xong. Các bạn có thể xem hình dưới để dễ hình dung:

Từ đó ta thấy async sẽ hữu ích với những script không tác động gì đến DOM/CSSOM, không ảnh hưởng gì đến UX, ví dụ như analytics hoặc tracking. Còn defer thì sẽ hữu ích với những script tác động đến Render Tree nhưng không liên quan gì đến việc hiển thị phần above the fold (phần trên nếp gấp) của trang web hoặc cần những script khác chạy trước nó.

Bước 4: Render Tree

Khi tất cả các node đã được đọc, DOM và CSSOM đã sẵn sàng thì trình duyệt sẽ ghép chúng lại và dựng Render Tree.

Bước 5: Layout

Ở bước này, trình duyệt sẽ xác định size và position của tất cả các phần tử trên trang web.

Bước 6: Paint

Bước cuối cùng là vẽ và hiển thị trang trên màn hình.

Nhìn thì nhiều bước thế thôi nhưng toàn bộ quá trình này thưởng chỉ diễn ra trong vài giây hoặc vài chục giây. Tối ưu tốc độ load trang là 1 việc không dễ cho các frontend developer. Hy vọng bài viết sẽ cho các bạn cái nhìn tổng quan về quá trình 1 website được tạo ra.

Cảm ơn các bạn đã đọc.

Bài viết gốc được đăng tải tại anywayblogs.com

Mình thấy những bài viết sau cũng khá hay:

Xem thêm hàng loạt tin tuyển dụng IT trên TopDev

Data Warehouse Là Gì? Tổng Quan Về Kho Dữ Liệu

Data warehouse là gì

Hàng ngày, cá nhân hoặc doanh nghiệp đều tiếp nhận và xử lý một lượng dữ liệu nhất định. Theo năm tháng, lượng dữ liệu này trở nên khổng lồ và đòi hỏi một nơi lưu trữ đầy đủ nhằm đảm bảo hiệu quả cho những bước phân tích tiếp theo, cũng như giúp nâng cao tốc độ cho các kết quả trả về của hệ thống. Data warehouse đảm nhận nhiệm vụ này. Để hiểu rõ hơn Data Warehouse là gì, bạn hãy theo dõi bài viết bên dưới.

1. Data Warehouse là gì?

Data warehouse (DW) hay kho dữ liệu là một hệ thống lưu trữ dữ liệu từ nhiều nguồn, nhiều môi trường khác nhau như: phần mềm bán hàng, kế toán, nhân sự hay hệ thống lõi ngân hàng,… giúp tăng cường hiệu suất của các truy vấn cho báo cáo và phân tích.

Data Warehouse hoạt động như một kho lưu trữ trung tâm. Dữ liệu đi vào kho dữ liệu từ hệ thống giao dịch và các cơ sở dữ liệu liên quan khác. Sau đó, dữ liệu được xử lý, chuyển đổi để người dùng có thể truy cập những dữ liệu này thông qua công cụ Business Intelligence, SQL client hay bảng tính.

Một Data Warehouse thường bao gồm các yếu tố như:

  • Một cơ sở dữ liệu quan hệ để lưu trữ và quản lý dữ liệu.
  • Giải pháp trích xuất, tải và biến đổi ELT để chuẩn bị dữ liệu cho phân tích.
  • Khả năng phân tích thống kê, báo cáo và khai thác dữ liệu.
  • Các công cụ phân tích khách hàng để trực quan hóa và trình bày dữ liệu cho người dùng doanh nghiệp.
  • Các ứng dụng phân tích khác, phức tạp hơn tạo ra thông tin có thể hành động bằng cách áp dụng khoa học dữ liệu và thuật toán trí tuệ nhân tạo AI hoặc các tính năng đồ thị và không gian cho phép nhiều loại phân tích dữ liệu hơn trên quy mô lớn.

Sau khi hiểu được Data Warehouse là gì và cách thức hoạt động của nó, chúng ta tiếp tục tìm hiểu về những đặc tính cũng như lợi ích mà kho dữ liệu này mang lại cho cá nhân cũng như doanh nghiệp

2. Những đặc tính của Data Warehouse

2.1. Hướng chủ đề (subject-oriented)

Hướng chủ đề tức thông tin trong Data Warehouse sẽ được tổ chức và sắp xếp theo một chủ đề nhất định. Ví dụ, chủ đề phân tích bệnh án bệnh nhân, bệnh liên quan đến tim, thì bác sỹ cần quan tâm không chỉ một mà còn phải có các chỉ số liên quan đến máu, chỉ số về huyết áp, nhịp tim, điện tâm đồ. Ngoài ra còn cần theo dõi theo thời gian để xem xét sự thay đổi mà có phương pháp điều trị kịp thời. Trong trường hợp này thời gian được gọi là chiều phân tích.

Mục đích của Kho dữ liệu là phục vụ các yêu cầu phân tích, hoặc khai phá cụ thể được gọi là chủ đề.

2.2. Được tích hợp (integrated)

Mở rộng cho ví dụ trên, các khoa khác nhau tại bệnh viện sẽ thực hiện nhiều xét nghiệm khác nhau. Tương tự với doanh nghiệp, dữ liệu cần phân tích nằm rải rác tại những phòng ban khác nhau và cần tích hợp lại. Từ đó, tổng hợp dữ liệu từ nhiều nguồn vào một kho dữ liệu cho phép chúng ta có thể xem đồng thời nhiều nhóm chỉ tiêu khác nhau. Quá trình tích hợp này sẽ được thực hiện trong quá trình ETL.

Tổng quan về Data warehouse

2.3. Có gán nhãn thời gian (time variant)

Vì dữ liệu thay đổi liên tục nên chúng sẽ được gán 1 nhãn thời gian tương ứng tại thời điểm nhập liệu. Việc gắn thời gian này giúp ta dễ dàng so sánh dữ liệu với nhau để biết được các thay đổi đang đi theo chiều hướng tích cực hay tiêu cực.

Ví dụ, so sánh độ đo doanh thu của một mặt hàng của tháng hiện tại với tháng trước, tháng này năm trước thì sẽ có nhiều thông tin hơn để đánh giá doanh thu của mặt hàng đó là tốt hay không, trên cơ sở đó sẽ có các quyết định phù hợp. Ngoài ra, dữ liệu lịch sử còn cho phép dự báo được tương lai khi ứng dụng khai phá dữ liệu.

Tin tuyển dụng IT lương cao đang chờ bạn ứng tuyển đây!

2.4. Bất biến (non-volatile)

Dữ liệu trong Kho dữ liệu có chức năng báo cáo lại các chỉ số về hoạt động kinh doanh thực tế đã xảy ra do đó không thể cập nhật, thay đổi vì nó sẽ không phản ánh đúng thực tế. Vì vậy, với kho dữ liệu chỉ có 2 thao tác chính là tải dữ liệu vào kho và truy cập (đọc) dữ liệu từ kho.

3. Data warehouse mang lại lợi ích gì?

Sự xuất hiện của kho dữ liệu nhằm mục đích đáp ứng lượng dữ liệu ngày càng tăng cần được xử lý. Nhu cầu lưu trữ dữ liệu tăng lên đi kèm với đó là sự phức tạp của hệ thống máy tính. Từ đó, ta thấy được những lợi ích mà kho dữ liệu mang lại cho doanh nghiệp như: 

  • Tích hợp dữ liệu vào một nguồn, ở cùng một định dạng, giải quyết sự phân mảnh và mất cân bằng dữ liệu để đáp ứng nhu cầu thông tin của tất cả người dùng. 
  • Tiết kiệm thời gian và hiệu quả trong việc tìm kiếm dữ liệu cần thiết.
  • Thông qua xử lý và phân tích dữ liệu Data Warehouse giúp cho dữ liệu của doanh nghiệp hiệu quả hơn.
  • Giúp người dùng đưa ra các quyết định hợp lý, nhanh chóng và hiệu quả, đem lại nhiều lợi nhuận hơn,…
  • Giúp tổ chức, xác định, quản lý và thực hiện các dự án/hoạt động một cách hiệu quả và chính xác.
  • Tăng đáng kể lượng dữ liệu cần được tổng hợp, lưu trữ và xử lý.

Trên đây là bài viết mang cái nhìn tổng quan về Data Warehouse là gì, định nghĩa và những khái niệm liên quan. Để hiểu sâu hơn các bạn có thể tìm hiểu về cách thức hoạt động chuyên sâu cũng như cấu trúc của Data Warehouse, các khái niệm liên quan như OLTP, OLAP,…

Những chủ đề khác bạn có thể tham khảo:

Top Developers đừng bỏ lỡ Top việc làm IT trên TopDev nhé!

Stack Overflow Là Gì? Vì Sao Đệ Quy Lại Dễ Gây Tràn Stack?

Vì sao đệ quy gây tràn Stack
Bài viết được sự cho phép của tác giả Khiêm Trần

Trong nội dung bài này, mình sẽ giải thích vì sao lại có hiện tượng tràn bộ nhớ Stack, và đặc biệt hay xảy ra khi gọi đệ quy.

Một số khái niệm

Bộ nhớ Stack: bộ nhớ dành riêng cho việc lưu trữ các biến cục bộ, tham số, kết quả trả về, và ghi nhớ các thanh ghi. Bộ nhớ này có giới hạn về kích thước.

Push: thao tác push và stack

Pop: thao tác lấy ra từ stack.

RBP – register base pointer – thanh ghi chứa địa chỉ bắt đầu của stack được sử dụng trong chương trình con hiện tại.

RSP – register stack pointer – đỉnh của stack hiện tại. Giá trị địa chỉ của stack sẽ giảm dần khi mình tăng kích thước của stack.

Vào bài thôi

Xét một hàm đơn giản như sau:

int add(int a, int b) {  return a + b; }

Ta thấy trong hàm này có 2 tham số là a và b. Khi biên dịch hàm này trên chip Intel 64bit ta có kết quả như sau:

_add:
 pushq %rbp  # đẩy giá trị của rbp vào bộ nhớ stack
 movq  %rsp, %rbp # gán địa chỉ bắt đầu bằng đỉnh của stack.
 movl %edi, -4(%rbp)  # chuyển giá trị của tham số thứ nhất từ thanh ghi %edi vào ô nhớ có địa chỉ %rbp - 4 (số int có kích thước 4 byte)
 movl %esi, -8(%rbp) # chuyển giá trị của tham số thứ hai (b) từ thanh ghi %esi vào ô nhớ có địa chỉ %rbp - 8
 movl -4(%rbp), %eax # gán a cho thanh ghi %eax - thanh ghi %eax sẽ chứa giá trị trả về của hàm
 addl -8(%rbp) %eax # cộng b cho thanh ghi %eax
 popq %rbp # phục hồi lại địa chỉ bắt đầu stack cho %rbp  
 retq # trở lại

Ta thấy hàm này này sử dụng tổng cộng 16 bytes trên stack (8 bytes để lưu %rbp và 8 bytes để lưu tham số a, b), khi gọi hàm này thì đỉnh của stack giảm đi 16 bytes. Sau khi kết thúc lời gọi hàm này thì bộ nhớ stack được giải phóng (tăng lên lại 16 bytes), đơn giản chưa mọi người?

Bây giờ ta sẽ xét tiếp trường hợp một hàm đệ quy:

Xét đoạn code sau:

int factorial(int n) {  if (n == 0) {    return 1;  }  return n * factorial(n - 1); }

Đoạn này sẽ được dịch ra Assembly như sau:

_factorial:
 pushq %rbp  # tương tự, đẩy giá trị của rbp vào bộ nhớ stack
 movq  %rsp, %rbp # gán địa chỉ bắt đầu bằng đỉnh của stack.
 subq $16, %rsp # trừ bộ nhớ stack đi thêm 16 bytes
 ….
 callq _factorial # gọi đệ quy

 addq $16, %rsp # cộng đỉnh stack lại 16 bytes
 popq %rbp # phục hồi địa chỉ bắt đầu của stack
 retq       # trả về

Top việc làm C++ hấp dẫn trên TopDev đang chờ bạn ứng tuyển nè

Khi trong hàm chúng ta có lời gọi hàm thì chương trình sẽ tính lại đỉnh của stack (trong trường hợp này là -16 bytes, để dành 16 bytes để lưu các giá trị tính toán trung gian trong hàm). Trong hàm này, tổng cộng bộ nhớ stack được sử dụng là 24 bytes (16 bytes + 8 bytes để lưu con trỏ %rbp). Sau khi gọi hàm thì 24 bytes này sẽ được phục hồi và trả về lại trên hệ thống.

Nếu chúng ta gọi đệ quy thì bộ nhớ stack sẽ tăng liên tục sau mỗi lời gọi hàm, do bộ nhớ STACK có giới hạn, nên sẽ bị TRÀN STACK!!

Tada!! quá dễ sao nói rườm rà vậy?? Hy vọng lời giải thích rườm rà này sẽ giúp các bạn hiểu ra bản chất của vấn đề.

Tái bút:

  • Thêm 1 lí do để viết Assembly vì hàm add trên trình duyệt làm hơi rườm rà, không cần xài stack luôn.
_add:
 movl %edi, %eax
 addl %esi, %eax
 retq
  • Gọi là “Tràn Stack” có vẻ hơi sai vì địa chỉ stack được đánh giá ngược nên nó giảm cho đến khi bị tràn, chắc phải gọi là hụt stack mới đúng.
  • Bộ nhớ stack không tự động bị xoá đi sau khi kết thúc lời gọi hàm, nên password, key, không nên lưu trữ dạng raw trong bộ nhớ để tránh bị quét bộ nhớ. Sau khi xử lí nhớ dọn dẹp.
  • Hy vọng chưa có ai bị nổ não.

Bài viết gốc được đăng tải trên fanpage Khiem Tran – Programmer

Những bài viết bạn có thể tham khảo: