Skip to content

Commit

Permalink
Add benchmark for hashing. Improve hashing performance.
Browse files Browse the repository at this point in the history
  • Loading branch information
davidmorgan committed Nov 7, 2016
1 parent b9d9bbe commit 99e99e2
Show file tree
Hide file tree
Showing 17 changed files with 169 additions and 60 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
- Generate empty constructor with semicolon instead of {}.
- Use ArgumentError.notNull for null errors.
- Reject dynamic fields.
- Add simple benchmark for hashing. Improve hashing performance.

## 0.1.5

Expand Down
18 changes: 16 additions & 2 deletions built_value/lib/built_value.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@

library built_value;

export 'package:quiver/core.dart' show hashObjects;

/// Implement this for a Built Value.
///
/// Then use built_value_generator.dart code generation functionality to
Expand Down Expand Up @@ -59,3 +57,19 @@ abstract class Builder<V extends Built<V, B>, B extends Builder<V, B>> {
//
// Fields marked with this annotation are allowed to be null.
const String nullable = 'nullable';

/// For use by generated code in calculating hash codes. Do not use directly.
int $jc(int hash, int value) {
// Jenkins hash "combine".
hash = 0x1fffffff & (hash + value);
hash = 0x1fffffff & (hash + ((0x0007ffff & hash) << 10));
return hash ^ (hash >> 6);
}

/// For use by generated code in calculating hash codes. Do not use directly.
int $jf(int hash) {
// Jenkins hash "finish".
hash = 0x1fffffff & (hash + ((0x03ffffff & hash) << 3));
hash = hash ^ (hash >> 11);
return 0x1fffffff & (hash + ((0x00003fff & hash) << 15));
}
3 changes: 0 additions & 3 deletions built_value/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,3 @@ homepage: https://github.com/google/built_value.dart

environment:
sdk: '>=1.8.0 <2.0.0'

dependencies:
quiver: '>=0.21.0 <0.24.0'
8 changes: 5 additions & 3 deletions built_value_generator/lib/src/source_class.dart
Original file line number Diff line number Diff line change
Expand Up @@ -259,9 +259,11 @@ abstract class SourceClass implements Built<SourceClass, SourceClassBuilder> {
if (fields.length == 0) {
result.writeln('return ${name.hashCode};');
} else {
result.writeln('return hashObjects([');
result.write(fields.map((field) => field.name).join(', '));
result.writeln(']);');
result.writeln(r'return $jf(');
result.writeln(r'$jc(' * fields.length);
result.writeln('0, ');
result.write(fields.map((field) => '${field.name}.hashCode').join('), '));
result.writeln('));');
}
result.writeln('}');
result.writeln();
Expand Down
39 changes: 24 additions & 15 deletions built_value_generator/lib/src/source_class.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

22 changes: 12 additions & 10 deletions built_value_generator/lib/src/source_field.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

38 changes: 21 additions & 17 deletions example/lib/collections.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions example/lib/compound_value.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions example/lib/simple_value.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions example/lib/validated_value.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions example/lib/value_with_code.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions example/lib/value_with_defaults.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions example/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,5 @@ dev_dependencies:
# built_value_generator: '^0.1.6'
built_value_generator:
path: ../built_value_generator
quiver: '>=0.21.0 <0.24.0'
test: any
36 changes: 36 additions & 0 deletions example/test/benchmark_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// Copyright (c) 2016, Google Inc. 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.

import 'package:example/simple_value.dart';
import 'package:test/test.dart';

void main() {
group('benchmark SimpleValue', () {
test('hashCode', () {
final value = new SimpleValue((b) => b
..anInt = 0
..aString = 'zero');
benchmark('hashCode', () => value.hashCode);
});
});
}

void benchmark(String name, function()) {
// Warm up.
for (var i = 0; i != 1000; ++i) {
function();
}

// Time.
for (int i = 0; i != 3; ++i) {
final stopwatch = new Stopwatch()..start();
final reps = 10000000;
for (var i = 0; i != reps; ++i) {
function();
}
final perSecond =
(reps / (stopwatch.elapsedMicroseconds / 1000000.0)).round();
print('$name: $perSecond/s');
}
}
25 changes: 25 additions & 0 deletions example/test/collections_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import 'package:built_collection/built_collection.dart';
import 'package:example/collections.dart';
import 'package:quiver/core.dart';
import 'package:test/test.dart';

void main() {
Expand Down Expand Up @@ -70,5 +71,29 @@ void main() {
'six': [false]
});
});

test('hash matches quiver hash', () {
final collections = new Collections((b) => b
..list.add(1)
..set.add('two')
..map['three'] = 4
..listMultimap.add(5, true)
..setMultimap.add('six', false));

expect(
collections.hashCode,
hashObjects([
collections.list,
collections.set,
collections.map,
collections.listMultimap,
collections.setMultimap,
collections.nullableList,
collections.nullableSet,
collections.nullableMap,
collections.nullableListMultimap,
collections.nullableSetMultimap,
]));
});
});
}
10 changes: 10 additions & 0 deletions example/test/compound_value_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import 'package:example/compound_value.dart';
import 'package:example/validated_value.dart';
import 'package:quiver/core.dart';
import 'package:test/test.dart';

void main() {
Expand All @@ -28,5 +29,14 @@ void main() {
..validatedValue.anInt = 2).validatedValue.anInt,
2);
});

test('hash matches quiver hash', () {
final value = new CompoundValue((b) => b
..simpleValue.anInt = 1
..simpleValue.aString = 'two');

expect(value.hashCode,
hashObjects([value.simpleValue, value.validatedValue]));
});
});
}
Loading

0 comments on commit 99e99e2

Please sign in to comment.