Array.Copy so với Buffer.BlockCopy


124

Array.CopyBuffer.BlockCopy đều làm điều tương tự, nhưng BlockCopynhằm mục đích sao chép mảng nguyên thủy cấp byte nhanh, trong khi đó Copylà việc triển khai mục đích chung. Câu hỏi của tôi là - bạn nên sử dụng trong những trường hợp BlockCopynào? Bạn có nên sử dụng nó bất cứ lúc nào khi bạn đang sao chép các mảng kiểu nguyên thủy hay chỉ nên sử dụng nó nếu bạn đang viết mã cho hiệu suất? Có điều gì nguy hiểm về việc sử dụng Buffer.BlockCopyquá mức Array.Copykhông?


3
Đừng quên Marshal.Copy:-). Tốt, sử dụng Array.Copycho các kiểu tham chiếu, kiểu giá trị phức tạp và nếu kiểu không thay đổi, Buffer.BlockCopyđể "chuyển đổi" giữa các kiểu giá trị, mảng byte và phép byte. F.ex. sự kết hợp với StructLayoutkhá mạnh mẽ nếu bạn biết mình đang làm gì. Đối với hiệu suất, có vẻ như cuộc gọi không được quản lý đến memcpy/ cpblklà nhanh nhất cho điều đó - xem code4k.blogspot.nl/2010/10/… .
atlaste

1
Tôi đã làm một số bài kiểm tra điểm chuẩn với byte[]. Không có sự khác biệt trong phiên bản phát hành. Đôi khi Array.Copy, đôi khi Buffer.BlockCopy(hơi) nhanh hơn.
Bitterblue

Câu trả lời toàn diện mới vừa được đăng dưới đây. Lưu ý rằng trong trường hợp có kích thước bộ đệm nhỏ, sao chép vòng lặp rõ ràng thường là tốt nhất.
Sốt đặc biệt

Tôi không nghĩ rằng họ luôn luôn làm điều tương tự - bạn không thể sử dụng Array.Copy để sao chép một mảng của Ints tới một mảng của Bytes ví dụ
mcmillab

Array.Copylà một phiên bản chuyên biệt hơn - ví dụ như nó chỉ có thể sao chép các mảng cùng thứ hạng.
astrowalker

Câu trả lời:


59

Vì các tham số Buffer.BlockCopydựa trên byte thay vì dựa trên chỉ mục, bạn có nhiều khả năng làm hỏng mã của mình hơn là nếu bạn sử dụng Array.Copy, vì vậy tôi sẽ chỉ sử dụng Buffer.BlockCopytrong phần quan trọng về hiệu suất của mã của mình.


9
Hoàn toàn đồng ý. Có quá nhiều chỗ cho lỗi với Buffer.BlockCopy. Hãy đơn giản và đừng cố vắt bất kỳ nước trái cây nào ra khỏi chương trình của bạn cho đến khi bạn biết nước ép ở đâu (định hình).
Stephen

5
Điều gì sẽ xảy ra nếu bạn đang xử lý một byte []? Có bất kỳ mẹo nào khác với BlockCopy không?
thecoop

4
@thecoop: nếu bạn đang xử lý một byte [] thì có lẽ bạn nên sử dụng BlockCopy, trừ khi định nghĩa của "byte" sau đó được thay đổi thành một thứ gì đó khác với byte, điều này có thể có ảnh hưởng khá tiêu cực đến các phần khác của mã của bạn dù sao. :) Điểm có tiềm năng duy nhất khác là BlockCopy chỉ thực hiện các byte thẳng, vì vậy nó không cần tính đến khả năng kết thúc, nhưng điều này sẽ chỉ phát huy tác dụng trên máy không phải Windows và chỉ khi bạn sửa mã trong nơi đầu tiên. Ngoài ra, có thể có một số khác biệt kỳ lạ nếu bạn đang sử dụng mono.
MusiGenesis 09/09/09

