| OLD | NEW |
| 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 library analysis_server.src.status.memory_use; | 5 library analysis_server.src.status.memory_use; |
| 6 | 6 |
| 7 import 'dart:collection'; | 7 import 'dart:collection'; |
| 8 | 8 |
| 9 import 'package:analysis_server/src/analysis_server.dart'; | 9 import 'package:analysis_server/src/analysis_server.dart'; |
| 10 import 'package:analyzer/dart/ast/ast.dart'; | 10 import 'package:analyzer/dart/ast/ast.dart'; |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 158 * The maximum size of an instance set. | 158 * The maximum size of an instance set. |
| 159 */ | 159 */ |
| 160 static const int maxInstanceSetSize = 1000000; | 160 static const int maxInstanceSetSize = 1000000; |
| 161 | 161 |
| 162 /** | 162 /** |
| 163 * A table mapping classes to instances of the class. | 163 * A table mapping classes to instances of the class. |
| 164 */ | 164 */ |
| 165 Map<Type, Set> instances = new HashMap<Type, Set>(); | 165 Map<Type, Set> instances = new HashMap<Type, Set>(); |
| 166 | 166 |
| 167 /** | 167 /** |
| 168 * A table mapping classes to the classes of objects from which they were |
| 169 * reached. |
| 170 */ |
| 171 Map<Type, Set<Type>> ownerMap = new HashMap<Type, Set<Type>>(); |
| 172 |
| 173 /** |
| 168 * A set of all the library specific units, using equality rather than | 174 * A set of all the library specific units, using equality rather than |
| 169 * identity in order to determine whether re-using equal instances would save | 175 * identity in order to determine whether re-using equal instances would save |
| 170 * significant space. | 176 * significant space. |
| 171 */ | 177 */ |
| 172 Set<LibrarySpecificUnit> uniqueLSUs = new HashSet<LibrarySpecificUnit>(); | 178 Set<LibrarySpecificUnit> uniqueLSUs = new HashSet<LibrarySpecificUnit>(); |
| 173 | 179 |
| 174 /** | 180 /** |
| 175 * A set of all the targeted results, using equality rather than identity in | 181 * A set of all the targeted results, using equality rather than identity in |
| 176 * order to determine whether re-using equal instances would save significant | 182 * order to determine whether re-using equal instances would save significant |
| 177 * space. | 183 * space. |
| 178 */ | 184 */ |
| 179 Set<TargetedResult> uniqueTargetedResults = new HashSet<TargetedResult>(); | 185 Set<TargetedResult> uniqueTargetedResults = new HashSet<TargetedResult>(); |
| 180 | 186 |
| 181 /** | 187 /** |
| 188 * A set containing all of the analysis targets for which the key in the |
| 189 * cache partition is not the same instance as the target stored in the entry. |
| 190 */ |
| 191 Set<AnalysisTarget> mismatchedTargets = new HashSet<AnalysisTarget>(); |
| 192 |
| 193 /** |
| 182 * A table mapping the types of AST nodes to the number of instances being | 194 * A table mapping the types of AST nodes to the number of instances being |
| 183 * held directly (as values in the cache). | 195 * held directly (as values in the cache). |
| 184 */ | 196 */ |
| 185 Map<Type, int> directNodeCounts = new HashMap<Type, int>(); | 197 Map<Type, int> directNodeCounts = new HashMap<Type, int>(); |
| 186 | 198 |
| 187 /** | 199 /** |
| 188 * A table mapping the types of AST nodes to the number of instances being | 200 * A table mapping the types of AST nodes to the number of instances being |
| 189 * held indirectly (such as nodes reachable from element models). | 201 * held indirectly (such as nodes reachable from element models). |
| 190 */ | 202 */ |
| 191 Map<Type, int> indirectNodeCounts = new HashMap<Type, int>(); | 203 Map<Type, int> indirectNodeCounts = new HashMap<Type, int>(); |
| 192 | 204 |
| 193 /** | 205 /** |
| 194 * A table mapping the types of the elements to the number of instances being | 206 * A table mapping the types of the elements to the number of instances being |
| 195 * held directly (as values in the cache). | 207 * held directly (as values in the cache). |
| 196 */ | 208 */ |
| 197 final Map<Type, int> elementCounts = new HashMap<Type, int>(); | 209 final Map<Type, int> elementCounts = new HashMap<Type, int>(); |
| 198 | 210 |
| 199 /** | 211 /** |
| 200 * Initialize a newly created instance. | 212 * Initialize a newly created instance. |
| 201 */ | 213 */ |
| 202 MemoryUseData(); | 214 MemoryUseData(); |
| 203 | 215 |
| 204 /** | 216 /** |
| 205 * Traverse an analysis [server] to compute memory usage data. | 217 * Traverse an analysis [server] to compute memory usage data. |
| 206 */ | 218 */ |
| 207 void processAnalysisServer(AnalysisServer server) { | 219 void processAnalysisServer(AnalysisServer server) { |
| 208 _recordInstance(server); | 220 _recordInstance(server, null); |
| 209 Iterable<AnalysisContext> contexts = server.analysisContexts; | 221 Iterable<AnalysisContext> contexts = server.analysisContexts; |
| 210 for (AnalysisContextImpl context in contexts) { | 222 for (AnalysisContextImpl context in contexts) { |
| 211 _processAnalysisContext(context); | 223 _processAnalysisContext(context, server); |
| 212 } | 224 } |
| 213 DartSdkManager manager = server.sdkManager; | 225 DartSdkManager manager = server.sdkManager; |
| 214 List<SdkDescription> descriptors = manager.sdkDescriptors; | 226 List<SdkDescription> descriptors = manager.sdkDescriptors; |
| 215 for (SdkDescription descriptor in descriptors) { | 227 for (SdkDescription descriptor in descriptors) { |
| 216 _processAnalysisContext(manager.getSdk(descriptor, () => null).context); | 228 _processAnalysisContext( |
| 229 manager.getSdk(descriptor, () => null).context, manager); |
| 217 } | 230 } |
| 218 } | 231 } |
| 219 | 232 |
| 220 void _processAnalysisContext(AnalysisContextImpl context) { | 233 void _processAnalysisContext(AnalysisContextImpl context, Object owner) { |
| 221 _recordInstance(context); | 234 _recordInstance(context, owner); |
| 222 _recordInstance(context.analysisCache); | 235 _recordInstance(context.analysisCache, context); |
| 223 Map<AnalysisTarget, CacheEntry> map = | 236 CachePartition partition = context.privateAnalysisCachePartition; |
| 224 context.privateAnalysisCachePartition.entryMap; | 237 Map<AnalysisTarget, CacheEntry> map = partition.entryMap; |
| 225 map.forEach((AnalysisTarget target, CacheEntry entry) { | 238 map.forEach((AnalysisTarget target, CacheEntry entry) { |
| 226 _processAnalysisTarget(target); | 239 _processAnalysisTarget(target, partition); |
| 227 _processCacheEntry(entry); | 240 _processCacheEntry(entry, partition); |
| 241 if (!identical(entry.target, target)) { |
| 242 mismatchedTargets.add(target); |
| 243 } |
| 228 }); | 244 }); |
| 229 } | 245 } |
| 230 | 246 |
| 231 void _processAnalysisTarget(AnalysisTarget target) { | 247 void _processAnalysisTarget(AnalysisTarget target, Object owner) { |
| 232 _recordInstance(target); | 248 _recordInstance(target, owner); |
| 233 } | 249 } |
| 234 | 250 |
| 235 void _processCacheEntry(CacheEntry entry) { | 251 void _processCacheEntry(CacheEntry entry, Object owner) { |
| 236 _recordInstance(entry); | 252 _recordInstance(entry, owner); |
| 237 List<ResultDescriptor> descriptors = entry.nonInvalidResults; | 253 List<ResultDescriptor> descriptors = entry.nonInvalidResults; |
| 238 for (ResultDescriptor descriptor in descriptors) { | 254 for (ResultDescriptor descriptor in descriptors) { |
| 239 _recordInstance(descriptor); | 255 _recordInstance(descriptor, entry); |
| 240 _processResultData(entry.getResultDataOrNull(descriptor)); | 256 _processResultData(entry.getResultDataOrNull(descriptor), entry); |
| 241 } | 257 } |
| 242 } | 258 } |
| 243 | 259 |
| 244 void _processResultData(ResultData resultData) { | 260 void _processResultData(ResultData resultData, Object owner) { |
| 245 _recordInstance(resultData); | 261 _recordInstance(resultData, owner); |
| 246 if (resultData != null) { | 262 if (resultData != null) { |
| 247 _recordInstance(resultData.state); | 263 _recordInstance(resultData.state, resultData); |
| 248 _recordInstance(resultData.value, onFirstOccurrence: (Object object) { | 264 _recordInstance(resultData.value, resultData, |
| 265 onFirstOccurrence: (Object object) { |
| 249 if (object is AstNode) { | 266 if (object is AstNode) { |
| 250 object.accept(new AstNodeCounter(directNodeCounts)); | 267 object.accept(new AstNodeCounter(directNodeCounts)); |
| 251 } else if (object is Element) { | 268 } else if (object is Element) { |
| 252 object.accept(new ElementCounter(elementCounts, indirectNodeCounts)); | 269 object.accept(new ElementCounter(elementCounts, indirectNodeCounts)); |
| 253 } | 270 } |
| 254 }); | 271 }); |
| 255 resultData.dependedOnResults.forEach(_processTargetedResult); | 272 resultData.dependedOnResults.forEach((TargetedResult result) => |
| 256 resultData.dependentResults.forEach(_processTargetedResult); | 273 _processTargetedResult(result, resultData)); |
| 274 resultData.dependentResults.forEach((TargetedResult result) => |
| 275 _processTargetedResult(result, resultData)); |
| 257 } | 276 } |
| 258 } | 277 } |
| 259 | 278 |
| 260 void _processTargetedResult(TargetedResult result) { | 279 void _processTargetedResult(TargetedResult result, Object owner) { |
| 261 _recordInstance(result); | 280 _recordInstance(result, owner); |
| 262 uniqueTargetedResults.add(result); | 281 uniqueTargetedResults.add(result); |
| 263 _recordInstance(result.target); | 282 _recordInstance(result.target, result); |
| 264 _recordInstance(result.result); | 283 _recordInstance(result.result, result); |
| 265 } | 284 } |
| 266 | 285 |
| 267 /** | 286 /** |
| 268 * Record the given [instance] that was found. If this is the first time that | 287 * Record the given [instance] that was found. If this is the first time that |
| 269 * the instance has been found, execute the [onFirstOccurrence] function. | 288 * the instance has been found, execute the [onFirstOccurrence] function. |
| 270 * | 289 * |
| 271 * Note that instances will not be recorded if there are more than | 290 * Note that instances will not be recorded if there are more than |
| 272 * [maxInstanceSetSize] instances of the same type, and that the | 291 * [maxInstanceSetSize] instances of the same type, and that the |
| 273 * [onFirstOccurrence] function will not be executed if the instance is not | 292 * [onFirstOccurrence] function will not be executed if the instance is not |
| 274 * recorded. | 293 * recorded. |
| 275 */ | 294 */ |
| 276 void _recordInstance(Object instance, | 295 void _recordInstance(Object instance, Object owner, |
| 277 {void onFirstOccurrence(Object object)}) { | 296 {void onFirstOccurrence(Object object)}) { |
| 278 Type type = instance.runtimeType; | 297 Type type = instance.runtimeType; |
| 279 Set instanceSet = instances.putIfAbsent(type, () => new HashSet.identity()); | 298 Set instanceSet = instances.putIfAbsent(type, () => new HashSet.identity()); |
| 280 if (instanceSet != InfiniteSet.instance) { | 299 if (instanceSet != InfiniteSet.instance) { |
| 281 if (instanceSet.add(instance) && onFirstOccurrence != null) { | 300 if (instanceSet.add(instance) && onFirstOccurrence != null) { |
| 282 onFirstOccurrence(instance); | 301 onFirstOccurrence(instance); |
| 283 } | 302 } |
| 284 if (instanceSet.length >= maxInstanceSetSize) { | 303 if (instanceSet.length >= maxInstanceSetSize) { |
| 285 instances[type] = InfiniteSet.instance; | 304 instances[type] = InfiniteSet.instance; |
| 286 } | 305 } |
| 287 } | 306 } |
| 307 ownerMap |
| 308 .putIfAbsent(instance.runtimeType, () => new HashSet<Type>()) |
| 309 .add(owner.runtimeType); |
| 288 if (instance is LibrarySpecificUnit) { | 310 if (instance is LibrarySpecificUnit) { |
| 289 uniqueLSUs.add(instance); | 311 uniqueLSUs.add(instance); |
| 290 } | 312 } |
| 291 } | 313 } |
| 292 } | 314 } |
| OLD | NEW |