Deep debugging


wcuhlfb
Debugging on production – Thecodinglove.com

Debug là một phần không thể thiếu của công việc lập trình. Nếu đã là lập trình viên, chắc chắn không ít lần chúng ta phải vò đầu bứt tai hoặc chỉ muốn xóa mọi thứ chỉ vì một lỗi mà chúng ta không thể nào hiểu được nguyên nhân tại sao. Cảm giác tuyệt vọng cùng với tư tưởng đổ lỗi cho hoàn cảnh hoặc vì một thế lực huyền bí nào đó là khá phổ biến. Nhưng đi kèm với đó là cảm giác phấn khích khi tự mình giải quyết được vấn đề hóc búa chưa ai gặp.

Có nhiều giải pháp khác nhau để debug một lỗi không rõ nguyên nhân. Cách thông thường nhất là tìm kiếm trên Google để xem đã có ai từng gặp vấn đề này chưa. Có thể nói là 80% đến 90% các vấn đề mà các lập trình viên gặp trong lúc làm việc có thể đã từng có người khác gặp và đã được giải quyết. StackOverflow không còn là địa chỉ xa lạ với tất cả các lập trình viên, hầu như mọi câu hỏi và vấn đề lập trình đều được đưa lên StackOverflow để tất cả cùng thảo luận và các chuyên gia giải quyết. Cứ tưởng tượng một ngày nào đó StackOverflow bị đánh sập, đó chắc chắn sẽ là thảm họa cho toàn bộ giới lập trình viên và hiệu suất công việc chắc chắn sẽ giảm sút nghiêm trọng.

Tuy nhiên…

Đôi khi việc quá dựa dẫm vào StackOverflow hoặc Google khiến cho chúng ta không còn suy nghĩ nhiều nữa. Giả sử như chúng ta gặp một bug phức tạp nhưng ngay lập tức tìm thấy câu trả lời trên StackOverflow, hầu hết chúng ta sẽ không chần chừ áp dụng giải pháp được đưa ra trên đó và nếu nó giải quyết được vấn đề thì đa số sẽ không còn nhớ nhiều đến vấn đề đó nữa (một phần là vì sau lưng mỗi lập trình viên thường có con dao “Deadline”, dừng lại một chút cũng có nghĩa là thêm một chút đau đớn từ Deadline). Mọi việc tưởng chừng vẫn suôn sẻ cho đến một ngày một anh chàng “Bug bự” xuất hiện trước mặt chúng ta và anh ta chưa từng được khám quá trước đó. Thay vì cảm giác phấn khích khi phát hiện ra một sinh vật mới (như các nhà thám hiểm) và xem đó như là một thử thách mới thì chúng ta cảm thấy lo sợ và hoảng loạn, đặc biệt nếu như không tìm thấy được bất kỳ thông tin nào về anh chàng “Bug bự” này, cảm giác cả thế giới như đang chống lại chúng ta vậy.

Ngày hôm qua, một anh “Bug bự” như vậy đã xuất hiện trước mặt mình và làm mình cực kỳ ức chế. Mình đang học và thử nghiệm một framework về Deep Learning tên là TensorFlow và có anh chàng kia chia sẻ mã nguồn của một model rất hay dựa trên framework này, nhưng khi mình chạy thì lại bị lỗi ở phần Load dữ liệu training do mình tạo ra. Tự nhủ với lòng chắc là do mình chưa tìm hiểu về định dạng của dữ liệu nên chắc gây ra lỗi, vì thế dành cả buổi chiều để đọc về các định dạng file tương ứng với framework. Không có kết quả, tất cả vẫn không giúp giải quyết được vấn đề. Mọi thứ mình làm đều giống như documentation của framework nhưng nó vẫn bị lỗi. Câu hỏi là tại sao dữ liệu mình tạo ra giống như mô tả rồi nhưng vẫn không chạy được? Mình ngay lập tức tìm kiếm trên các Google và StackOverflow nhưng rất tiếc không có kết quả. Mã nguồn của anh chàng kia cũng chỉ mới được chia sẻ trong khoảng 20 ngày gần đây nên chắc cũng chưa có ai sử dụng và gặp vấn đề như mình. Theo thói quen thông thường, mình post câu hỏi lên ngay project Github của anh chàng kia, đồng thời Post câu hỏi lên StackOverflow cũng như gửi email trực tiếp đến cho tác giả hỏi về vấn đề này. Và chờ đợi trong hy vọng rằng sẽ có ai đó giải quyết giúp mình vấn đề này.

