Skip to content

Conversation

evgeny-leksikov
Copy link
Contributor

@evgeny-leksikov evgeny-leksikov commented Sep 26, 2025

What?

RegDescList and XferDescList missed APIs:

  • equality operators
  • set/get
  • get index

@github-actions
Copy link

👋 Hi evgeny-leksikov! Thank you for contributing to ai-dynamo/nixl.

Your PR reviewers will review your contribution then trigger the CI to test your changes.

🚀

@evgeny-leksikov evgeny-leksikov changed the title RUST: RegDescList and XferDescList missed APIs RUST: RegDescList and XferDescList APIs Sep 26, 2025
inner: NonNull<bindings::nixl_capi_reg_dlist_s>,
_phantom: PhantomData<&'a dyn NixlDescriptor>,
// Track descriptors internally for comparison purposes
descriptors: Vec<RegDescriptor>,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need to maintain duplicate storage, with all the implications?
Instead of simply exposing operators from C++...
Am I missing something?
patch.txt

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Index and IndexMut

Copy link
Contributor

@roiedanino roiedanino Oct 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like a nice optimization, but I'm afraid some of those APIs may have (or will have in the future) some side effects and checks that we are skipping that way, IMO RegDescList should call the bindings directly, and maybe have another struct called "CachedRegDescList" or make those implementations interchangeable with a configuration flag, making it less error prone, giving a simple workaround in case some incosistencies happen on users end because of this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added sync_mgr to automate consistency and avoid accidental mutation in future changes

@ovidiusm
Copy link
Contributor

/build

- equality operators
- set/get
- get index

Signed-off-by: Evgeny Leksikov <[email protected]>
Add SyncManager absraction to replace manual control

Signed-off-by: Evgeny Leksikov <[email protected]>
@evgeny-leksikov
Copy link
Contributor Author

/build

@evgeny-leksikov evgeny-leksikov marked this pull request as ready for review October 20, 2025 11:07
}

/// Mutates the frontend data (marks as dirty)
pub fn mutate<F, R>(&mut self, f: F) -> R
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor: Maybe we should rename this function to modify, as semantically mutate may be associated mistakenly with a modification of a replica/copy.

Although we can think of it as a copy of the C++ object, it may not be clear to the next developer working on this

Comment on lines +1661 to +1718
// Test XferDescList equality scenarios (same tests as RegDescList)
{
// 1. Empty lists of same type should be equal
let xfer_list1 = XferDescList::new(MemType::Dram).unwrap();
let xfer_list2 = XferDescList::new(MemType::Dram).unwrap();
assert_eq!(xfer_list1, xfer_list2);
assert!(!(xfer_list1 != xfer_list2));

// 2. Lists with different memory types should not be equal
let xfer_list_vram = XferDescList::new(MemType::Vram).unwrap();
assert_ne!(xfer_list1, xfer_list_vram);
assert!(!(xfer_list1 == xfer_list_vram));

// 3. Lists with same descriptors should be equal
let mut xfer_list3 = XferDescList::new(MemType::Dram).unwrap();
let mut xfer_list4 = XferDescList::new(MemType::Dram).unwrap();

xfer_list3.add_desc(0x1000, 0x100, 0).unwrap();
xfer_list3.add_desc(0x2000, 0x200, 1).unwrap();

xfer_list4.add_desc(0x1000, 0x100, 0).unwrap();
xfer_list4.add_desc(0x2000, 0x200, 1).unwrap();

assert_eq!(xfer_list3, xfer_list4);
assert!(!(xfer_list3 != xfer_list4));

// 4. Lists with different descriptors should not be equal
let mut xfer_list5 = XferDescList::new(MemType::Dram).unwrap();
let mut xfer_list6 = XferDescList::new(MemType::Dram).unwrap();

xfer_list5.add_desc(0x1000, 0x100, 0).unwrap();
xfer_list6.add_desc(0x2000, 0x200, 1).unwrap();

assert_ne!(xfer_list5, xfer_list6);
assert!(!(xfer_list5 == xfer_list6));

// 5. Lists with different lengths should not be equal
let mut xfer_list7 = XferDescList::new(MemType::Dram).unwrap();
let xfer_list8 = XferDescList::new(MemType::Dram).unwrap();

xfer_list7.add_desc(0x1000, 0x100, 0).unwrap();

assert_ne!(xfer_list7, xfer_list8);
assert!(!(xfer_list7 == xfer_list8));

// 6. Lists with same descriptors but different order should not be equal
let mut xfer_list9 = XferDescList::new(MemType::Dram).unwrap();
let mut xfer_list10 = XferDescList::new(MemType::Dram).unwrap();

xfer_list9.add_desc(0x1000, 0x100, 0).unwrap();
xfer_list9.add_desc(0x2000, 0x200, 1).unwrap();

xfer_list10.add_desc(0x2000, 0x200, 1).unwrap();
xfer_list10.add_desc(0x1000, 0x100, 0).unwrap();

assert_ne!(xfer_list9, xfer_list10);
assert!(!(xfer_list9 == xfer_list10));
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a separate test; it would be better to move it to a separate test function

Comment on lines +1592 to +1613
// Test RegDescList equality scenarios
{
// 1. Empty lists of same type should be equal
let reg_list1 = RegDescList::new(MemType::Dram).unwrap();
let reg_list2 = RegDescList::new(MemType::Dram).unwrap();
assert_eq!(reg_list1, reg_list2);
assert!(!(reg_list1 != reg_list2));

// 2. Lists with different memory types should not be equal
let reg_list_vram = RegDescList::new(MemType::Vram).unwrap();
assert_ne!(reg_list1, reg_list_vram);
assert!(!(reg_list1 == reg_list_vram));

// 3. Lists with same descriptors should be equal
let mut reg_list3 = RegDescList::new(MemType::Dram).unwrap();
let mut reg_list4 = RegDescList::new(MemType::Dram).unwrap();

reg_list3.add_desc(0x1000, 0x100, 0).unwrap();
reg_list3.add_desc(0x2000, 0x200, 1).unwrap();

reg_list4.add_desc(0x1000, 0x100, 0).unwrap();
reg_list4.add_desc(0x2000, 0x200, 1).unwrap();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It feels like 1, 2, 3, 4, 5, 6, 7 can each be a test on its own. It would also be much easier to look at and understand what failed once one of those scenarios fails.

Also, there are a few lines here and there that look like code duplication that we can avoid


// Tests for equality operators on RegDescList and XferDescList
#[test]
fn test_descriptor_list_equality() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we should add some tests that trigger the synchronization manager and make sure it works properly. Maybe we can do it directly by creating a class that implements the trait just to assert that the synchronization happened

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants