Lý giải chút về tên series
Series Phản Phác Quy Chân – Tại sao cộng string lại chậm
返璞归真 – Phản phác quy chân: Nghĩa là điểm cao nhất cũng chính là điểm xuất phát, được ứng dụng trong rất nhiều lĩnh vực. Trong võ học, nó có nghĩa là đạt tới cảnh giới “Tối thượng” trong truyền thuyết, quên đi tất cả võ học trong thiên hạ, bản thân đã không còn chiêu thức cụ thể, chỉ dựa vào ý cảnh mà đơn giản xử lý.
Bạn đang xem: Phản phác quy chân là gì
Võ học được xây dựng từ những chiêu thức cơ bản, tuyệt thế võ thuật cũng từ những chiêu thức cơ bản mà ra. Code học cũng tạo thành từ bit / byte cơ bản, chương trình phức tạp đến mấy cũng dịch được ra bytecode. Đôi khi, ta đã quá quen với việc dùng thư viện, dùng framework mà quên thì những thứ nằm sâu bên dưới, không nắm được thực chất. Có những yếu tố mà phải nắm rõ thực chất của nó ta mới hoàn toàn có thể xử lý được .
Như cái tên “Phản Phác Quy Chân”, series này không giới thiệu công nghệ hay ngôn ngữ mới, mà sẽ tập trung quay lại những cái bản chất, đơn giản, tinh túy nhất mà ít người quan tâm để ý (Bên tiếng Anh có một từ tương tự : Back to Basic, bỏ qua những cái phức tạp, quay lại những cái cơ bản để hiểu tận gốc vấn đề).
Bạn đang đọc: Series Phản Phác Quy Chân Là Gì, Phản Phác Qui Chân
Ở bài viết đầu, mình sẽ nhắc sơ lại về string, cũng như lý giải nguyên do vì sao việc cộng string sẽ tác động ảnh hưởng tới bộ nhớ và performance của mạng lưới hệ thống ( Hình minh họa và bài viết méo tương quan với nhau đâu, vì tác giả thích thế : v ) .
Chuyện về String
Ngày xửa rất lâu rồi, thời còn học Java, ta thường được nghe dạy rằng khi cộng chuỗi, phải dùng StringBuilder và append, thay vì cộng String. Lý do là vì String là kiểu immutable, giá trị của nó không đổi khác, khi cộng string ta tạo một string mới trong bộ nhớ. Còn StringBuilder là kiểu mutable, do đó khi ta dùng append, giá trị của nó biến hóa chứ không tạo ra string mới. Do đó dùng StringBuilder sẽ tiết kiệm chi phí bộ nhớ và chạy nhanh hơn .Không tin à, hãy xem 2 đoạn code dưới đây, đoạn code dùng StringBuilder chỉ mất 4 ms để chạy, còn đoạn code sử dụng String mất tới 4828 ms ( Nguồn ) .
int total = 50000; String s = “”; for (int i = 0; i Ta tạm gật gù đồng ý “Ồ, ra thế”. Tuy nhiên, có bao giờ ta tự hỏi, tại sao cộng string lại chậm hay không? Hãy cùng đọc bài viết và tìm hiểu nhé.
Xem thêm: Betcha Là Gì – Betcha Có Nghĩa Là Gì
Cộng string thì có vấn đề gì
Để giải thích vấn đề này, ta hãy thử trải nghiệm cảm giác “Phản phác qui chân“: Bỏ qua một bên những công nghệ mới mẻ hoành tráng, những framework đồ sộ, những ngôn ngữ ảo diệu, quay lại từ cái thời ngày xửa ngày xưa còn dùng DevC, còn làm việc với byte và bộ nhớ. Đúng vậy, những kiến thức về byte, về bộ nhớ là nền tảng cho hệ thống kiến thức của bạn.
Hãy nhớ lại cách C lưu trữ string: String là một mảng các byte, có kí tự cuối cùng là kí tự null. Với cách lưu trữ này, để biết được độ dài của string, ta phải chạy một vòng lặp bắt đầu từ con trỏ chứa byte đầu tiên cho tới khi gặp kí tự null. Dưới đây là một phiên bản của hàm strcat, hàm cộng chuỗi trong C.
Xem thêm: Gu của anh là người mẫu
void strcat ( char * dest, char * src ) { while ( * dest ) dest + + ; while ( * dest + + = * src + + ) ; } Đọc code và suy ngẫm nhé. Dòng tiên phong, code sẽ chạy từ đầu cho tới khi gặp phải null character cuối string dest, sau đó nó sẽ copy từng byte của string src và string dest. Hai vòng lặp, độ phức tạp chỉ là O ( n ), đâu có gì ghê gớm nhỉ ? ? Tuy nhiên, khi ta thực thi việc cộng chuỗi nhiều lần, với chuỗi dài thì sao ?
char bigString<1000>; bigString<0> = “\0”;strcat(bigString,”John, “);strcat(bigString,”Paul, “);strcat(bigString,”George, “);strcat(bigString,”Joel “);Mỗi lần gọi strcat, vòng lặp sẽ chạy từ đầu cho tới cuối chuỗi, chuỗi càng dài thì vòng lặp chạy càng lâu. Tới khi chuỗi string vô cùng lớn thì việc cộng chuỗi diễn ra rất nặng nề và chậm chạp. Bác Joel có một câu chuyện cười (mình đọc chả thấy vui) để mô tả vấn đề này.
Một cô tóc vàng mới vào nghề sơn vạch phân tuyến trên đường cao tốc. Ngày đầu, cô sơn được 10 dặm, ngày hôm sau cô chỉ sơn được 7 dặm. Ông chủ nghĩ rằng cô mệt, nên cho nghỉ một ngày. Sau hôm đó, cô ta làm cũng chỉ được 5 dặm. Cứ thế mỗi ngày cô lại làm ít hơn. Ông chủ gọi cô tới hỏi :– Có chuyện gì xảy ra thế ? Tại sao hiệu suất của cô giảm từng ngày ?
– Tôi tưởng là ông phải biết chứ! Đơn giản là càng ngày, tôi càng đi xa cái thùng sơn hơn.
Tương tự như trong truyện, string gốc càng dài thì vòng lặp phải chạy càng lâu. Do đó, để giải quyết vấn đề này, một số phiên bản khác của hàm strcat đã được tạo ra:
char* mystrcat( char* dest, char* src ){ while (*dest) dest++; while (*dest++ = *src++); return –dest;}char bigString<1000>; char *p = bigString;bigString<0> = “\0”;p = mystrcat(p,”John, “);p = mystrcat(p,”Paul, “);p = mystrcat(p,”George, “);p = mystrcat(p,”Joel “);Với cách viết này, sau khi cộng chuỗi, ta trả ra vị trí con trỏ cuối cùng. Mỗi lần cộng thêm, vòng lặp chỉ cần chạy từ con trỏ được trả cho tới cuối chuỗi src thôi, không còn lặp nhiều như thuật toán ban đầu nữa.
Xem thêm: Lê Trương Hải Hiếu: Kẻ phóng đãng!
Kết luận
Lâu lâu tìm hiểu về những khái niệm/ngôn ngữ bậc thấp cũng khá hay phải không nào. May mắn là chúng ta được sử dụng C#, Java tự giải phóng bộ nhớ, lại có khá nhiều thư viện hỗ trợ. Nhiều bác vẫn còn viết C, C++, truy cấp bộ nhớ bằng tay rất cực (Cực nhưng lương cao chót vót đấy nhé). Tuy nhiên, nếu mình là người viết code, trong 90% các trường hợp, mình vẫn sẽ dùng String hoặc String.Format thay vì StringBuilder!! Vì sao?? Chịu khó chờ nhé, mình sẽ dành một bài viết khác để giải thích chuyện này.
Xem thêm: Biên Lợi Nhuận Gộp ( Gross Margin Là Gì ? Công Thức Tính Gross Margin
Bài viết tìm hiểu thêm nhiều từ blog Joel on Software của bác Joel, một người vừa cứng technical vừa giỏi quản lý và điều hành và quản trị : http://www.joelonsoftware.com/articles/fog0000000319.html. Bài viết gốc phẫu thuật khá nhiều yếu tố về performance, bộ nhớ tương quan tới string, cơ mà mình thấy không có ích mấy nên không đưa vào bài viết nhé .
Source: https://www.doom.vodka
Category: Tin tức
Leave a Reply
You must be logged in to post a comment.