6
Trong thử nghiệm của riêng tôi, Array.Copy () có hiệu suất rất giống với Buffer.BlockCopy (). Buffer.BlockCopy liên tục nhanh hơn <10% đối với tôi khi xử lý mảng 640 byte phần tử (là loại tôi quan tâm nhất). Nhưng bạn nên tự kiểm tra dữ liệu của riêng mình, vì có lẽ nó sẽ thay đổi tùy thuộc vào dữ liệu, kiểu dữ liệu, kích thước mảng, v.v. Tôi nên lưu ý rằng cả hai phương pháp đều nhanh hơn khoảng 3 lần so với sử dụng Array.Clone () và có thể nhanh hơn 20 lần so với việc sao chép nó trong vòng lặp for.
Ken Smith

3
@KevinMiller: uh, UInt16là hai byte cho mỗi phần tử. Nếu bạn truyền mảng này cho BlockCopy cùng với số phần tử trong mảng, tất nhiên chỉ một nửa mảng sẽ được sao chép. Đối với điều này để làm việc đúng cách, bạn sẽ cần phải vượt qua số phần tử lần kích thước của mỗi phần tử (2) như các thông số chiều dài. msdn.microsoft.com/en-us/library/… và tìm kiếm INT_SIZEtrong các ví dụ.
MusiGenesis

129

Khúc dạo đầu

Tôi tham gia bữa tiệc muộn, nhưng với 32 nghìn lượt xem, điều này đáng để làm đúng. Hầu hết mã microbenchmarking trong các câu trả lời đã đăng cho đến nay đều mắc phải một hoặc nhiều lỗi kỹ thuật nghiêm trọng, bao gồm cả việc không di chuyển phân bổ bộ nhớ ra khỏi các vòng kiểm tra (giới thiệu các tạo tác GC nghiêm trọng), không kiểm tra biến so với luồng thực thi xác định, khởi động JIT, và không theo dõi sự thay đổi trong thử nghiệm. Ngoài ra, hầu hết các câu trả lời không kiểm tra tác động của các kích thước bộ đệm khác nhau và các kiểu nguyên thủy khác nhau (đối với hệ thống 32 bit hoặc 64 bit). Để giải quyết câu hỏi này một cách toàn diện hơn, tôi đã kết nối nó với một khuôn khổ đánh dấu microbenchmarking tùy chỉnh mà tôi đã phát triển để giảm hầu hết các "lỗi" phổ biến đến mức có thể. Các thử nghiệm đã được chạy ở chế độ Phát hành .NET 4.0 trên cả máy 32 bit và máy 64 bit. Kết quả được tính trung bình trên 20 lần chạy thử nghiệm, trong đó mỗi lần chạy có 1 triệu lần thử nghiệm cho mỗi phương pháp. Các loại ban đầu được kiểm tra làbyte(1 byte), int(4 byte) và double(8 byte). Ba phương pháp đã được thử nghiệm: Array.Copy(), Buffer.BlockCopy(), và đơn giản chuyển nhượng cho mỗi chỉ số trong một vòng lặp. Dữ liệu quá nhiều để đăng ở đây, vì vậy tôi sẽ tóm tắt những điểm quan trọng.

