Skip to content

Commit 6069814

Browse files
Merge pull request #24335 from ravikandhadai/oslog-refactoring
[os_log][stdlib-private] Refactor new os log APIs based on string interpolation for enabling optimizations.
2 parents 76ced56 + 37f00ed commit 6069814

File tree

2 files changed

+230
-90
lines changed

2 files changed

+230
-90
lines changed

stdlib/private/OSLog/OSLog.swift

Lines changed: 49 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
@available(macOS 10.12, iOS 10.0, watchOS 3.0, tvOS 10.0, *)
2020
public struct Logger {
21+
@usableFromInline
2122
internal let logObject: OSLog
2223

2324
/// Create a custom OS log object.
@@ -30,8 +31,16 @@ public struct Logger {
3031
logObject = OSLog.default
3132
}
3233

34+
// Functions defined below are marked @_optimize(none) to prevent inlining
35+
// of string internals (such as String._StringGuts) which will interfere with
36+
// constant evaluation and folding. Note that these functions will be inlined,
37+
// constant evaluated/folded and optimized in the context of a caller.
38+
3339
/// Log a string interpolation at a given level. The level is `default` if
3440
/// it is not specified.
41+
@inlinable
42+
@_semantics("oslog.log")
43+
@_optimize(none)
3544
public func log(level: OSLogType = .default, _ message: OSLogMessage) {
3645
osLog(logObject, level, message)
3746
}
@@ -44,28 +53,46 @@ public struct Logger {
4453
/// extract the format string, serialize the arguments to a byte buffer,
4554
/// and pass them to the OS logging system.
4655
@available(macOS 10.12, iOS 10.0, watchOS 3.0, tvOS 10.0, *)
56+
@usableFromInline
57+
@_transparent
58+
@_optimize(none)
4759
internal func osLog(
4860
_ logObject: OSLog,
4961
_ logLevel: OSLogType,
5062
_ message: OSLogMessage
5163
) {
52-
guard logObject.isEnabled(type: logLevel) else { return }
53-
64+
// Compute static constants first so that they can be folded by
65+
// OSLogOptimization pass.
66+
let formatString = message.interpolation.formatString
67+
let preamble = message.interpolation.preamble
68+
let argumentCount = message.interpolation.argumentCount
5469
let bufferSize = message.bufferSize
55-
let bufferMemory = UnsafeMutablePointer<UInt8>.allocate(capacity: bufferSize)
56-
var builder = OSLogByteBufferBuilder(bufferMemory)
5770

58-
message.serializeArguments(into: &builder)
71+
// Code that will execute at runtime.
72+
let arguments = message.interpolation.arguments
73+
formatString.withCString { cFormatString in
74+
75+
guard logObject.isEnabled(type: logLevel) else { return }
76+
77+
// Ideally, we could stack allocate the buffer as it is local to this
78+
// function and also its size is a compile-time constant.
79+
let bufferMemory =
80+
UnsafeMutablePointer<UInt8>.allocate(capacity: bufferSize)
81+
var builder = OSLogByteBufferBuilder(bufferMemory)
82+
83+
builder.serialize(preamble)
84+
builder.serialize(argumentCount)
85+
arguments.serialize(into: &builder)
5986

60-
message.formatString.withCString { cFormatString in
6187
___os_log_impl(UnsafeMutableRawPointer(mutating: #dsohandle),
6288
logObject,
6389
logLevel,
6490
cFormatString,
6591
bufferMemory,
6692
UInt32(bufferSize))
93+
94+
bufferMemory.deallocate()
6795
}
68-
bufferMemory.deallocate()
6996
}
7097

7198
/// A test helper that constructs a byte buffer and a format string from an
@@ -76,18 +103,31 @@ internal func osLog(
76103
/// - message: An instance of `OSLogMessage` created from string interpolation
77104
/// - assertion: A closure that takes a format string and a pointer to a
78105
/// byte buffer and asserts a condition.
106+
@inlinable
107+
@_semantics("oslog.log.test_helper")
108+
@_optimize(none)
79109
public // @testable
80110
func _checkFormatStringAndBuffer(
81111
_ message: OSLogMessage,
82112
with assertion: (String, UnsafeBufferPointer<UInt8>) -> Void
83113
) {
114+
// Compute static constants first so that they can be folded by
115+
// OSLogOptimization pass.
116+
let formatString = message.interpolation.formatString
117+
let preamble = message.interpolation.preamble
118+
let argumentCount = message.interpolation.argumentCount
84119
let bufferSize = message.bufferSize
120+
121+
// Code that will execute at runtime.
85122
let bufferMemory = UnsafeMutablePointer<UInt8>.allocate(capacity: bufferSize)
86123
var builder = OSLogByteBufferBuilder(bufferMemory)
87-
message.serializeArguments(into: &builder)
124+
125+
builder.serialize(preamble)
126+
builder.serialize(argumentCount)
127+
message.interpolation.arguments.serialize(into: &builder)
88128

89129
assertion(
90-
message.formatString,
130+
formatString,
91131
UnsafeBufferPointer(start: UnsafePointer(bufferMemory), count: bufferSize))
92132

93133
bufferMemory.deallocate()

0 commit comments

Comments
 (0)