comparison rust/hg-core/src/ancestors.rs @ 41715:fccb61a1777b

rust: less set lookups in MissingAncestors using the return values of HashSet::remove(), we can factor pairs of `contains()/remove()` into a single `remove()`. On a perfdiscovery run done on the PyPy repository, prepared with contrib/discovery-helper.sh 50 100, I do get a modest improvement with this (mean of medians of three runs is better by 2%) Sample readings, before this change: ! wall 0.175609 comb 0.180000 user 0.180000 sys 0.000000 (median of 58) With this change: ! wall 0.171662 comb 0.180000 user 0.170000 sys 0.010000 (median of 60) Differential Revision: https://phab.mercurial-scm.org/D5943
author Georges Racinet <georges.racinet@octobus.net>
date Mon, 04 Feb 2019 12:04:59 +0100
parents 70827ebba453
children 977432970080
comparison
equal deleted inserted replaced
41714:70827ebba453 41715:fccb61a1777b
332 let mut missing: Vec<Revision> = Vec::new(); 332 let mut missing: Vec<Revision> = Vec::new();
333 for curr in (0..=start).rev() { 333 for curr in (0..=start).rev() {
334 if revs_visit.is_empty() { 334 if revs_visit.is_empty() {
335 break; 335 break;
336 } 336 }
337 if both_visit.contains(&curr) { 337 if both_visit.remove(&curr) {
338 // curr's parents might have made it into revs_visit through 338 // curr's parents might have made it into revs_visit through
339 // another path 339 // another path
340 // TODO optim: Rust's HashSet.remove returns a boolean telling
341 // if it happened. This will spare us one set lookup
342 both_visit.remove(&curr);
343 for p in self.graph.parents(curr)?.iter().cloned() { 340 for p in self.graph.parents(curr)?.iter().cloned() {
344 if p == NULL_REVISION { 341 if p == NULL_REVISION {
345 continue; 342 continue;
346 } 343 }
347 revs_visit.remove(&p); 344 revs_visit.remove(&p);
352 missing.push(curr); 349 missing.push(curr);
353 for p in self.graph.parents(curr)?.iter().cloned() { 350 for p in self.graph.parents(curr)?.iter().cloned() {
354 if p == NULL_REVISION { 351 if p == NULL_REVISION {
355 continue; 352 continue;
356 } 353 }
357 if bases_visit.contains(&p) || both_visit.contains(&p) { 354 if bases_visit.contains(&p) {
358 // p is an ancestor of revs_visit, and is implicitly 355 // p is already known to be an ancestor of revs_visit
359 // in bases_visit, which means p is ::revs & ::bases. 356 revs_visit.remove(&p);
360 // TODO optim: hence if bothvisit, we look up twice 357 both_visit.insert(p);
358 } else if both_visit.contains(&p) {
359 // p should have been in bases_visit
361 revs_visit.remove(&p); 360 revs_visit.remove(&p);
362 bases_visit.insert(p); 361 bases_visit.insert(p);
363 both_visit.insert(p);
364 } else { 362 } else {
365 // visit later 363 // visit later
366 revs_visit.insert(p); 364 revs_visit.insert(p);
367 } 365 }
368 } 366 }
369 } else if bases_visit.contains(&curr) { 367 } else if bases_visit.contains(&curr) {
370 for p in self.graph.parents(curr)?.iter().cloned() { 368 for p in self.graph.parents(curr)?.iter().cloned() {
371 if p == NULL_REVISION { 369 if p == NULL_REVISION {
372 continue; 370 continue;
373 } 371 }
374 if revs_visit.contains(&p) || both_visit.contains(&p) { 372 if revs_visit.remove(&p) || both_visit.contains(&p) {
375 // p is an ancestor of bases_visit, and is implicitly 373 // p is an ancestor of bases_visit, and is implicitly
376 // in revs_visit, which means p is ::revs & ::bases. 374 // in revs_visit, which means p is ::revs & ::bases.
377 // TODO optim: hence if bothvisit, we look up twice
378 revs_visit.remove(&p);
379 bases_visit.insert(p); 375 bases_visit.insert(p);
380 both_visit.insert(p); 376 both_visit.insert(p);
381 } else { 377 } else {
382 bases_visit.insert(p); 378 bases_visit.insert(p);
383 } 379 }