Những điều rút ra

  • Nếu độ dài bộ đệm của bạn khoảng 75-100 hoặc ít hơn, quy trình sao chép vòng lặp rõ ràng thường nhanh hơn (khoảng 5%) so với Array.Copy()hoặc Buffer.BlockCopy()đối với cả 3 kiểu nguyên thủy được thử nghiệm trên cả máy 32 bit và 64 bit. Ngoài ra, quy trình sao chép vòng lặp rõ ràng có sự thay đổi hiệu suất thấp hơn đáng kể so với hai lựa chọn thay thế. Hiệu suất tốt gần như chắc chắn là do vị trí của tham chiếu được bộ nhớ đệm CPU L1 / L2 / L3 khai thác kết hợp với không có phí gọi phương thức.
    • Đối với doublebộ đệm chỉ trên máy 32-bit : Quy trình sao chép vòng lặp rõ ràng tốt hơn cả hai lựa chọn thay thế cho tất cả các kích thước bộ đệm được thử nghiệm lên đến 100k. Cải thiện tốt hơn 3-5% so với các phương pháp khác. Điều này là do hiệu suất của Array.Copy()Buffer.BlockCopy() trở nên suy giảm hoàn toàn khi vượt qua chiều rộng 32 bit gốc. Vì vậy, tôi cho rằng hiệu ứng tương tự sẽ áp dụng cholong bộ đệm.
  • Đối với kích thước bộ đệm vượt quá ~ 100, việc sao chép vòng lặp rõ ràng nhanh chóng trở nên chậm hơn nhiều so với 2 phương pháp còn lại (với một ngoại lệ cụ thể vừa được lưu ý). Sự khác biệt đáng chú ý nhất vớibyte[] , khi sao chép vòng lặp rõ ràng có thể trở nên chậm hơn 7 lần hoặc hơn ở kích thước bộ đệm lớn.
  • Nói chung, đối với cả 3 kiểu nguyên thủy đã được thử nghiệm và trên tất cả các kích thước bộ đệm, Array.Copy()Buffer.BlockCopy()hoạt động gần như giống nhau. Trung bình, Array.Copy()có vẻ như có một lợi thế rất nhỏ khoảng 2% hoặc ít hơn thời gian thực hiện (nhưng 0,2% - 0,5% tốt hơn là điển hình), mặc dùBuffer.BlockCopy() đôi khi đã đánh bại nó. Vì những lý do không xác định, Buffer.BlockCopy()có sự thay đổi trong thử nghiệm cao hơn đáng kể so với Array.Copy(). Hiệu ứng này không thể bị loại bỏ mặc dù tôi đã thử nhiều biện pháp giảm nhẹ và không có một lý thuyết có thể hoạt động về lý do tại sao.
  • Bởi vì Array.Copy()là một phương pháp "thông minh hơn", tổng quát hơn và an toàn hơn nhiều, ngoài việc nhanh hơn một chút và ít thay đổi trung bình, nó nên được ưa thích Buffer.BlockCopy()trong hầu hết các trường hợp phổ biến. Trường hợp sử dụng duy nhất Buffer.BlockCopy()sẽ tốt hơn đáng kể là khi kiểu giá trị mảng nguồn và đích khác nhau (như đã chỉ ra trong câu trả lời của Ken Smith). Mặc dù kịch bản này không phổ biến, nhưng Array.Copy()có thể hoạt động rất kém ở đây do liên tục truyền loại giá trị "an toàn", so với truyền trực tiếp Buffer.BlockCopy().
  • Bạn có thể tìm thấy bằng chứng bổ sung từ bên ngoài StackOverflow Array.Copy()nhanh hơn so Buffer.BlockCopy()với sao chép mảng cùng loại tại đây .

Là một sang một bên, nó cũng chỉ ra rằng xung quanh chiều dài mảng của 100 là khi NET là Array.Clear()lần đầu tiên bắt đầu để đánh bại một thanh toán bù trừ giao loop rõ ràng của một mảng (thiết lập để false, 0hoặc null). Điều này phù hợp với những phát hiện tương tự của tôi ở trên. Những tiêu chuẩn riêng biệt đã được phát hiện trực tuyến tại đây: manski.net/2012/12/net-array-clear-vs-arrayx-0-performance
Sauce đặc biệt

Khi bạn nói kích thước bộ đệm; ý bạn là tính theo byte hay số phần tử?
dmarra

Trong câu trả lời ở trên của tôi, cả "độ dài bộ đệm" và "kích thước bộ đệm" thường đề cập đến số phần tử.
Sốt đặc biệt vào

