From 050c1620a9149fcc1bf84e36d02bb111455e453d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96mer=20Sinan=20A=C4=9Facan?= Date: Mon, 23 Oct 2023 10:51:00 +0200 Subject: [PATCH] Optimize `CodedBufferWriter._copyInto` to memcpy (#885) dart2wasm currently can't optimize loops into memcpy, however `setRange` methods have type tests to generate `array.copy` (Wasm's `memcpy`). Replacing the loops in `CodedBufferWriter._copyInto` with `setRange` improves an internal benchmark extracted from a real use case significantly in all targets: | | Before | After | Diff | |------------------------------|------------|------------|---------------------| | AOT | 127,587 us | 95,634 us | -31,953 us, -25.0% | | JIT | 106,880 us | 92,800 us | -14,080 us, -13.1% | | dart2js -O4 | 285,587 us | 262,222 us | -23,365 us, -8.1% | | dart2wasm --omit-type-checks | 337,000 us | 236,100 us | -100,900 us, -29.9% | --- .../lib/src/protobuf/coded_buffer_writer.dart | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/protobuf/lib/src/protobuf/coded_buffer_writer.dart b/protobuf/lib/src/protobuf/coded_buffer_writer.dart index 6391584c3..e149fabd0 100644 --- a/protobuf/lib/src/protobuf/coded_buffer_writer.dart +++ b/protobuf/lib/src/protobuf/coded_buffer_writer.dart @@ -421,22 +421,19 @@ class CodedBufferWriter { /// Copy bytes from the given typed data array into the output buffer. /// - /// Has a specialization for Uint8List for performance. + /// Has a specialization for [Uint8List] for performance. int _copyInto(Uint8List buffer, int pos, TypedData value) { if (value is Uint8List) { final len = value.length; - for (var j = 0; j < len; j++) { - buffer[pos++] = value[j]; - } - return pos; + final end = pos + len; + buffer.setRange(pos, end, value); + return end; } else { final len = value.lengthInBytes; - final u8 = Uint8List.view( - value.buffer, value.offsetInBytes, value.lengthInBytes); - for (var j = 0; j < len; j++) { - buffer[pos++] = u8[j]; - } - return pos; + final end = pos + len; + final u8 = Uint8List.view(value.buffer, value.offsetInBytes, len); + buffer.setRange(pos, end, u8); + return end; } }