如何提高Dart数据转换性能/从二进制? [英] How to improve Dart performance of data conversion to/from binary?

查看:2949
本文介绍了如何提高Dart数据转换性能/从二进制?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为更大的德国公司做一些咨询工作Future Technologies Group我已经将大约6000行Java服务器端软件移植到Dart。这应该有助于回答Dart是否可以有效地在服务器上使用的问题。 (由于搜索了有一种语言用于客户端和服务器端编程的优势,它本身将给Dart一个绿色的光。)

Doing some consulting work for a bigger German companies Future Technologies Group I have ported about 6000 lines of Java server side software to Dart. This should help to answer the question whether Dart can efficiently be used on the server. (Which itself would give a green light for Dart due to the searched for advantage of having one language for client and server side programming.)

学习Dart喜欢使用)给了我相对于Java的性能损失30-50%的期望,但在任何情况下都不会比上述决策过程的截止值100%(两倍慢)。

Learning about Dart (which I really enjoyed working with) gave me an expectation of a performance penalty of 30-50% relative to Java but in any case no worse than 100% (twice as slow) which is the cutoff for the decision process mentioned above.

港口顺利。我学到了很多。单元测试很好。但是性能最糟糕的是,与Java程序相比,整体速度减慢了SEVEN倍。

The port went smoothly. I learned a lot. Unit tests were fine. But the performance turned out to be extremly bad ... SEVEN times slower overall compared to the Java program.

分析代码揭示了两个主要原因:数据转换和文件I / O。也许我做错了什么?在我回到我的客户端,他们取消他们的Dart研究之前,我想搜索一些关于如何改进的建议。让我们从数据转换开始,将本机Dart数据类型转换为可用于有效传输和存储数据的各种二进制格式。

Profiling the code revealed two main culprits: data conversion and file I/O. Maybe I'm doing something wrong? Before I go back to my client and they cancel their Dart research I would like to search some advice on how to improve things. Let's start with data conversion, the conversion of native Dart data types into various binary formats which can be used for effective transfer and storage of data.

通常这些转换很简单,非常快,因为没有什么真的要从使用的内部格式转换,但大多存储到缓冲区。我创建了一个基准程序,它反映了我的程序中这些转换的典型用法:

Usually these conversions are simple and very fast because nothing has really to be converted from the used internal format but mostly stored into a buffer. I created a benchmark program which somehow reflects the typical use of these conversions in my program:

import 'dart:typed_data';
import 'package:benchmark_harness/benchmark_harness.dart';

// Create a new benchmark by extending BenchmarkBase
class ConversionBenchmark extends BenchmarkBase {

  Uint8List result;

  ConversionBenchmark() : super("Conversion");

  // The benchmark code.
  void run() {
    const int BufSize = 262144; // 256kBytes
    const int SetSize = 64;     // one "typical" set of data, gets repeated
    ByteData buffer = new ByteData(BufSize);
    double doubleContent = 0.0; // used to simulate double content
    int intContent = 0;         // used to simulate int content
    int offset = 0;
    for (int j = 0; j < buffer.lengthInBytes / SetSize; j++) {
      // The following represents some "typical" conversion mix:
      buffer.setFloat64(offset, doubleContent); offset += 8; doubleContent += 0.123;
      for (int k = 0; k < 8; k++) { // main use case
        buffer.setFloat32(offset, doubleContent); offset += 4; doubleContent += 0.123;
      }
      buffer.setInt32(offset, intContent); offset += 4; intContent++;
      buffer.setInt32(offset, intContent); offset += 4; intContent++;
      buffer.setInt16(offset, intContent); offset += 2; intContent++;
      buffer.setInt16(offset, intContent); offset += 2; intContent++;
      buffer.setInt8(offset, intContent); offset += 1; intContent++;
      buffer.setInt8(offset, intContent); offset += 1; intContent++;
      buffer.buffer.asUint8List(offset).setAll(0, "AsciiStrng".codeUnits); offset += 10;
        // [ByteData] knows no other mechanism to transfer ASCII strings in
      assert((offset % SetSize) == 0); // ensure the example content fits [SetSize] bytes
    }
    result = buffer.buffer.asUint8List(); // only this can be used for further processing
  }
}

main() {
  new ConversionBenchmark().report();
}

它是基于从https://github.com/dart-lang/benchmark_harness 。为了进行比较,我使用了以下Java程序,基于来自 https://github.com/bono8106/benchmark_harness_java:

It is based on the benchmark harness from https://github.com/dart-lang/benchmark_harness. For comparisions I used the following Java program based on a port of the Dart benchmark harness from https://github.com/bono8106/benchmark_harness_java:

package ylib.tools;

import java.nio.ByteBuffer;

public class ConversionBenchmark extends BenchmarkBase {

  public ByteBuffer result;

  public ConversionBenchmark() { super("Conversion"); }