Tôi có một ví dụ trong đó tôi cần thường xuyên sao chép khoảng 8 byte dữ liệu vào một bộ đệm đọc từ nguồn có độ lệch 5 byte. Tôi thấy bản sao vòng lặp rõ ràng nhanh hơn đáng kể sau đó sử dụng Buffer.BlockCopy hoặc Array.Copy. Loop Results for 1000000 iterations 17.9515ms. Buffer.BlockCopy Results for 1000000 iterations 39.8937ms. Array.Copy Results for 1000000 iterations 45.9059ms Tuy nhiên, nếu kích thước bản sao> ~ 20 byte, vòng lặp rõ ràng sẽ chậm hơn đáng kể.
Tod Cunningham

@TodCunningham, 8 byte dữ liệu? Bạn có nghĩa là tương đương dài? Truyền và sao chép phần tử đơn lẻ (chết nhanh) hoặc đơn giản là giải nén vòng lặp đó theo cách thủ công.
con chim tu hú

67

Một ví dụ khác về thời điểm hợp lý để sử dụng Buffer.BlockCopy()là khi bạn được cung cấp một mảng nguyên thủy (ví dụ, quần short) và cần chuyển đổi nó thành một mảng byte (ví dụ, để truyền qua mạng). Tôi sử dụng phương pháp này thường xuyên khi xử lý âm thanh từ Silverlight AudioSink. Nó cung cấp mẫu dưới dạng một short[]mảng, nhưng bạn cần chuyển nó thành một byte[]mảng khi bạn đang xây dựng gói mà bạn gửi đến Socket.SendAsync(). Bạn có thể sử dụng BitConvertervà lặp lại từng mảng một, nhưng nhanh hơn rất nhiều (khoảng 20 lần trong thử nghiệm của tôi) chỉ để làm điều này:

Buffer.BlockCopy(shortSamples, 0, packetBytes, 0, shortSamples.Length * sizeof(short)).  

Và thủ thuật tương tự cũng hoạt động ngược lại:

Buffer.BlockCopy(packetBytes, readPosition, shortSamples, 0, payloadLength);

Điều này gần giống như bạn nhận được trong C # an toàn với (void *)kiểu quản lý bộ nhớ rất phổ biến trong C và C ++.


6
Đó là một ý tưởng tuyệt vời - bạn có bao giờ gặp vấn đề với sự kết thúc không?
Phillip

Vâng, tôi nghĩ rằng bạn có thể gặp phải vấn đề đó, tùy thuộc vào tình huống của bạn. Các tình huống của riêng tôi thường là (a) Tôi cần chuyển đổi qua lại giữa mảng byte và mảng ngắn trên cùng một máy hoặc (b) Tôi tình cờ biết rằng tôi đang gửi dữ liệu của mình đến các máy giống nhau endianness, và cái mà tôi điều khiển từ xa. Nhưng nếu bạn đang sử dụng một giao thức mà máy từ xa mong đợi dữ liệu được gửi theo thứ tự mạng thay vì thứ tự máy chủ, thì đúng, cách tiếp cận này sẽ gây ra vấn đề cho bạn.
Ken Smith

Ken cũng có một bài viết về BlockCopy trên blog của anh ấy: blog.wouldbetheologian.com/2011/11/…
Drew Noakes

4
Lưu ý rằng kể từ .Net Core 2.1, bạn có thể thực hiện việc này mà không cần sao chép. MemoryMarshal.AsBytes<T>hoặc MemoryMarshal.Cast<TFrom, TTo>cho phép bạn diễn giải trình tự của một nguyên thủy như một chuỗi nguyên thủy khác.
Timo

16

Dựa trên thử nghiệm của tôi, hiệu suất không phải là lý do để thích Buffer.BlockCopy hơn Array.Copy. Từ thử nghiệm của tôi, Array.Copy thực sự nhanh hơn Buffer.BlockCopy.

var buffer = File.ReadAllBytes(...);

var length = buffer.Length;
var copy = new byte[length];

