I have some issues using the new raw memory API. For instance, let's
suppose I want to call the `SecRandomCopyBytes` API to generate a
cryptographically secure random 32-bit number. The difficulty is its 3rd
argument, which is declared as UnsafeMutablePointer<UInt8>. Here is a
function that does that:
func entropicRandom() -> UInt32 {
let randomWordPT = UnsafeMutablePointer<UInt32>.allocate(capacity: 1)
let _ = randomWordPT.withMemoryRebound(to: UInt8.self, capacity: 4) {
(p: UnsafeMutablePointer<UInt8>) -> Int32 in
let result = SecRandomCopyBytes(kSecRandomDefault, MemoryLayout<
UInt32>.size, p)
return result
}
let randomInt32 = randomWordPT[0]
randomWordPT.deallocate(capacity: 1)
return randomInt32
}
apparently, the calls to allocate and then deallocate suggest that there is
some heap allocation happening behind the scene here, possibly malloc/free.
Is that correct?
If so, this is quite wasteful. Is there a way to use a local variable on
the stack to achieve the same result?
I have some issues using the new raw memory API. For instance, let's
suppose I want to call the `SecRandomCopyBytes` API to generate a
cryptographically secure random 32-bit number. The difficulty is its 3rd
argument, which is declared as UnsafeMutablePointer<UInt8>. Here is a
function that does that:
func entropicRandom() -> UInt32 {
let randomWordPT = UnsafeMutablePointer<UInt32>.allocate(capacity: 1)
let _ = randomWordPT.withMemoryRebound(to: UInt8.self, capacity: 4) {
(p: UnsafeMutablePointer<UInt8>) -> Int32 in
let result = SecRandomCopyBytes(kSecRandomDefault, MemoryLayout<
UInt32>.size, p)
return result
}
let randomInt32 = randomWordPT[0]
randomWordPT.deallocate(capacity: 1)
return randomInt32
}
apparently, the calls to allocate and then deallocate suggest that there is
some heap allocation happening behind the scene here, possibly malloc/free.
Is that correct?
Quite so.
But what did you suppose allocate and deallocate did, if not dynamic
memory allocation?
If so, this is quite wasteful. Is there a way to use a local variable on
the stack to achieve the same result?
func entropicRandom() -> UInt32 {
var randomInt32: UInt32 = 0
let byteCount = MemoryLayout.size(ofValue: randomInt32)
Personally I would be surprised if the malloc caused an actual measurable
performance hit tbh.
On Mon, 3 Oct 2016 at 02:15 Jean-Denis Muys via swift-users < > swift-users@swift.org> wrote:
Hi,
I have some issues using the new raw memory API. For instance, let's
suppose I want to call the `SecRandomCopyBytes` API to generate a
cryptographically secure random 32-bit number. The difficulty is its 3rd
argument, which is declared as UnsafeMutablePointer<UInt8>. Here is a
function that does that:
func entropicRandom() -> UInt32 {
let randomWordPT = UnsafeMutablePointer<UInt32>.allocate(capacity: 1)
let _ = randomWordPT.withMemoryRebound(to: UInt8.self, capacity: 4) {
(p: UnsafeMutablePointer<UInt8>) -> Int32 in
let result = SecRandomCopyBytes(kSecRandomDefault, MemoryLayout<
UInt32>.size, p)
return result
}
let randomInt32 = randomWordPT[0]
randomWordPT.deallocate(capacity: 1)
return randomInt32
}
apparently, the calls to allocate and then deallocate suggest that there
is some heap allocation happening behind the scene here, possibly
malloc/free. Is that correct?
If so, this is quite wasteful. Is there a way to use a local variable on
the stack to achieve the same result?
Personally I would be surprised if the malloc caused an actual measurable
performance hit tbh.
···
On Mon, 3 Oct 2016 at 02:15 Jean-Denis Muys via swift-users < swift-users@swift.org> wrote:
Hi,
I have some issues using the new raw memory API. For instance, let's
suppose I want to call the `SecRandomCopyBytes` API to generate a
cryptographically secure random 32-bit number. The difficulty is its 3rd
argument, which is declared as UnsafeMutablePointer<UInt8>. Here is a
function that does that:
func entropicRandom() -> UInt32 {
let randomWordPT = UnsafeMutablePointer<UInt32>.allocate(capacity: 1)
let _ = randomWordPT.withMemoryRebound(to: UInt8.self, capacity: 4) {
(p: UnsafeMutablePointer<UInt8>) -> Int32 in
let result = SecRandomCopyBytes(kSecRandomDefault, MemoryLayout<
UInt32>.size, p)
return result
}
let randomInt32 = randomWordPT[0]
randomWordPT.deallocate(capacity: 1)
return randomInt32
}
apparently, the calls to allocate and then deallocate suggest that there
is some heap allocation happening behind the scene here, possibly
malloc/free. Is that correct?
If so, this is quite wasteful. Is there a way to use a local variable on
the stack to achieve the same result?
It won’t be noticeable against a call to SecRandom, as noted, but there are other circumstances where it’s a big performance hit to put a temporary buffer on the heap. (Right now I’m working on some rather performance-sensitive database code in C++ where avoiding a few heap allocations per iteration has proven to be a big win.)
Does Swift have any solution for allocating stack-based array buffers?
—Jens
···
On Oct 2, 2016, at 5:14 PM, Mike Ferenduros via swift-users <swift-users@swift.org> wrote:
Personally I would be surprised if the malloc caused an actual measurable performance hit tbh.
There has been some work in the optimizer toward optimizing arrays onto the stack when they don't escape. In general, I would recommend sticking with the pointer allocate/deallocate methods if you need to directly control the destiny of the memory. If the allocate and deallocate occur unconditionally in the same function, it is possible to optimize the pair into a stack allocation. Using a local variable isn't a guarantee that you'll get stack memory, since closures may force the variable onto the heap, and furthermore subjects you to more aggressive semantic constraints on the underlying memory than you may want.
-Joe
···
On Oct 3, 2016, at 10:20 AM, Jens Alfke via swift-users <swift-users@swift.org> wrote:
On Oct 2, 2016, at 5:14 PM, Mike Ferenduros via swift-users <swift-users@swift.org <mailto:swift-users@swift.org>> wrote:
Personally I would be surprised if the malloc caused an actual measurable performance hit tbh.
It won’t be noticeable against a call to SecRandom, as noted, but there are other circumstances where it’s a big performance hit to put a temporary buffer on the heap. (Right now I’m working on some rather performance-sensitive database code in C++ where avoiding a few heap allocations per iteration has proven to be a big win.)
Does Swift have any solution for allocating stack-based array buffers?
But that function was just an example. I wanted to learn about how to use the stack to call C functions that will fill some memory area passed as a pointer.
Jean-Denis
···
On 3 Oct 2016, at 09:46, Quinn The Eskimo! via swift-users <swift-users@swift.org> wrote:
On 3 Oct 2016, at 01:14, Mike Ferenduros via swift-users <swift-users@swift.org> wrote:
Personally I would be surprised if the malloc caused an actual measurable performance hit tbh.
Quite. SecRandom generates cryptographically sound random numbers and thus is not optimised for speed.
Share and Enjoy
--
Quinn "The Eskimo!" <http://www.apple.com/developer/>
Apple Developer Relations, Developer Technical Support, Core OS/Hardware