2013-07-17 28 views
8

Tôi đang viết một hàm vẽ hình ảnh vào pixel yếu tố canvas theo pixel. Tôi nhận thấy rằng có một điểm, nơi mà chức năng đột nhiên mất nhiều thời gian hơn để xử lý hơn trước đây - cụ thể là từ một canvas 338x338 pixel đến một khung ảnh 339x339 pixel.Sự khác biệt về xử lý rất cao giữa hai vòng gần như tương tự nhau trong khi các vòng

Đưa chức năng tìm kiếm tương tự vào jsfiddle, tôi nhận được kết quả tương tự. Vòng lặp while xử lý một mảng gồm 338x338 mất khoảng. 6-7 giây, trong khi một mảng 339x339 mất khoảng. 24-25 giây.

Điều này đang xảy ra trên Chrome. Trong Firefox cả hai đều mất khoảng. 16 giây.

Đây là fiddle: http://jsfiddle.net/8pb89/5/

Mã này trông như thế này:

var ary1 = []; 
var ary2 = []; 
var mapData = {}; 
var colorMatrix = {}; 

for (var i = 0; i < (338 * 338); i++) { 
    ary1.push([i, i + 2]); 
} 

for (var i = 0; i < (339 * 339); i++) { 
    ary2.push([i, i + 2]); 
} 

//Light operation 
function test(i, j) { 
    return Math.floor((i * j + i + j)/j); 
} 

//Heavy operation on objects 
function calcTest(ary){ 
    var point = ary.splice(0, 1); 
    var i = point[0]; 
    var j = point[1]; 

    if (!mapData[i]) { 
     mapData[i] = []; 
    } 
    if (!mapData[i][j]) { 
     mapData[i][j] = []; 
    } 

    mapData[i][j]["one"] = test(i, j); 
    mapData[i][j]["two"] = test(i, j); 

    colorMatrix[mapData[i][j]["two"]] = mapData[i][j]["one"]; 

} 

var len = ary1.length; 
var start = new Date().getTime(); 

while (len--) { 
    calcTest(ary1); 
} 

var end = new Date().getTime(); 
var time = end - start; 
alert('Execution for 338x338: ' + time); 

var len2 = ary2.length; 
obj = {}; 
obj2 = {}; 

start = new Date().getTime(); 
while (len2--) { 
    calcTest(ary2); 
} 
end = new Date().getTime(); 
time = end - start; 
alert('Execution for 339x339: ' + time); 

Đây có phải là một vấn đề bộ nhớ với javascript trên Chrome, hay tôi làm điều gì sai với các đối tượng? Có cách nào để tránh thời gian xử lý cao hơn này không?

+2

Thú vị. http://jsperf.com/chrome-loops-test – climbage

+0

Tôi không biết điều này có nghĩa vụ phải làm gì, nhưng có nhiều sai lầm trong hàm 'calcTest' đó. Bạn có muốn xây dựng? – Bergi

+0

Fiddle chỉ là một phiên bản đơn giản hóa chức năng của tôi, vì vậy tôi có thể kiểm tra sự khác biệt giữa các mảng 338x338 và 339x339. Trong chương trình cuối cùng, mảng (ary1/ary2) chứa tọa độ, chưa được xử lý. Hàm calcTest tính toán màu pixel cho tọa độ và lưu trữ dữ liệu trong đối tượng mapData và đối tượng colorMatrix (được đổi tên trong ví dụ trên) – LongInt

Trả lời

1

Tôi đoán đó là một hoặc cả hai điều sau đây.

  • Chrome đang thay đổi kích thước phần bắt đầu cơ bản ở đâu đó giữa 338 * 338339 * 339.
  • Thu gom rác đang diễn ra trong cùng một khung thời gian.

Tôi nghi ngờ đây là vấn đề về bộ nhớ.

1

Hãy xem xét hoạt động SPLICE của bạn thực sự đang làm gì. Hãy chạy qua nối mảng này:

[0,1,2,3,4,5]

tôi phải:

STORE the 0 
READ the 1, WRITE to where the 0 was 
READ the 2, WRITE to where the 1 was 
READ the 3, WRITE to where the 2 was 
READ the 4, WRITE to where the 3 was 
READ the 5, WRITE to where the 4 was 
DELETE the 5 

đó là 12 hoạt động (trên một mảng đó là 6 mục lớn) ... mảng của bạn là nhiều, lớn hơn nhiều (hơn 100 nghìn mặt hàng) ... và bạn đang lặp qua chúng, cắt chúng xuống khi bạn đi. Tôi kiếm được khoảng 26 tỷ phép tính mà bạn yêu cầu trong mã của bạn !!!

Tôi đã xác thực lại mã của bạn để đặt vòng lặp while trong thử nghiệm và KHÔNG sử dụng chức năng SPLICE - Bây giờ tôi đã kiểm tra xuống 23ms và 25ms trên máy của tôi (đạt được kết quả tương tự như kiểm tra của bạn). Ví dụ của bạn lấy 3599ms và 19464ms - hiệu quả gần gấp 500 lần :)

Bạn có nhiều vấn đề khác với mã này, nhưng điều này dẫn đến trọng tâm của vấn đề lớn nhất của bạn!

var ary1 = []; 
var ary2 = []; 
var mapData = {}; 
var colorMatrix = {}; 

for (var i = 0; i < (338 * 338); i++) { 
    ary1.push([i, i + 2]); 
} 

for (var i = 0; i < (339 * 339); i++) { 
    ary2.push([i, i + 2]); 
} 

//Light operation 
function test(i, j) { 
    return Math.floor((i * j + i + j)/j); 
} 

//Heavy operation on objects 
function calcTest(ary){ 
    for (index=ary.length-1;index>=0;index--){ 
     var point=ary[index]; 

     var i = point[0]; 
     var j = point[1]; 

     if (!mapData[i]) { 
      mapData[i] = []; 
     } 
     if (!mapData[i][j]) { 
      mapData[i][j] = []; 
     } 

     mapData[i][j]["one"] = test(i, j); 
     mapData[i][j]["two"] = test(i, j); 

     colorMatrix[mapData[i][j]["two"]] = mapData[i][j]["one"]; 
    } 
} 

//I'm only putting the following lines in first to show that the first 
//Operation takes longer by populating the mapData and colorMatrix arrays 
//If you delete the next two lines you'll find that the 339 option takes 
//less time than the 338 (because it's going second!) 
calcTest(ary1); 
calcTest(ary2); 

var start = new Date().getTime(); 
calcTest(ary1); 
var end = new Date().getTime(); 
var time = end - start; 
alert('Execution for 338x338: ' + time); 

start = new Date().getTime(); 
calcTest(ary2); 
end = new Date().getTime(); 
time = end - start; 
alert('Execution for 339x339: ' + time); 
+0

Cảm ơn bạn đã tối ưu hóa, tôi đang làm điều này như một dự án sở thích, vì vậy không có nhiều kinh nghiệm với javascript. Nếu bạn đề cập đến những vấn đề khác mà bạn thấy, tôi cũng rất hoan nghênh điều đó, bởi vì nó sẽ giúp tôi học hỏi. – LongInt

Các vấn đề liên quan