var stopwatch = new Stopwatch();

TimeSpan blockCopyTotal = TimeSpan.Zero, arrayCopyTotal = TimeSpan.Zero;

const int times = 20;

for (int i = 0; i < times; ++i)
{
    stopwatch.Start();
    Buffer.BlockCopy(buffer, 0, copy, 0, length);
    stopwatch.Stop();

    blockCopyTotal += stopwatch.Elapsed;

    stopwatch.Reset();

    stopwatch.Start();
    Array.Copy(buffer, 0, copy, 0, length);
    stopwatch.Stop();

    arrayCopyTotal += stopwatch.Elapsed;

    stopwatch.Reset();
}

Console.WriteLine("bufferLength: {0}", length);
Console.WriteLine("BlockCopy: {0}", blockCopyTotal);
Console.WriteLine("ArrayCopy: {0}", arrayCopyTotal);
Console.WriteLine("BlockCopy (average): {0}", TimeSpan.FromMilliseconds(blockCopyTotal.TotalMilliseconds / times));
Console.WriteLine("ArrayCopy (average): {0}", TimeSpan.FromMilliseconds(arrayCopyTotal.TotalMilliseconds / times));

Đầu ra mẫu:

bufferLength: 396011520
BlockCopy: 00:00:02.0441855
ArrayCopy: 00:00:01.8876299
BlockCopy (average): 00:00:00.1020000
ArrayCopy (average): 00:00:00.0940000

1
Xin lỗi vì câu trả lời này chỉ là một bình luận, nhưng nó quá dài cho một bình luận. Vì sự đồng thuận dường như là Buffer.BlockCopy tốt hơn cho tốc độ thực hiện, tôi nghĩ mọi người nên biết rằng tôi không thể xác nhận sự đồng thuận đó bằng thử nghiệm.
Kevin

10
Tôi nghĩ rằng có một vấn đề với phương pháp kiểm tra của bạn. Hầu hết sự khác biệt về thời gian mà bạn đang lưu ý là kết quả của việc ứng dụng tự quay lên, tự lưu vào bộ nhớ đệm, chạy JIT, đại loại là vậy. Hãy thử nó với một bộ đệm nhỏ hơn, nhưng vài nghìn lần; và sau đó lặp lại toàn bộ bài kiểm tra trong vòng nửa chục lần và chỉ chú ý đến lần chạy cuối cùng. Thử nghiệm của riêng tôi có Buffer.BlockCopy () chạy có thể nhanh hơn 5% so với Array.Copy () cho mảng 640 byte. Không nhanh hơn nhiều, nhưng một chút.
Ken Smith

2
Tôi đã đo tương tự cho một vấn đề cụ thể, tôi không thể thấy sự khác biệt về hiệu suất giữa Array.Copy () và Buffer.BlockCopy () . Nếu có bất cứ điều gì, BlockCopy đã giới thiệu tính không an toàn thực sự đã giết chết ứng dụng của tôi trong một trường hợp.
gatopeich

1
Cũng giống như thêm Array.Copy hỗ trợ long cho vị trí nguồn vì vậy việc chia thành các mảng byte lớn sẽ không tạo ra ngoại lệ ngoài phạm vi.
Alxwest,

2
Dựa trên bài kiểm tra tôi vừa thực hiện ( bitbucket.org/breki74/tutis/commits/… ), tôi sẽ nói rằng không có sự khác biệt về hiệu suất thực tế giữa hai phương pháp khi bạn xử lý mảng byte.
Igor Brejc

4

ArrayCopy thông minh hơn BlockCopy. Nó tìm ra cách sao chép các phần tử nếu nguồn và đích là cùng một mảng.

Nếu chúng ta điền một mảng int với 0,1,2,3,4 và áp dụng:

Array.Copy (array, 0, array, 1, array.Length - 1);

chúng tôi kết thúc với 0,0,1,2,3 như mong đợi.