Điều gì sai trong cách làm ở trên của mình? Đó là mình vẫn chưa thử hết các giải pháp có thể để debug lỗi này. Framework của mình đang dùng là một framework mã nguồn mở và mình hoàn toàn có thể xem được toàn bộ mã nguồn để hiểu lỗi sinh ra là nguyên nhân vì đâu. Đó chính là một ưu điểm tuyệt vời của mã nguồn mở, chúng ta có thể debug trong chính framework mà chúng ta đang dùng. Nếu dùng .NET hoặc Java, đa phần chúng ta phải dựa vào các thông báo lỗi của các framework này đưa ra để debug, còn ngày nay, chúng ta sẽ nhảy vào tận source code của framework và trace back lại toàn bộ con đường dẫn đến lỗi. Đó tất nhiên là cả một nghệ thuật và suy luận, nhưng chúng ta là lập trình viên và nếu muốn trở thành lập trình viên giỏi thì chúng ta phải chịu khó đi sâu hơn so với lập trình viên bình thường.

Quay lại vấn đề Bug Bự ở trên, trong lúc đợi chờ vô vọng câu trả lời từ tác giả hoặc cộng đồng, mình đã bình tĩnh hơn và bắt đầu công việc debug một cách chủ động. Quan sát đoạn code được chia sẻ của tác giả, mình thấy rằng tác giả luôn đọc 8 bytes đầu tiên trong file Binary để quyết định xem file binary đó có bao nhiêu byte tiếp theo là cho phần dữ liệu. Như vậy là thông tin độ dài dữ liệu được lưu trong 8 bytes này. Nếu như file dữ liệu của mình khi đọc bị lỗi thì có khả năng là bởi vì 8 bytes này không chính xác nên độ dài dữ liệu lấy ra không đúng. Thông báo lỗi của framework khi load dữ liệu càng khẳng định thêm một chút về hướng suy nghĩ này. Mình nhảy vào Github của TensorFlow và tìm đến thư viện chịu trách nhiệm ghi dữ liệu xuống file. Tất nhiên còn phải dò qua vài file nữa mới đến được chính xác hàm để ghi dữ liệu vì module này có thể tham chiếu đến module khác khá là nhiều tầng. Và tadaaaa, mình đã nhìn thấy ra được vấn đề. Trong hàm để ghi dữ liệu xuống file của TensorFlow, thay vì dùng 8 byte để ghi ra độ dài của dữ liệu thì nó còn dùng thêm 4 bytes để cho việc CRC (https://en.wikipedia.org/wiki/Cyclic_redundancy_check). Như vậy là có tới 12 bytes đầu tiên trong file binary là thông tin meta rồi sau đó mới đến phần dữ liệu, còn trong code của tác giả thì file của họ chỉ có 8 bytes đầu tiên là thông tin meta, còn lại là dữ liệu. Đây là là nguyên nhân làm cho file binary của mình không thể được load lên bởi model của tác giả. Khi đã biết nguyên nhân thì việc sửa lỗi khá là dễ dàng, thay vì đọc 8 byte rồi đọc dữ liệu thì mình sẽ đọc 8 byte, sau đó bỏ qua 4 byte tiếp theo và cuối cùng đọc dữ liệu. Problem solved!

Như vậy, nếu chúng ta có thời gian bình tĩnh suy nghĩ để debug thì chúng ta hoàn toàn có khả năng khuất phục các anh chàng Bug Bự. Tất nhiên việc này cũng không phải dễ dàng nếu như chúng ta đang phải chạy đua với deadline hoặc bị quá nhiều sức ép. Nếu bạn là lập trình viên, hãy sẵn sàng nghênh chiến với các thử thách sẽ xuất hiện và đôi khi hãy tự cố gắng tìm giải pháp cho một vấn đề khó, khi đó bạn sẽ học thêm được nhiều thứ và nó sẽ tồn tại rất lâu trong trí nhớ của bạn. Đặc biệt khi làm việc với mã nguồn mở, khả năng tự giải quyết được vấn đề sẽ tăng lên nhiều lần vì chúng ta có truy cập trực tiếp vào mã nguồn. Tuy vậy, đừng bao giờ quên chia sẻ giải pháp của mình hoặc là nêu câu hỏi cho cộng đồng bởi vì hỏi cũng là một cách để học. Có những vấn đề sẽ là quá sức đối với bản thân chúng ta và khi đó sự trợ giúp từ các chuyên gia và những người có trình độ cao hơn là hoàn toàn cần thiết. Suy ra cho cùng, chúng ta cũng không phải là siêu nhân và thời gian của chúng ta cũng là hữu hạn.

Happy coding!

Tác giả: xuanchien

Tran Xuan Chien. Japan Advanced Institute of Science and Technology - Japan. Senior Developer - NUS Technology.

3 thoughts on “Deep debugging”

Gửi phản hồi

Mời bạn điền thông tin vào ô dưới đây hoặc kích vào một biểu tượng để đăng nhập:

WordPress.com Logo

Bạn đang bình luận bằng tài khoản WordPress.com Log Out / Thay đổi )

Twitter picture

Bạn đang bình luận bằng tài khoản Twitter Log Out / Thay đổi )

Facebook photo

Bạn đang bình luận bằng tài khoản Facebook Log Out / Thay đổi )

Google+ photo

Bạn đang bình luận bằng tài khoản Google+ Log Out / Thay đổi )

Connecting to %s