3 Replies
      Latest reply on Aug 23, 2017 1:50 AM by eskimo
      dhamukrish Level 1 Level 1 (0 points)

        Hi,

         

        I need help to solve this error. Basically this was working fine in Swift 2.x and Swift 3 broken. Please advise.

        Note that below code is almost converted to Swift 3 but with below error.

         

        Error

        'init' is unavailable: use 'withMemoryRebound(to:capacity:_)' to temporarily view memory as another layout-compatible type.

         

        Error Line: 7

        let kerr = task_info(name, flavor, UnsafeMutablePointer(infoPointer), &size)

         

        Here is the code snippet

        open class func getMemoryUsed() -> Float {
          let MACH_TASK_BASIC_INFO_COUNT = (MemoryLayout<mach_task_basic_info_data_t>.size / MemoryLayout<natural_t>.size)
          let name = mach_task_self_
          let flavor = task_flavor_t(MACH_TASK_BASIC_INFO)
          var size = mach_msg_type_number_t(MACH_TASK_BASIC_INFO_COUNT)
          let infoPointer = UnsafeMutablePointer<mach_task_basic_info>.allocate(capacity: 1)
          let kerr = task_info(name, flavor, UnsafeMutablePointer(infoPointer), &size)
          let info = infoPointer.move()
          infoPointer.deallocate(capacity: 1)
        
          if kerr == KERN_SUCCESS {
            let used_bytes: Float = Float(info.resident_size)
            let total_bytes: Float = Float(ProcessInfo.processInfo.physicalMemory)
            log.info("Used: \(used_bytes / 1024.0 / 1024.0) MB out of \(total_bytes / 1024.0 / 1024.0) MB (\(used_bytes * 100.0 / total_bytes)%)")
            return used_bytes / 1000000 /
          }
        }
        
        


        • Re: Swift 3 iOS Memory Usage for Monitoring
          eskimo Apple Staff Apple Staff (10,065 points)

          Mach, like many old school C-based APIs, plays fast’n’loose with typing.  Getting this to work with Swift 3’s stricter aliasing rules is tricky.  Honestly, I think you might be better off writing a C helper routine to do this and then calling that helper routine from Swift.

          However, to answer your direct question, here’s how to call task_info to get MACH_TASK_BASIC_INFO in Swift 3.

          func mach_task_self() -> task_t {
              return mach_task_self_
          }
          
          func getMegabytesUsed() -> Float? { 
              var info = mach_task_basic_info()
              var count = mach_msg_type_number_t(MemoryLayout.size(ofValue: info) / MemoryLayout<integer_t>.size)
              let kerr = withUnsafeMutablePointer(to: &info) { infoPtr in
                  return infoPtr.withMemoryRebound(to: integer_t.self, capacity: Int(count)) { (machPtr: UnsafeMutablePointer<integer_t>) in
                      return task_info(
                          mach_task_self(),
                          task_flavor_t(MACH_TASK_BASIC_INFO),
                          machPtr,
                          &count
                      )
                  }
              }
              guard kerr == KERN_SUCCESS else {
                  return nil
              }
              return Float(info.resident_size) / (1024 * 1024) 
          }
          

          Notes

          • Lines 1…3 expose mach_task_self_ via a function-based wrapper, as you’d expect in C.

          • Line 6 declares the output buffer on the stack as the correct type, mach_task_basic_info.

          • Line 7 calculates its size in terms of integer_t, which is how Mach IPC counts.

          • Line 8 gets its address as an UnsafeMutablePointer<mach_task_basic_info>.

          • Line 9 reinterprets that as a contiguous array of integer_t, which is what Mach IPC wants.

          Finally, be warned that the value returned by this function has limited utility.  It might be useful when debugging but it’s almost certainly a very bad idea to use in production code.  If you are using it in product code, please post back explaining what you’re using it for and I can explain why that’s a bad idea (-:

          Share and Enjoy

          Quinn “The Eskimo!”
          Apple Developer Relations, Developer Technical Support, Core OS/Hardware
          let myEmail = "eskimo" + "1" + "@apple.com"

            • Re: Swift 3 iOS Memory Usage for Monitoring
              LWisniewski Level 1 Level 1 (0 points)

              Hi Eskimo,

               

              Can you expand on your comment that it's a bad idea to use this in production code?  I was looking for a way to monitor "typical" memory usage.

                • Re: Swift 3 iOS Memory Usage for Monitoring
                  eskimo Apple Staff Apple Staff (10,065 points)

                  Can you expand on your comment that it's a bad idea to use this in production code?

                  Sure.  The problem with this API — and this is true for all the low-level Mach APIs that let you introspect the state of virtual memory — is that they are intimately tied to the kernel’s VM implementation.  That has changed radically in the past and may well change radically in the future, and those changes can invalidate the assumptions implicit in your use of the API.  I talked about this in detail on this thread.

                  I was looking for a way to monitor "typical" memory usage.

                  OK.  And what action are you going to take based on the value you get back?  If the goal is to report that value via your analytics, that’s fine.  When you do your analysis you can take the OS version and device hardware into account.  If, on the other hand, you plan to change your app’s behaviour based on that value, you have to be very careful.

                  Share and Enjoy

                  Quinn “The Eskimo!”
                  Apple Developer Relations, Developer Technical Support, Core OS/Hardware
                  let myEmail = "eskimo" + "1" + "@apple.com"