Hãy thử điều này với BlockCopy và chúng tôi nhận được: 0,0,2,3,4. Nếu tôi chỉ địnharray[0]=-1 sau đó, nó sẽ trở thành -1,0,2,3,4 như mong đợi, nhưng nếu độ dài mảng là chẵn, như 6, chúng tôi nhận được -1,256,2,3,4,5. Những thứ nguy hiểm. Không sử dụng BlockCopy ngoài việc sao chép một mảng byte sang một mảng khác.

Có một trường hợp khác mà bạn chỉ có thể sử dụng Array.Copy: nếu kích thước mảng dài hơn 2 ^ 31. Array.Copy bị quá tải với một longtham số kích thước. BlockCopy không có điều đó.


2
Kết quả kiểm tra của bạn với BlockCopy không nằm ngoài dự đoán. Đó là bởi vì Block copy cố gắng sao chép các khối dữ liệu tại một thời điểm thay vì từng byte một. Trên hệ thống 32 bit, nó sao chép 4 byte một lúc, trên hệ thống 64 bit, nó sao chép 8 byte cùng một lúc.
Pharap

Vì vậy, hành vi không xác định được mong đợi.
binki

2

Để cân nhắc về lập luận này, nếu một người không cẩn thận về cách họ tạo ra điểm chuẩn này, họ có thể dễ dàng bị nhầm lẫn. Tôi đã viết một bài kiểm tra rất đơn giản để minh họa điều này. Trong thử nghiệm của tôi dưới đây, nếu tôi hoán đổi thứ tự các thử nghiệm của mình giữa việc khởi động Buffer.BlockCopy trước hoặc Array. Sao chép cái đi trước hầu như luôn là chậm nhất (mặc dù nó là một bản đóng). Điều này có nghĩa là vì một loạt lý do mà tôi sẽ không đi vào chỉ đơn giản là chạy thử nghiệm nhiều lần, đặc biệt là lần này đến lần khác sẽ không cho kết quả chính xác.

Tôi đã sử dụng để duy trì thử nghiệm như hiện tại với 1000000 lần thử cho mỗi dãy 1000000 lần nhân đôi liên tiếp. Tuy nhiên, sau đó tôi bỏ qua 900000 chu kỳ đầu tiên và lấy trung bình phần còn lại. Trong trường hợp đó, Buffer là ưu việt hơn.

private static void BenchmarkArrayCopies()
        {
            long[] bufferRes = new long[1000000];
            long[] arrayCopyRes = new long[1000000];
            long[] manualCopyRes = new long[1000000];

            double[] src = Enumerable.Range(0, 1000000).Select(x => (double)x).ToArray();

            for (int i = 0; i < 1000000; i++)
            {
                bufferRes[i] = ArrayCopyTests.ArrayBufferBlockCopy(src).Ticks;
            }

            for (int i = 0; i < 1000000; i++)
            {
                arrayCopyRes[i] = ArrayCopyTests.ArrayCopy(src).Ticks;
            }

            for (int i = 0; i < 1000000; i++)
            {
                manualCopyRes[i] = ArrayCopyTests.ArrayManualCopy(src).Ticks;
            }

            Console.WriteLine("Loop Copy: {0}", manualCopyRes.Average());
            Console.WriteLine("Array.Copy Copy: {0}", arrayCopyRes.Average());
            Console.WriteLine("Buffer.BlockCopy Copy: {0}", bufferRes.Average());

            //more accurate results - average last 1000

            Console.WriteLine();
            Console.WriteLine("----More accurate comparisons----");

            Console.WriteLine("Loop Copy: {0}", manualCopyRes.Where((l, i) => i > 900000).ToList().Average());
            Console.WriteLine("Array.Copy Copy: {0}", arrayCopyRes.Where((l, i) => i > 900000).ToList().Average());
            Console.WriteLine("Buffer.BlockCopy Copy: {0}", bufferRes.Where((l, i) => i > 900000).ToList().Average());
            Console.ReadLine();
        }

