// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

// Macro-benchmark for ffi with boringssl.

import 'dart:convert';
import 'dart:ffi';
import 'dart:typed_data';

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

import 'calloc.dart';
import 'digest.dart';
import 'types.dart';

//
// BoringSSL functions
//

Uint8List inventData(int length) {
  final result = Uint8List(length);
  for (int i = 0; i < length; i++) {
    result[i] = i % 256;
  }
  return result;
}

Uint8List toUint8List(Pointer<Bytes> bytes, int length) {
  final result = Uint8List(length);
  final uint8bytes = bytes.asUint8Pointer();
  for (int i = 0; i < length; i++) {
    result[i] = uint8bytes[i];
  }
  return result;
}

void copyFromUint8ListToTarget(Uint8List source, Pointer<Data> target) {
  final int length = source.length;
  final uint8target = target.asUint8Pointer();
  for (int i = 0; i < length; i++) {
    uint8target[i] = source[i];
  }
}

String hash(Pointer<Data> data, int length, Pointer<EVP_MD> hashAlgorithm) {
  final context = EVP_MD_CTX_new();
  EVP_DigestInit(context, hashAlgorithm);
  EVP_DigestUpdate(context, data, length);
  final int resultSize = EVP_MD_CTX_size(context);
  final Pointer<Bytes> result = calloc<Uint8>(resultSize).cast();
  EVP_DigestFinal(context, result, nullptr);
  EVP_MD_CTX_free(context);
  final String hash = base64Encode(toUint8List(result, resultSize));
  calloc.free(result);
  return hash;
}

//
// Benchmark fixtures.
//

// Number of repeats: 1 && Length in bytes: 10000000
//  * CPU: Intel(R) Xeon(R) Gold 6154
//    * Architecture: x64
//      * 23000 - 52000000 us (without optimizations)
//      * 23000 - 30000 us (with optimizations)
const int L = 1000; // Length of data in bytes.

final hashAlgorithm = EVP_sha512();

// Hash of generated data of `L` bytes with `hashAlgorithm`.
const String expectedHash =
    'bNLtqb+cBZcSkCmwBUuB5DP2uLe0madetwXv10usGUFJg1sdGhTEi+aW5NWIRW1RKiLq56obV74rVurn014Iyw==';

/// This benchmark runs a digest algorithm on data residing in C memory.
///
/// This benchmark is intended as macro benchmark with a realistic workload.
class DigestCMemory extends BenchmarkBase {
  DigestCMemory() : super('FfiBoringssl.DigestCMemory');

  Pointer<Data> data = nullptr; // Data in C memory that we want to digest.

  @override
  void setup() {
    data = calloc<Uint8>(L).cast();
    copyFromUint8ListToTarget(inventData(L), data);
    hash(data, L, hashAlgorithm);
  }

  @override
  void teardown() {
    calloc.free(data);
  }

  @override
  void run() {
    final String result = hash(data, L, hashAlgorithm);
    if (result != expectedHash) {
      throw Exception('$name: Unexpected result: $result');
    }
  }
}

/// This benchmark runs a digest algorithm on data residing in Dart memory.
///
/// This benchmark is intended as macro benchmark with a realistic workload.
class DigestDartMemory extends BenchmarkBase {
  DigestDartMemory() : super('FfiBoringssl.DigestDartMemory');

  Uint8List data = Uint8List(0); // Data in C memory that we want to digest.

  @override
  void setup() {
    data = inventData(L);
    final Pointer<Data> dataInC = calloc<Uint8>(L).cast();
    copyFromUint8ListToTarget(data, dataInC);
    hash(dataInC, L, hashAlgorithm);
    calloc.free(dataInC);
  }

  @override
  void teardown() {}

  @override
  void run() {
    final Pointer<Data> dataInC = calloc<Uint8>(L).cast();
    copyFromUint8ListToTarget(data, dataInC);
    final String result = hash(dataInC, L, hashAlgorithm);
    calloc.free(dataInC);
    if (result != expectedHash) {
      throw Exception('$name: Unexpected result: $result');
    }
  }
}

//
// Main driver.
//

void main() {
  final benchmarks = [
    () => DigestCMemory(),
    () => DigestDartMemory(),
  ];
  for (final benchmark in benchmarks) {
    benchmark().report();
  }
}