  // The benchmark code.
  @Override protected void run() {
    final int BufSize = 262144; // 256kBytes
    final int SetSize = 64;     // one "typical" set of data, gets repeated
    ByteBuffer buffer = ByteBuffer.allocate(BufSize);
    double doubleContent = 0.0; // used to simulate double content
    int intContent = 0;         // used to simulate int content
    for (int j = 0; j < (buffer.capacity() / SetSize); j++) {
      // The following represents some "typical" conversion mix:
      buffer.putDouble(doubleContent); doubleContent += 0.123;
      for (int k = 0; k < 8; k++) { // main use case
        buffer.putFloat((float)doubleContent); doubleContent += 0.123;
      }
      buffer.putInt(intContent); intContent++;
      buffer.putInt(intContent); intContent++;
      buffer.putShort((short)intContent); intContent++;
      buffer.putShort((short)intContent); intContent++;
      buffer.put((byte)intContent); intContent++;
      buffer.put((byte)intContent); intContent++;
      buffer.put("AsciiStrng".getBytes());
      //assert((buffer.position() % SetSize) == 0); // ensure the example content fits [SetSize] bytes
    }
    buffer.flip(); // needed for further processing
    result = buffer; // to avoid the compiler optimizing away everything
  }

  public static void main(String[] args) {
    new ConversionBenchmark().report();
  }
}

Java代码的运行速度几乎比Dart代码在我的Intel Windows 7机器上。两者都在其各自的VM上以生产模式运行。

The Java code runs almost exactly 10 times faster than the Dart code on my Intel Windows 7 machine. Both run in production mode on their respective VMs.

代码中是否有明显错误?还是有不同的Dart类可以做这项工作?任何解释为什么Dart这么简单的转换慢得多?

Is there an obvious error in the code? Or are there different Dart classes available to do the job? Any explanation as to why Dart is so much slower with these simple conversions? Or do I have completely wrong expectations with respect to Dart VM performance?

推荐答案

确实,字节数据方法的性能( ByteData.setXYZ ByteData.getXYZ )在Dart VM上相比直接类型数组访问非常糟糕。我们开始处理这个问题,初步结果是有希望的[1]。

It is true that performance of byte data methods (ByteData.setXYZ and ByteData.getXYZ) is pretty bad on Dart VM compared to direct typed array access. We started working on the issue and initial results are promising[1].

同时,你可以通过滚动自己的转换到大端,来解决这个不幸的性能回归使用类型化数组([2]中的完整代码):

In the mean time you can work around this unfortunate performance regression by rolling your own conversion to big endian using typed arrays (full code at[2]):

/// Writer wraps a fixed size Uint8List and writes values into it using
/// big-endian byte order.
class Writer {
  /// Output buffer.
  final Uint8List out;

  /// Current position within [out].
  var position = 0;

  Writer._create(this.out);

  factory Writer(size) {
    final out = new Uint8List(size);
    if (Endianness.HOST_ENDIAN == Endianness.LITTLE_ENDIAN) {
      return new _WriterForLEHost._create(out);
    } else {
      return new _WriterForBEHost._create(out);
    }
  }

  writeFloat64(double v);

}

/// Lists used for data convertion (alias each other).
final Uint8List _convU8 = new Uint8List(8);
final Float32List _convF32 = new Float32List.view(_convU8.buffer);
final Float64List _convF64 = new Float64List.view(_convU8.buffer);

/// Writer used on little-endian host.
class _WriterForLEHost extends Writer {
  _WriterForLEHost._create(out) : super._create(out);

  writeFloat64(double v) {
    _convF64[0] = v;
    out[position + 7] = _convU8[0];
    out[position + 6] = _convU8[1];
    out[position + 5] = _convU8[2];
    out[position + 4] = _convU8[3];
    out[position + 3] = _convU8[4];
    out[position + 2] = _convU8[5];
    out[position + 1] = _convU8[6];
    out[position + 0] = _convU8[7];
    position += 8;
  }
}


$ b $ p

在您的测试中对此手动转换进行基准测试, :

Benchmarking this manual conversion on your test yields around 6x improvement:

import 'dart:typed_data';
import 'package:benchmark_harness/benchmark_harness.dart';
import 'writer.dart';

class ConversionBenchmarkManual extends BenchmarkBase {

  Uint8List result;

  ConversionBenchmarkManual() : super("Conversion (MANUAL)");

  // The benchmark code.
  void run() {
    const int BufSize = 262144; // 256kBytes
    const int SetSize = 64;     // one "typical" set of data, gets repeated

    final w = new Writer(BufSize);

    double doubleContent = 0.0; // used to simulate double content
    int intContent = 0;         // used to simulate int content
    int offset = 0;
    for (int j = 0; j < (BufSize / SetSize); j++) {
      // The following represents some "typical" conversion mix:
      w.writeFloat64(doubleContent); doubleContent += 0.123;
      for (int k = 0; k < 8; k++) { // main use case
        w.writeFloat32(doubleContent); doubleContent += 0.123;
      }
      w.writeInt32(intContent); intContent++;
      w.writeInt32(intContent); intContent++;
      w.writeInt16(intContent); intContent++;
      w.writeInt16(intContent); intContent++;
      w.writeInt8(intContent);  intContent++;
      w.writeInt8(intContent);  intContent++;
      w.writeString("AsciiStrng");
      assert((offset % SetSize) == 0); // ensure the example content fits [SetSize] bytes
    }
    result = w.out; // only this can be used for further processing
  }
}

1] https://code.google.com/p/dart/issues / detail?id = 22107

[2] https://gist.github.com/mraleph/4eb5ccbb38904075141e

这篇关于如何提高Dart数据转换性能/从二进制?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