|
| 1 | +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file |
| 2 | +// for details. All rights reserved. Use of this source code is governed by a |
| 3 | +// BSD-style license that can be found in the LICENSE file. |
| 4 | + |
| 5 | +import 'package:dart_model/src/json_buffer/json_buffer_builder.dart'; |
| 6 | + |
| 7 | +import 'serialization_benchmark.dart'; |
| 8 | + |
| 9 | +JsonBufferBuilder? runningBuffer; |
| 10 | + |
| 11 | +/// Benchmark accumulating data directly into a [JsonBufferBuilder] with an |
| 12 | +/// indirection through a thin wrapper type (which is a real type, not an |
| 13 | +/// extension type). |
| 14 | +class RegularClassesBufferWireBenchmark extends SerializationBenchmark { |
| 15 | + @override |
| 16 | + void run() { |
| 17 | + var data = createData(); |
| 18 | + |
| 19 | + final buffer = runningBuffer = JsonBufferBuilder(); |
| 20 | + data.forEach((k, v) => buffer.map[k] = v.toJson()); |
| 21 | + serialized = runningBuffer!.serialize(); |
| 22 | + } |
| 23 | + |
| 24 | + /// Creates the data, but its not ready yet to be serialized. |
| 25 | + Map<String, Interface> createData() { |
| 26 | + final map = <String, Interface>{}; |
| 27 | + |
| 28 | + for (final key in mapKeys) { |
| 29 | + final intKey = int.parse(key); |
| 30 | + var interface = Interface( |
| 31 | + members: { |
| 32 | + for (final memberName in makeMemberNames(intKey)) |
| 33 | + memberName: _makeMember(memberName), |
| 34 | + }, |
| 35 | + properties: Properties( |
| 36 | + isAbstract: (intKey & 1) == 1, |
| 37 | + isClass: (intKey & 2) == 2, |
| 38 | + isGetter: (intKey & 4) == 4, |
| 39 | + isField: (intKey & 8) == 8, |
| 40 | + isMethod: (intKey & 16) == 16, |
| 41 | + isStatic: (intKey & 32) == 32, |
| 42 | + ), |
| 43 | + ); |
| 44 | + map[key] = interface; |
| 45 | + } |
| 46 | + |
| 47 | + return map; |
| 48 | + } |
| 49 | + |
| 50 | + Member _makeMember(String key) { |
| 51 | + final intKey = key.length; |
| 52 | + return Member( |
| 53 | + properties: Properties( |
| 54 | + isAbstract: (intKey & 1) == 1, |
| 55 | + isClass: (intKey & 2) == 2, |
| 56 | + isGetter: (intKey & 4) == 4, |
| 57 | + isField: const [true, false, null][intKey % 3], |
| 58 | + isMethod: (intKey & 16) == 16, |
| 59 | + isStatic: (intKey & 32) == 32, |
| 60 | + ), |
| 61 | + ); |
| 62 | + } |
| 63 | + |
| 64 | + @override |
| 65 | + void deserialize() { |
| 66 | + deserialized = JsonBufferBuilder.deserialize( |
| 67 | + serialized!, |
| 68 | + ).map.map<String, Interface>( |
| 69 | + (k, v) => MapEntry(k, Interface.fromJson(v as Map<String, Object?>)), |
| 70 | + ); |
| 71 | + } |
| 72 | +} |
| 73 | + |
| 74 | +abstract interface class Serializable { |
| 75 | + Map<String, Object?> toJson(); |
| 76 | +} |
| 77 | + |
| 78 | +/// An interface. |
| 79 | +class Interface implements Serializable, Hashable { |
| 80 | + final Map<String, Member>? _members; |
| 81 | + Map<String, Member> get members => _members!; |
| 82 | + |
| 83 | + final Properties? _properties; |
| 84 | + Properties get properties => _properties!; |
| 85 | + |
| 86 | + static TypedMapSchema schema = TypedMapSchema({ |
| 87 | + 'members': Type.growableMapPointer, |
| 88 | + 'properties': Type.typedMapPointer, |
| 89 | + }); |
| 90 | + |
| 91 | + Interface({Properties? properties, Map<String, Member>? members}) |
| 92 | + : _properties = properties, |
| 93 | + _members = members; |
| 94 | + |
| 95 | + factory Interface.fromJson(Map<String, Object?> json) => Interface( |
| 96 | + properties: Properties.fromJson(json['properties'] as Map<String, Object?>), |
| 97 | + members: (json['members'] as Map<String, Object?>).map( |
| 98 | + (k, v) => MapEntry(k, Member.fromJson(v as Map<String, Object?>)), |
| 99 | + ), |
| 100 | + ); |
| 101 | + |
| 102 | + @override |
| 103 | + Map<String, Object?> toJson() { |
| 104 | + var membersMap = runningBuffer!.createGrowableMap<Map<String, Object?>>(); |
| 105 | + _members?.forEach((k, v) => membersMap[k] = v.toJson()); |
| 106 | + return runningBuffer!.createTypedMap( |
| 107 | + schema, |
| 108 | + membersMap, |
| 109 | + _properties?.toJson(), |
| 110 | + ); |
| 111 | + } |
| 112 | + |
| 113 | + @override |
| 114 | + int get deepHash { |
| 115 | + var result = 0; |
| 116 | + result ^= 'members'.hashCode; |
| 117 | + _members?.forEach((k, v) { |
| 118 | + result ^= k.hashCode; |
| 119 | + result ^= v.deepHash; |
| 120 | + }); |
| 121 | + result ^= 'properties'.hashCode ^ (_properties?.deepHash ?? null.hashCode); |
| 122 | + return result; |
| 123 | + } |
| 124 | +} |
| 125 | + |
| 126 | +/// A member. |
| 127 | +class Member implements Serializable, Hashable { |
| 128 | + final Properties? _properties; |
| 129 | + Properties get properties => _properties!; |
| 130 | + |
| 131 | + static TypedMapSchema schema = TypedMapSchema({ |
| 132 | + 'properties': Type.typedMapPointer, |
| 133 | + }); |
| 134 | + |
| 135 | + Member({Properties? properties}) : _properties = properties; |
| 136 | + |
| 137 | + factory Member.fromJson(Map<String, Object?> json) => Member( |
| 138 | + properties: Properties.fromJson(json['properties'] as Map<String, Object?>), |
| 139 | + ); |
| 140 | + |
| 141 | + @override |
| 142 | + Map<String, Object?> toJson() => |
| 143 | + runningBuffer!.createTypedMap(schema, _properties?.toJson()); |
| 144 | + |
| 145 | + @override |
| 146 | + int get deepHash { |
| 147 | + var result = 0; |
| 148 | + result ^= 'properties'.hashCode ^ (_properties?.deepHash ?? null.hashCode); |
| 149 | + return result; |
| 150 | + } |
| 151 | +} |
| 152 | + |
| 153 | +/// Set of boolean properties. |
| 154 | +class Properties implements Serializable, Hashable { |
| 155 | + /// Whether the entity is abstract, meaning it has no definition. |
| 156 | + final bool? _isAbstract; |
| 157 | + bool get isAbstract => _isAbstract!; |
| 158 | + |
| 159 | + /// Whether the entity is a class. |
| 160 | + final bool? _isClass; |
| 161 | + bool get isClass => _isClass!; |
| 162 | + |
| 163 | + /// Whether the entity is a getter. |
| 164 | + final bool? _isGetter; |
| 165 | + bool get isGetter => _isGetter!; |
| 166 | + |
| 167 | + /// Whether the entity is a field. |
| 168 | + final bool? _isField; |
| 169 | + bool get isField => _isField!; |
| 170 | + |
| 171 | + /// Whether the entity is a method. |
| 172 | + final bool? _isMethod; |
| 173 | + bool get isMethod => _isMethod!; |
| 174 | + |
| 175 | + /// Whether the entity is static. |
| 176 | + final bool? _isStatic; |
| 177 | + bool get isStatic => _isStatic!; |
| 178 | + |
| 179 | + static TypedMapSchema schema = TypedMapSchema({ |
| 180 | + 'isAbstract': Type.boolean, |
| 181 | + 'isClass': Type.boolean, |
| 182 | + 'isGetter': Type.boolean, |
| 183 | + 'isField': Type.boolean, |
| 184 | + 'isMethod': Type.boolean, |
| 185 | + 'isStatic': Type.boolean, |
| 186 | + }); |
| 187 | + |
| 188 | + Properties({ |
| 189 | + bool? isAbstract, |
| 190 | + bool? isClass, |
| 191 | + bool? isGetter, |
| 192 | + bool? isField, |
| 193 | + bool? isMethod, |
| 194 | + bool? isStatic, |
| 195 | + }) : _isAbstract = isAbstract, |
| 196 | + _isClass = isClass, |
| 197 | + _isGetter = isGetter, |
| 198 | + _isField = isField, |
| 199 | + _isMethod = isMethod, |
| 200 | + _isStatic = isStatic; |
| 201 | + |
| 202 | + factory Properties.fromJson(Map<String, Object?> json) => Properties( |
| 203 | + isAbstract: json['isAbstract'] as bool?, |
| 204 | + isClass: json['isClass'] as bool?, |
| 205 | + isGetter: json['isGetter'] as bool?, |
| 206 | + isField: json['isField'] as bool?, |
| 207 | + isMethod: json['isMethod'] as bool?, |
| 208 | + isStatic: json['isStatic'] as bool?, |
| 209 | + ); |
| 210 | + |
| 211 | + @override |
| 212 | + Map<String, Object?> toJson() => runningBuffer!.createTypedMap( |
| 213 | + schema, |
| 214 | + _isAbstract, |
| 215 | + _isClass, |
| 216 | + _isGetter, |
| 217 | + _isField, |
| 218 | + _isMethod, |
| 219 | + _isStatic, |
| 220 | + ); |
| 221 | + |
| 222 | + @override |
| 223 | + int get deepHash { |
| 224 | + var result = 0; |
| 225 | + result ^= 'isAbstract'.hashCode ^ _isAbstract.hashCode; |
| 226 | + result ^= 'isClass'.hashCode ^ _isClass.hashCode; |
| 227 | + result ^= 'isGetter'.hashCode ^ _isGetter.hashCode; |
| 228 | + result ^= 'isField'.hashCode ^ _isField.hashCode; |
| 229 | + result ^= 'isMethod'.hashCode ^ _isMethod.hashCode; |
| 230 | + result ^= 'isStatic'.hashCode ^ _isStatic.hashCode; |
| 231 | + return result; |
| 232 | + } |
| 233 | +} |
0 commit comments