Lâu lâu quay lại tham gia góp vui.
Mã ASM của các dạng GetSumRange vẫn còn chậm. Bị vướng 2 cái sau, nên khó đè đầu ngoạn mục thằng VBA được. Viết đúng nó phải nhanh hơn gấp 10 lần
1. Trong vòng for i, biến j được get lại nhiều lần qua 2 hàm VarArrayLowBound và VarArrayHighBound
Nhìn kỹ thì VarArrayLowBound(arr, 2) và VarArrayHighBound(arr, 2) là hằng khi vào hàm.
Nên chúng ta đẩy (cache) giá trị nó ra ngoài vòng for i.
2. iSum := iSum + TVarData(arr[i, j]).VDouble => Delphi compiler chèn mã lệnh call tới hàm internal linkproc VarArrayGet, làm chậm đi ít nữa
Nên ép kiểu qua PSafeArray rồi truy xuất pointer tới trực tiếp từng giá trị double luôn.
Dùng trực tiếp các hàm API về SafeArray, seek pointer tới ngay vùng đầu data của PSafeArray.
Vd hàm API SafeArrayPtrOfIndex
Các bạn đọc source hàm _VarArrayGet trong file System.Variants.pas để tham khảo thêm
Giải quyết 1 và 2 đủ bóp cổ code thông dịch của VBA
PS: bổ sung, nếu biến truyền vào hàm các bạn muốn dùng truyền theo kiểu byref giống VBA và các bạn không thay đổi nội dung biến đó, các bạn thay vì viết var X: YYYY thì có thể viết const X: YYYY
Compiler sẽ sinh mã truyền by pointer cho các bạn, và kiểm tra luôn nếu code các bạn có tiềm tàng thay đổi nội dung biến hay không, và sẽ báo error hay warning ngay lúc compile.
VD: GetSumRange(const arr: Variant): Double; stdcall;
Khai báo là var arr: Variant thì compiler mặc định xem như biến arr sẽ bị thay đổi
Vài góp ý nhỏ, chân chọng, bét xì ga