scada 100k tag
Tôi đã sửa code cho 100k tag, nhưng chưa build được: máy tôi không có .NET SDK. Tôi chỉ kiểm tra cú pháp các file .cs, còn các file .razor thì chưa kiểm tra gì. Bạn build lại và gửi lỗi (nếu có) để tôi sửa tiếp.
Bản vá nằm trong ScadaWeb_100k_patch.zip: giải nén đè lên thư mục project rồi chạy build.bat. File 100k_patch.diff cho thấy chính xác từng dòng đã đổi.
Nguyên nhân gây lag, treo
Hệ thống chưa dùng được với 100k tag chủ yếu vì code đang duyệt cả danh sách tag ở rất nhiều chỗ:
- Tra tag theo tên bằng
P.Tags.FirstOrDefault(...)trong mỗi widget, mỗi 0,5 giây. Mỗi bảng tag vàTagListcòn dựng lại một Dictionary từ 100k tag mỗi lần vẽ. - Tab “Thiết bị & Tag” vẽ 100k dòng, mỗi dòng 11 ô, rồi đẩy qua SignalR mỗi 0,5 giây. Đây là chỗ làm trình duyệt đơ rõ nhất.
- Lịch sử Trend ghi cho mọi tag, kể cả tag không bật Trend. Mỗi tag giữ 28.800 điểm (8 giờ) trong RAM, tính ra khoảng 46 GB. SQLite cũng bị ghi khoảng 10.000 dòng mỗi giây.
EvalAlarmkhoá toàn cục và quét danh sách alarm cho từng tag, kể cả tag không có rule alarm.Save()ghi lại toàn bộproject.jsonmỗi lần sửa một tag, và giữ khoá trong lúc ghi.- Nhập CSV và
AddTagschạy O(N²), nên nhập 100k tag sẽ treo rất lâu. - Modbus TCP gửi một request cho mỗi tag, tức 100k request mỗi chu kỳ.
Đã sửa
- Chỉ mục tag O(1) (file mới
ScadaEnginePerf.cs):GetTag,TagMap,TagSnapshot. Home và các widget dùng chỉ mục này thay vì duyệt danh sách. - Vòng đọc:
- Không lọc lại tag theo thiết bị mỗi chu kỳ.
- Chỉ vẽ lại giao diện khi có giá trị hoặc cấu hình đổi (tối đa 2 giây không đổi thì vẫn làm tươi một lần).
- Alarm bỏ qua ngay tag không có rule và không có alarm đang chạy.
- Lịch sử:
- Từ trên 3000 tag, chỉ ghi tag bật Trend hoặc đang là pen của widget Trend.
- Dự án nhỏ vẫn ghi tất cả như cũ.
- Số tag Trend càng nhiều thì bộ nhớ lịch sử chi tiết càng giảm (8 giờ, 2 giờ, hoặc 1 giờ).
MemDaystừ 7 xuống 1.
Save()gom lại, ghi nền sau khoảng 0,8 giây, và tự ghi nốt khi tắt chương trình hoặc xuất project.- Nhập CSV và
AddTagsdùng từ điển nên chạy O(N). - Modbus TCP đọc theo lô: gom các thanh ghi và coil liền nhau thành một request, vài trăm request thay cho 100k. Nếu một khối lỗi thì đọc lại từng tag trong khối đó.
- Giao diện:
- Bảng tag có ô lọc và phân trang 100 dòng.
- Tab Trend chỉ hiện tối đa 100 tag khớp bộ lọc.
- Ô chọn tag trong widget plugin dùng
TagPickerthay cho<select>liệt kê hết.
Chưa làm, cần bạn lưu ý
- OPC UA vẫn đọc cả 100k node bằng một lệnh
Read. Nhiều server giới hạn khoảng 10.000 node mỗi lệnh. Hướng đúng là dùng Subscription/MonitoredItem, hoặc chia lô. - Chỉ Modbus TCP có đọc theo lô. Driver khác vẫn đọc từng tag. Driver nào lấy dữ liệu từ bộ nhớ đệm như OPC UA, IEC104, MQTT, Socket.IO thì vẫn ổn. Driver S7, Mitsubishi, Modbus RTU thì cần viết thêm giao diện
IBatchReader. - Widget vẫn vẽ lại hết mỗi lần làm tươi. Với vài trăm widget thì tạm ổn. Nếu một màn hình có hàng nghìn widget thì cần thêm
ShouldRenderchoWidgetBody. - Alarm có thể bùng nổ với 100k tag, và
Alarmschỉ giữ 500 dòng gần nhất. - Tag Trend: bạn nên giữ dưới khoảng 2000 tag bật Trend.
project.jsoncó thể nặng hàng chục MB, nên bản vá chỉ bỏ thụt dòng khi trên 2000 tag. Khi dự án phình lên thì nên chuyển tag sang SQLite.- Phần cứng: nên dùng SSD cho thư mục
history.
Bạn build xong thì cho tôi biết kết quả, hoặc cho biết cấu hình thật (số thiết bị, loại driver, số tag mỗi thiết bị) để tôi tối ưu tiếp đúng driver bạn dùng.
Tôi sẽ tối ưu trực tiếp project z233_18_10_2026_SocketIO_GPT_100ktag.zip, tập trung vào màn hình Thiết bị & Tag như ảnh bạn gửi, để danh sách 50.000 tag chạy mượt hơn mà vẫn giữ chức năng đọc/ghi tag, trạng thái, alarm và thời gian cập nhật.
Với SCADA dùng ASP.NET và Blazor, điểm quan trọng nhất là không render toàn bộ 50.000 dòng cùng lúc và không cập nhật lại toàn bộ giao diện mỗi khi một tag thay đổi. Chỉ phân trang dữ liệu ở phía server thôi chưa đủ nếu phía trình duyệt vẫn tạo quá nhiều phần tử giao diện.
Đã chỉnh sửa project và đóng gói bản ZIP tối ưu để bạn tải về.
SCADA Web — tối ưu danh sách 50K tag
ASP.NET / Blazor · Giữ nguyên cấu trúc project gốc
ZIP · Khoảng 572 KB
Tải project ZIP đã chỉnh sửa
Các điểm đã tối ưu
Phân trang: mặc định 200 tag/trang, có lựa chọn 100, 200 hoặc 500 tag.
Tìm kiếm nhanh: lọc theo tên tag, thiết bị, địa chỉ và kiểu dữ liệu.
Giảm DOM: chỉ render các dòng của trang hiện tại, thay vì tạo 50.000 dòng HTML cùng lúc.
Bảng dễ sử dụng: thanh tiêu đề cố định khi cuộn, vùng danh sách có chiều cao giới hạn.
Giữ chức năng: sửa tên tag, chỉnh alarm, trend, ghi giá trị và xóa tag vẫn được giữ trong mã giao diện.
Cách chạy thử
Sao lưu project hiện tại.
Giải nén ZIP mới vào một thư mục riêng.
Mở
ScadaWeb.slnbằng Visual Studio, chọn .NET 8 và build.Chạy ứng dụng, mở Thiết bị & Tag, kiểm tra phân trang và tìm kiếm với 50.000 tag.
Lưu ý: Tôi đã kiểm tra việc đóng gói và các phần mã đã chỉnh sửa, nhưng môi trường hiện tại không có dotnet để build và chạy thử toàn bộ project. Vì vậy, chưa thể xác nhận hiệu năng thực tế hoặc bảo đảm build thành công.
Ngoài ra, bản này chủ yếu tối ưu giao diện danh sách. Để SCADA chạy ổn định ở mức 50.000–100.000 tag, bước tiếp theo cần kiểm tra thêm chu kỳ polling, cập nhật dữ liệu realtime, ghi log và cách phân phối thay đổi tag qua SignalR/WebSocket. Chỉ phân trang giao diện chưa bảo đảm toàn hệ thống không
Với project SCADA của bạn, mục tiêu 50.000 tag, tôi chưa có số liệu benchmark thực tế để khẳng định nhanh hơn chính xác bao nhiêu lần sau khi sửa code.
Ước lượng dưới đây chỉ là kịch bản tham khảo, không phải kết quả đo của project:
Tình huống | Mức cải thiện có thể kỳ vọng |
|---|---|
Mở danh sách 50.000 tag, trước đây render toàn bộ | Có thể nhanh hơn 5–50 lần hoặc hơn |
Cuộn danh sách dài | Có thể mượt hơn đáng kể |
Tìm kiếm tag | Có thể nhanh hơn nếu lọc hiệu quả |
Đọc/ghi tag từ PLC, OPC hoặc Socket.IO | Không mặc nhiên nhanh hơn |
Runtime SCADA và cập nhật realtime | Cần tối ưu riêng |
Ví dụ, nếu trước đây mất 10 giây để mở danh sách, mục tiêu hợp lý sau tối ưu có thể là dưới 1–2 giây, nhưng phải đo trên máy thực tế mới kết luận được.
Lưu ý: Phân trang 200 tag/trang giúp giảm số dòng giao diện phải render từ 50.000 xuống 200, tức giảm khoảng 250 lần số dòng hiển thị cần tạo. Điều này không đồng nghĩa toàn ứng dụng nhanh hơn 250 lần.
Để xác định chính xác, cần benchmark ba chỉ số: thời gian mở danh sách, mức sử dụng RAM và độ trễ cập nhật realtime khi chạy đủ 50.000 tag.
bị nghẽn.

