Data .alwaysMapped question

Hi all,

I've got a question about the Data type functionality. If I load a fileURL through the Data(contentsOf:options:) initializer with .alwaysMapped, if I subscript that variable, does that still reference the local file or does it keep it in memory somehow?

extension Collection {
    func unfoldSubSequences(limitedTo maxLength: Int) -> UnfoldSequence<SubSequence, Index> {
        sequence(state: startIndex) { start in
            guard start < endIndex else { return nil }
            let end = index(start, offsetBy: maxLength, limitedBy: endIndex) ?? endIndex
            defer { start = end }
            return self[start..<end]
        }
    }
    
    func subSequences(of n: Int) -> [SubSequence] {
        .init(unfoldSubSequences(limitedTo: n))
    }
}

Thank you in advance!

if I subscript that variable, does that still reference the local file or does it keep it in memory somehow?

Let’s start with some basics:

  • The word memory is overloaded here. It might mean virtual address space and it might mean physical pages.

  • When you memory map a file, that consumes a chunk of virtual address space until you unmap it.

  • When you touch a page within that mapping, the kernel allocates a physical page, reads the file into it, and maps it into your address space.

  • This page then becomes like any other file-mapped read-only page in your process. The VM system can recover it at any time.

So the only meaningful way to answer the “keep it in memory” question is to focus on the virtual address space. In that case:

  • Data is a struct but, internally, it manages a backing object that manages the actual data.

  • When you initialise Data with .alwaysMapped, it creates the backing object which holds the mapping to the file.

  • Data unmaps the file when the last reference to that backing goes away.

  • Data is its own slice type. If you slice a Data value, the new Data value refers to the same backing object.

  • The backing object is read only. If you try to modify the contents of the Data value, that will trigger a copy. This is process known as copy-on-write.

In your example you do a bunch of slicing. The Data value and each of its slices all reference the same backing object. That backing object will go away, which unmaps the file, when you’re done with the last slice. There should be no copies unless someone writes to the Data value itself or one of these slices.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Data .alwaysMapped question
 
 
Q