public class ArrayCopyTests
    {
        private const int byteSize = sizeof(double);

        public static TimeSpan ArrayBufferBlockCopy(double[] original)
        {
            Stopwatch watch = new Stopwatch();
            double[] copy = new double[original.Length];
            watch.Start();
            Buffer.BlockCopy(original, 0 * byteSize, copy, 0 * byteSize, original.Length * byteSize);
            watch.Stop();
            return watch.Elapsed;
        }

        public static TimeSpan ArrayCopy(double[] original)
        {
            Stopwatch watch = new Stopwatch();
            double[] copy = new double[original.Length];
            watch.Start();
            Array.Copy(original, 0, copy, 0, original.Length);
            watch.Stop();
            return watch.Elapsed;
        }

        public static TimeSpan ArrayManualCopy(double[] original)
        {
            Stopwatch watch = new Stopwatch();
            double[] copy = new double[original.Length];
            watch.Start();
            for (int i = 0; i < original.Length; i++)
            {
                copy[i] = original[i];
            }
            watch.Stop();
            return watch.Elapsed;
        }
    }

https://github.com/chivandikwa/Random-Benchmarks


5
Tôi không thấy bất kỳ kết quả thời gian nào trong câu trả lời của bạn. Vui lòng bao gồm đầu ra bảng điều khiển.
ToolmakerSteve

0

Chỉ muốn thêm trường hợp thử nghiệm của tôi để hiển thị lại BlockCopy không có lợi ích 'PERFORMANCE' so với Array.Copy. Chúng dường như có cùng hiệu suất trong chế độ phát hành trên máy của tôi (cả hai đều mất khoảng 66ms để sao chép 50 triệu số nguyên). Trong chế độ gỡ lỗi, BlockCopy chỉ nhanh hơn một chút.

    private static T[] CopyArray<T>(T[] a) where T:struct 
    {
        T[] res = new T[a.Length];
        int size = Marshal.SizeOf(typeof(T));
        DateTime time1 = DateTime.Now;
        Buffer.BlockCopy(a,0,res,0, size*a.Length);
        Console.WriteLine("Using Buffer blockcopy: {0}", (DateTime.Now - time1).Milliseconds);
        return res;
    }

    static void Main(string[] args)
    {
        int simulation_number = 50000000;
        int[] testarray1 = new int[simulation_number];

        int begin = 0;
        Random r = new Random();
        while (begin != simulation_number)
        {
            testarray1[begin++] = r.Next(0, 10000);
        }

        var copiedarray = CopyArray(testarray1);

        var testarray2 = new int[testarray1.Length];
        DateTime time2 = DateTime.Now;
        Array.Copy(testarray1, testarray2, testarray1.Length);
        Console.WriteLine("Using Array.Copy(): {0}", (DateTime.Now - time2).Milliseconds);
    }

3
Không vi phạm nhưng kết quả kiểm tra của bạn không thực sự hữu ích;) Trước hết, "nhanh hơn 20ms" cho bạn biết không có gì nếu không biết thời gian tổng thể. Bạn cũng đã thực hiện hai bài kiểm tra đó theo một cách rất khác nhau. Trường hợp BlockCopy có một lệnh gọi phương thức bổ sung và phân bổ mảng đích của bạn mà bạn không có trong trường hợp Array.Copy của mình. Do biến động đa luồng (có thể có chuyển đổi tác vụ, chuyển đổi lõi), bạn có thể dễ dàng nhận được các kết quả khác nhau mỗi khi thực hiện kiểm tra.
Bunny83

@ Bunny83 cảm ơn vì nhận xét. Tôi đã sửa đổi một chút vị trí hẹn giờ, điều này sẽ đưa ra một so sánh công bằng hơn bây giờ. Và tôi hơi ngạc nhiên rằng blockcopy không nhanh hơn array.copy chút nào.
stt106
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.