Commit 66a6cec
committed
Add non-Arc-clone'ing variant of access()
`access()` implies (typically) an `Arc::clone` of the guarded resource.
When that resource is access()'d frequently, especially across many
cores, the contention for incrementing and decrementing the shared
refcount can become the primary bottleneck for Propolis.
This is particularly visible in `nvme`, where queues live in guest memory,
are mediated by `MemCtx`, queues are managed across dozens of threads
(hundreds in some cases!) threads, and millions of items are read and
written to queues per second. On large processors an increment can take
hundreds of nanoseconds, or thousands of cycles!
----
This patch is a less comprehensive improvement to the problem than I'd
hoped for, but it *is* a substantial improvement enough to include for
now.
The first try at this change set out to add an alternative to
accessors::Guard, call it accessor::View, which would have a
refresh() analogous to Guard::access(). View was expected to hold
a reference on a Node, and View::refresh() was
expected to go through the same "check res_leaf or else re-derive the
leaf resource" steps as guard().
After getting through the lock_tree() changes to keep a guard for a
node when refreshing the leaf, it became clear in most cases we'd have
an accessor::View we would *not* have that view via mutable reference.
accessor::View's cached reference would need to be behind a Mutex for
interior mutability, at which point a "View" is not much different from
any other "Node" in the accessor tree.
So, instead, this implements a less aspirational change of adding an
"access() but return the guard instead of clone the reference". This is
strictly less work than before, but still implies going out to
`mutex_lock` and such for something that, in the happy case, should be
nothing more than a load. Even so, the mutexes in question are per-Node
and generally not contended - this is hard to spot even under load.
----
In the limit, an accessor tree that supports disabling access to
subtrees already is up against the issue that `access()`'d `Guard` don't
synchronize with operations on the resource. A PCI bus can "deny"
access to memory, but a device or its queues may still have a Guard
permitting to access memory after the fact and do so.
It seems theoretically possible to lean into accessed resources being an
`Arc<T>` and have nodes hold an `AtomicUsize` of that pointer, updating
it as appropriate while managing the tree. Then, nodes and the tree
generally could have generation counters where on access the caller must
only compare generations to check that the cached access is still valid.
To deny access to a (sub)tree, relevant `Node` could be modified, the
tree's generation bumped, and the access-denier can wait on the
reference count to the old tree to drop to zero.
Critically, comparing the generation numbers requires only loads, so
cores don't fight over writes, and in the typical case the generation
number won't change, so a view's reference can remain counted until the
generation number change is finally witnessed.
I *think* that the main difficulty with this approach is that it
requires components that hold a long-lived reference on the resource to
regularly "check in" that the reference is still valid, but it would be
very easy to accidentally sleep while holding a reference. This is the
same general problem as blocking a writer becuase you've slept holding a
read lock.1 parent 2dc6437 commit 66a6cec
3 files changed
+112
-38
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
362 | 362 | | |
363 | 363 | | |
364 | 364 | | |
365 | | - | |
366 | 365 | | |
367 | | - | |
368 | | - | |
369 | 366 | | |
| 367 | + | |
370 | 368 | | |
| 369 | + | |
| 370 | + | |
371 | 371 | | |
372 | 372 | | |
373 | 373 | | |
| |||
423 | 423 | | |
424 | 424 | | |
425 | 425 | | |
426 | | - | |
427 | | - | |
428 | | - | |
429 | | - | |
| 426 | + | |
| 427 | + | |
| 428 | + | |
| 429 | + | |
| 430 | + | |
| 431 | + | |
| 432 | + | |
430 | 433 | | |
431 | 434 | | |
432 | 435 | | |
433 | | - | |
| 436 | + | |
434 | 437 | | |
435 | 438 | | |
436 | 439 | | |
437 | 440 | | |
438 | 441 | | |
439 | 442 | | |
440 | 443 | | |
441 | | - | |
| 444 | + | |
| 445 | + | |
| 446 | + | |
| 447 | + | |
| 448 | + | |
| 449 | + | |
| 450 | + | |
442 | 451 | | |
443 | | - | |
| 452 | + | |
444 | 453 | | |
445 | | - | |
| 454 | + | |
446 | 455 | | |
447 | 456 | | |
448 | 457 | | |
449 | 458 | | |
450 | | - | |
| 459 | + | |
451 | 460 | | |
452 | 461 | | |
453 | 462 | | |
454 | 463 | | |
455 | 464 | | |
456 | 465 | | |
457 | | - | |
| 466 | + | |
458 | 467 | | |
459 | 468 | | |
| 469 | + | |
| 470 | + | |
| 471 | + | |
| 472 | + | |
| 473 | + | |
460 | 474 | | |
| 475 | + | |
| 476 | + | |
| 477 | + | |
| 478 | + | |
| 479 | + | |
| 480 | + | |
| 481 | + | |
| 482 | + | |
| 483 | + | |
| 484 | + | |
| 485 | + | |
| 486 | + | |
| 487 | + | |
| 488 | + | |
| 489 | + | |
461 | 490 | | |
462 | | - | |
463 | | - | |
| 491 | + | |
| 492 | + | |
464 | 493 | | |
465 | 494 | | |
466 | 495 | | |
467 | | - | |
| 496 | + | |
468 | 497 | | |
469 | | - | |
470 | 498 | | |
471 | 499 | | |
472 | 500 | | |
473 | | - | |
| 501 | + | |
474 | 502 | | |
475 | 503 | | |
476 | 504 | | |
| |||
480 | 508 | | |
481 | 509 | | |
482 | 510 | | |
483 | | - | |
| 511 | + | |
484 | 512 | | |
485 | | - | |
| 513 | + | |
486 | 514 | | |
487 | 515 | | |
488 | 516 | | |
| |||
508 | 536 | | |
509 | 537 | | |
510 | 538 | | |
| 539 | + | |
| 540 | + | |
| 541 | + | |
| 542 | + | |
| 543 | + | |
| 544 | + | |
| 545 | + | |
| 546 | + | |
| 547 | + | |
| 548 | + | |
| 549 | + | |
| 550 | + | |
| 551 | + | |
| 552 | + | |
| 553 | + | |
511 | 554 | | |
512 | 555 | | |
513 | 556 | | |
| |||
538 | 581 | | |
539 | 582 | | |
540 | 583 | | |
541 | | - | |
542 | | - | |
| 584 | + | |
| 585 | + | |
| 586 | + | |
| 587 | + | |
543 | 588 | | |
544 | 589 | | |
545 | 590 | | |
| |||
564 | 609 | | |
565 | 610 | | |
566 | 611 | | |
567 | | - | |
| 612 | + | |
| 613 | + | |
568 | 614 | | |
569 | 615 | | |
570 | 616 | | |
| |||
578 | 624 | | |
579 | 625 | | |
580 | 626 | | |
| 627 | + | |
| 628 | + | |
| 629 | + | |
| 630 | + | |
| 631 | + | |
581 | 632 | | |
582 | 633 | | |
583 | 634 | | |
584 | 635 | | |
| 636 | + | |
| 637 | + | |
| 638 | + | |
| 639 | + | |
| 640 | + | |
| 641 | + | |
| 642 | + | |
| 643 | + | |
| 644 | + | |
| 645 | + | |
| 646 | + | |
| 647 | + | |
| 648 | + | |
| 649 | + | |
| 650 | + | |
| 651 | + | |
| 652 | + | |
| 653 | + | |
| 654 | + | |
585 | 655 | | |
586 | 656 | | |
587 | | - | |
| 657 | + | |
588 | 658 | | |
589 | 659 | | |
590 | 660 | | |
591 | 661 | | |
592 | | - | |
| 662 | + | |
593 | 663 | | |
594 | 664 | | |
595 | 665 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
631 | 631 | | |
632 | 632 | | |
633 | 633 | | |
634 | | - | |
| 634 | + | |
| 635 | + | |
635 | 636 | | |
636 | 637 | | |
637 | 638 | | |
| |||
868 | 869 | | |
869 | 870 | | |
870 | 871 | | |
871 | | - | |
872 | | - | |
873 | | - | |
874 | | - | |
875 | | - | |
876 | | - | |
877 | | - | |
878 | | - | |
879 | | - | |
880 | | - | |
| 872 | + | |
| 873 | + | |
881 | 874 | | |
882 | | - | |
| 875 | + | |
| 876 | + | |
| 877 | + | |
| 878 | + | |
| 879 | + | |
| 880 | + | |
| 881 | + | |
| 882 | + | |
| 883 | + | |
| 884 | + | |
| 885 | + | |
883 | 886 | | |
884 | 887 | | |
885 | 888 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
73 | 73 | | |
74 | 74 | | |
75 | 75 | | |
76 | | - | |
| 76 | + | |
| 77 | + | |
77 | 78 | | |
78 | 79 | | |
79 | 80 | | |
| |||
0 commit comments