Using libevent together with GCD (libdispatch) in Swift - swift

I'm creating a server side app in Swift 3. I've chosen libevent for implementing networking code because it's cross-platform and doesn't suffer from C10k problem. Libevent implements it's own event loop, but I want to keep CFRunLoop and GCD (DispatchQueue.main.after etc) functional as well, so I need to glue them somehow.
This is what I've came up with:
var terminated = false
DispatchQueue.main.after(when: DispatchTime.now() + 3) {
print("Dispatch works!")
terminated = true
}
while !terminated {
switch event_base_loop(eventBase, EVLOOP_NONBLOCK) { // libevent
case 1:
break // No events were processed
case 0:
print("DEBUG: Libevent processed one or more events")
default: // -1
print("Unhandled error in network backend")
exit(1)
}
RunLoop.current().run(mode: RunLoopMode.defaultRunLoopMode,
before: Date(timeIntervalSinceNow: 0.01))
}
This works, but introduces a latency of 0.01 sec. While RunLoop is sleeping, libevent won't be able to process events. Lowering this timeout increases CPU usage significantly when the app is idle.
I was also considering using only libevent, but third party libs in the project can use dispatch_async internally, so this can be problematic.
Running libevent's loop in a different thread makes synchronization more complex, is this the only way of solving this latency issue?
LINUX UPDATE. The above code does not work on Linux (2016-07-25-a Swift snapshot), RunLoop.current().run exists with an error. Below is a working Linux version reimplemented with a timer and dispatch_main. It suffers from the same latency issue:
let queue = dispatch_get_main_queue()
let timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue)
let interval = 0.01
let block: () -> () = {
guard !terminated else {
print("Quitting")
exit(0)
}
switch server.loop() {
case 1: break // Just idling
case 0: break //print("Libevent: processed event(s)")
default: // -1
print("Unhandled error in network backend")
exit(1)
}
}
block()
let fireTime = dispatch_time(DISPATCH_TIME_NOW, Int64(interval * Double(NSEC_PER_SEC)))
dispatch_source_set_timer(timer, fireTime, UInt64(interval * Double(NSEC_PER_SEC)), UInt64(NSEC_PER_SEC) / 10)
dispatch_source_set_event_handler(timer, block)
dispatch_resume(timer)
dispatch_main()

A quick search of the Open Source Swift Foundation libraries on GitHub reveals that the support in CFRunLoop is (perhaps obviously) implemented differently on different platforms. This means, in essence, that RunLoop and libevent, with respect to cross-platform-ness, are just different ways to achieve the same thing. I can see the thinking behind the thought that libevent is probably better suited to server implementations, since CFRunLoop didn't grow up with that specific goal, but as far as being cross-platform goes, they're both barking up the same tree.
That said, the underlying synchronization primitives used by RunLoop and libevent are inherently private implementation details and, perhaps more importantly, different between platforms. From the source, it looks like RunLoop uses epoll on Linux, as does libevent, but on macOS/iOS/etc, RunLoop is going to use Mach ports as its fundamental primitive, but libevent looks like it's going to use kqueue. You might, with enough effort, be able to make a hybrid RunLoopSource that ties to a libevent source for a given platform, but this would likely be very fragile, and generally ill-advised, for a couple of reasons: Firstly, it would be based on private implementation details of RunLoop that are not part of the public API, and therefore subject to change at any time without notice. Second, assuming you didn't go through and do this for every platform supported by both Swift and libevent, you would have broken the cross-platform-ness of it, which was one of your stated reasons for going with libevent in the first place.
One additional option you might not have considered would be to use GCD by itself, without RunLoops. Look at the docs for dispatch_main. In a server application, there's (typically) nothing special about a "main thread," so dispatching to the "main queue", should be good enough (if needed at all). You can use dispatch "sources" to manage your connections, etc. I can't personally speak to how dispatch sources scale up to the C10K/C100K/etc. level, but they've seemed pretty lightweight and low-overhead in my experience. I also suspect that using GCD like this would likely be the most idiomatic way to write a server application in Swift. I've written up a small example of a GCD-based TCP echo server as part of another answer here.
If you were bound and determined to use both RunLoop and libevent in the same application, it would, as you guessed, be best to give libevent it's own separate thread, but I don't think it's as complex as you might think. You should be able to dispatch_async from libevent callbacks freely, and similarly marshal replies from GCD managed threads to libevent using libevent's multi-threading mechanisms fairly easily (i.e. either by running with locking on, or by marshaling your calls into libevent as events themselves.) Similarly, third party libraries using GCD should not be an issue even if you chose to use libevent's loop structure. GCD manages its own thread pools and would have no way of stepping on libevent's main loop, etc.
You might also consider architecting your application such that it didn't matter what concurrency and connection handling library you used. Then you could swap out libevent, GCD, CFStreams, etc. (or mix and match) depending on what worked best for a given situation or deployment. Choosing a concurrency approach is important, but ideally you wouldn't couple yourself to it so tightly that you couldn't switch if circumstances called for it.
When you have such an architecture, I'm generally a fan of the approach of using the highest level abstraction that gets the job done, and only driving down to lower level abstractions when specific circumstances require it. In this case, that would probably mean using CFStreams and RunLoops to start, and switching out to "bare" GCD or libevent later, if you hit a wall and also determined (through empirical measurement) that it was the transport layer and not the application layer that was the limiting factor. Very few non-trivial applications actually get to the C10K problem in the transport layer; things tend to have to scale "out" at the application layer first, at least for apps more complicated than basic message passing.

Related

Background task in reactive pipeline (Fire-and-forget)

I have a reactive pipeline to process incoming requests. For each request I need to call a business-relevant function (doSomeRelevantProcessing).
After that is done, I need to notify some external service about what happened. That part of the pipeline should not increase the overall response time.
Also, notifying this external system is not business critical: giving a quick response after the main part of the pipeline is finished is more important than making sure the notification is successful.
As far as I learned, the only way to run something in the background without slowing down the overall process is to subscribe to in directly in the pipeline, thus achieving a fire-and-forget mentality.
Is there a good alternative to subscribing inside the flatmap?
I am a little worried about what might happen if notifying the external service takes longer than the original processing and a lot of requests are coming in at once. Could this lead to a memory exhaustion or the overall process to block?
fun runPipeline(incoming: Mono<Request>) = incoming
.flatMap { doSomeRelevantProcessing(it) } // this should not be delayed
.flatMap { doBackgroundJob(it) } // this can take a moment, but is not super critical
fun doSomeRelevantProcessing(request: Request) = Mono.just(request) // do some processing
fun doBackgroundJob(request: Request) = Mono.deferContextual { ctx: ContextView ->
val notification = "notification" // build an object from context
// this uses non-blocking HTTP (i.e. webclient), so it can take a second or so
notifyExternalService(notification).subscribeOn(Schedulers.boundedElastic()).subscribe()
Mono.just(Unit)
}
fun notifyExternalService(notification: String) = Mono.just(Unit) // might take a while
I'm answering this assuming that you notify the external service using purely reactive mechanisms - i.e. you're not wrapping a blocking service. If you are then the answer would be different as you're bound by the size of your bounded elastic thread pool, which could quickly become overwhelmed if you have hundreds of requests a second incoming.
(Assuming you're using reactive mechanisms, then there's no need for .subscribeOn(Schedulers.boundedElastic()) as you give in your example, as that's not buying you anything - it's designed for wrapping legacy blocking services.)
Could this lead to a memory exhaustion
It's only a possibility in really extreme cases, the memory used by each individual request will be tiny. It's almost certainly not worth worrying about, if you start seeing memory issues here then you'll almost certainly be hit by other issues elsewhere.
That being said, I'd probably recommend adding .timeout(Duration.ofSeconds(5)) or similar before your inner subscribe method to make sure the requests are killed off after a while if they haven't worked for any reason - this will prevent them building up.
...or [can this cause] the overall process to block?
This one is easier - a short no, it can't.

is GCD really Thread-Safe?

I have studied GCD and Thread-Safe.
In apple document, GCD is Thread-Safe that means multiple thread can access.
And I learned meaning of Thread-Safe that always give same result whenever multiple thread access to some object.
I think that meaning of Thread-Safe and GCD's Thread-Safe is not same because I tested some case which is written below to sum 0 to 9999.
"something.n" value is not same when I excute code below several time.
If GCD is Thread-Safe , Why isn't "something.n" value same ?
I'm really confused with that.. Could you help me?
I really want to master Thread-Safe!!!
class Something {
var n = 0
}
class ViewController: UIViewController {
let something = Something()
var concurrentQueue = DispatchQueue(label: "asdf", attributes: .concurrent)
override func viewDidLoad() {
super.viewDidLoad()
let group = DispatchGroup()
for idx in 0..<10000 {
concurrentQueue.async(group: group) {
self.something.n += idx
}
}
group.notify(queue: .main ) {
print(self.something.n)
}
}
}
You said:
I have studied GCD and Thread-Safe. In apple document, GCD is Thread-Safe that means multiple thread can access. And I learned meaning of Thread-Safe that always give same result whenever multiple thread access to some object.
They are saying the same thing. A block of code is thread-safe only if it is safe to invoke it from different threads at the same time (and this thread safety is achieved by making sure that the critical portion of code cannot run on one thread at the same time as another thread).
But let us be clear: Apple is not saying that if you use GCD, that your code is automatically thread-safe. Yes, the dispatch queue objects, themselves, are thread-safe (i.e. you can safely dispatch to a queue from whatever thread you want), but that doesn’t mean that your own code is necessarily thread-safe. If one’s code is accessing the same memory from multiple threads concurrently, one must provide one’s own synchronization to prevent writes simultaneous with any other access.
In the Threading Programming Guide: Synchronization, which predates GCD, Apple outlines various mechanisms for synchronizing code. You can also use a GCD serial queue for synchronization. If you using a concurrent queue, one achieves thread safety if you use a “barrier” for write operations. See the latter part of this answer for a variety of ways to achieve thread safety.
But be clear, Apple is not introducing a different definition of “thread-safe”. As they say in that aforementioned guide:
When it comes to thread safety, a good design is the best protection you have. Avoiding shared resources and minimizing the interactions between your threads makes it less likely for those threads to interfere with each other. A completely interference-free design is not always possible, however. In cases where your threads must interact, you need to use synchronization tools to ensure that when they interact, they do so safely.
And in the Concurrency Programming Guide: Migrating Away from Threads: Eliminating Lock-Based Code, which was published when GCD was introduced, Apple says:
For threaded code, locks are one of the traditional ways to synchronize access to resources that are shared between threads. ... Instead of using a lock to protect a shared resource, you can instead create a queue to serialize the tasks that access that resource.
But they are not saying that you can just use GCD concurrent queues and automatically achieve thread-safety, but rather that with careful and proper use of GCD queues, one can achieve thread-safety without using locks.
By the way, Apple provides tools to help you diagnose whether your code is thread-safe, namely the Thread Sanitizer (TSAN). See Diagnosing Memory, Thread, and Crash Issues Early.
Your current queue is concurrent
var concurrentQueue = DispatchQueue(label: "asdf", attributes: . concurrent)
which means that code can run in any order inside every async
Every run has a different order but variable is accessed only by one part at a time

Trap SIGINT in Cocoa macos application

I am attempting to trap a SIGINT for a UI application made for MacOS. In the app delegate class, I see the following method:
func applicationWillTerminate(_ aNotification: Notification) {
}
However, a Ctrl + C, SIGINT, never gets caught in here. Reading around the internet, has shown that this function is not guaranteed to execute, especially if the app goes in the background.
What can I do in the app delegate to catch a SIGINT? Or is there an alternate place I am to catch the interrupt so that I can close the resources appropriately?
Charles's answer is correct, but his caveat ("Be sure only to call reentrant functions from within the handler") is an extreme limitation. It's possible to redirect handling of a signal to a safer environment using kqueue and CFFileDescriptor.
Technical Note TN2050: Observing Process Lifetimes Without Polling is on a different subject but illustrates the technique. There, Apple describes Charles's caveat this way:
Listening for a signal can be tricky because of the wacky execution
environment associated with signal handlers. Specifically, if you
install a signal handler (using signal or sigaction), you must be very
careful about what you do in that handler. Very few functions are safe
to call from a signal handler. For example, it is not safe to allocate
memory using malloc!
The functions that are safe from a signal handler (the async-signal
safe functions) are listed on the sigaction man page.
In most cases you must take extra steps to redirect incoming signals
to a more sensible environment.
I've taken the code illustration from there and modified it for handling SIGINT. Sorry, it's Objective-C. Here's the one-time setup code:
// Ignore SIGINT so it doesn't terminate the process.
signal(SIGINT, SIG_IGN);
// Create the kqueue and set it up to watch for SIGINT. Use the
// EV_RECEIPT flag to ensure that we get what we expect.
int kq = kqueue();
struct kevent changes;
EV_SET(&changes, SIGINT, EVFILT_SIGNAL, EV_ADD | EV_RECEIPT, NOTE_EXIT, 0, NULL);
(void) kevent(kq, &changes, 1, &changes, 1, NULL);
// Wrap the kqueue in a CFFileDescriptor. Then create a run-loop source
// from the CFFileDescriptor and add that to the runloop.
CFFileDescriptorContext context = { 0, self, NULL, NULL, NULL };
CFFileDescriptorRef kqRef = CFFileDescriptorCreate(NULL, kq, true, sigint_handler, &context);
CFRunLoopSourceRef rls = CFFileDescriptorCreateRunLoopSource(NULL, kqRef, 0);
CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode);
CFRelease(rls);
CFFileDescriptorEnableCallBacks(kqRef, kCFFileDescriptorReadCallBack);
CFRelease(kqRef);
And here's how you would implement the sigint_handler callback referenced above:
static void sigint_handler(CFFileDescriptorRef f, CFOptionFlags callBackTypes, void *info)
{
struct kevent event;
(void) kevent(CFFileDescriptorGetNativeDescriptor(f), NULL, 0, &event, 1, NULL);
CFFileDescriptorEnableCallBacks(f, kCFFileDescriptorReadCallBack);
// You've been notified!
}
Note that this technique requires that you run the setup code on a thread which will live as long as you're interested in handling SIGINT (perhaps the app's lifetime) and service/run its run loop. Threads created by the system for its own purposes, such as those which service Grand Central Dispatch queues, are not suitable for this purpose.
The main thread of the app will work and you can use it. However, if the main thread locks up or become unresponsive, then it's not servicing its run loop and the SIGINT handler won't be called. Since SIGINT is often used to interrupt exactly such a stuck process, the main thread may not be suitable.
So, you may want to spawn a thread of your own just to monitor this signal. It should do nothing else, because anything else might cause it to get stuck, too. Even there, though, there are issues. Your handler function will be called on this background thread of yours and the main thread may still be locked up. There's a lot of stuff that is main-thread-only in the system libraries and you won't be able to do any of that. But you'll have much greater flexibility than in a POSIX-style signal handler.
I should add that GCD's dispatch sources can also monitor UNIX signals and are easier to work with, especially from Swift. However, they won't have a dedicated thread pre-created to run the handler. The handler will be submitted to a queue. Now, you may designate a high-priority/high-QOS queue, but I'm not entirely certain that the handler will get run if the process has numerous runaway threads already running. That is, a task that's actually running on a high-priority queue will take precedence over lower-priority threads or queues, but starting a new task might not. I'm not sure.
You can do this via the sigaction() function:
import Foundation
let handler: #convention(c) (Int32) -> () = { sig in
// handle the signal somehow
}
var action = sigaction(__sigaction_u: unsafeBitCast(handler, to: __sigaction_u.self),
sa_mask: 0,
sa_flags: 0)
sigaction(SIGINT, &action, nil)
Be sure only to call reentrant functions from within the handler.
Although I won't dare to compete with the great answers above, I think there is something important to say that may simplify the solution a lot.
I think your question mixes two very different levels of MacOS program life-cycle management.
True, you can run simple posix-style executables on Mac - but a Mac Cocoa app IS NOT a posix app with "attached UI". Mac application relies on a very verbose, complete, and feature-rich life-cycle mechanism that allows much more than anything posix process can -- from state preservation and restoration (when killed/re-launched) to being auto-launched in response to opening a file. Energy management, handling computer sleep, background and foreground transitions, attaching to the same app on close-by device, modes etc. etc.
Furthermore -- I can't see how one can ever expect a 'ctrl-C' from the keyboard to reach a Cocoa ("UI") application, as keyboard shortcuts are totally different in this context, and you can't run "UI" app from a terminal/shell synchronously.
Now the right wa to 'interrupt' a Cocoa app that is "stuck" or takes too long to perform something, is using the convention command-preiod key-combination, still widely implemented by many apps (Photoshop, video-editors, the Finder etc.) I'm sorry I could not locate this definition in Apple User Interface Guidelines - maybe it is no longer part of the standard. However, Ctrl-C certainly isn't!!!
you can implement Cmd-Period (⌘.) in your app (i.e. register for this high-level "interrupt" action, and handle it gracefully.
There is a good reason why NSApplication object wrapping the Cocoa App ignores SIGINT! it is completely out of context.

play - how to wrap a blocking code with futures

I am trying to understand the difference between the 2 methods, in terms of functionality.
class MyService (blockService: BlockService){
def doSomething1(): Future[Boolean] = {
//do
//some non blocking
//stuff
val result = blockService.block()
Future.successful(result)
}
def doSomething2(): Future[Boolean] = {
Future{
//do
//some non blocking
//stuff
blockService.block()
}
}
}
To my understanding the difference between the 2 is which thread is the actual thread that will be blocked.
So if there is a thread: thread_1 that execute something1, thread_1 will be the one that is blocked, while if a thread_1 executed something2a new thread will run it - thread_2, and thread_2 is the one to be blocked.
Is this true?
If so, than there is no really a preferred way to write this code? if I don't care which thread will eventually be blocked, then the end result will be the same.
dosomething1 seems like a weird way to write this code, I would choose dosomething2.
Make sense?
Yes, doSomething1 and doSomething2 blocks different threads, but depending on your scenario, this is an important decision.
As #AndreasNeumann said, you can have different execution contexts in doSomething2. Imagine that the main execution context is the one receiving HTTP requests from your users. Block threads in this context is bad because you can easily exhaust the execution context and impact requests that have nothing to do with doSomething.
Play docs have a better explanation about the possible problems with having blocking code:
If you plan to write blocking IO code, or code that could potentially do a lot of CPU intensive work, you need to know exactly which thread pool is bearing that workload, and you need to tune it accordingly. Doing blocking IO without taking this into account is likely to result in very poor performance from Play framework, for example, you may see only a few requests per second being handled, while CPU usage sits at 5%. In comparison, benchmarks on typical development hardware (eg, a MacBook Pro) have shown Play to be able to handle workloads in the hundreds or even thousands of requests per second without a sweat when tuned correctly.
In your case, both methods are being executed using Play default thread pool. I suggest you to take a look at the recommended best practices and see if you need a different execution context or not. I also suggest you to read Akka docs about Dispatchers and Futures to gain a better understanding about what executing Futures and have blocking/non-blocking code.
This approach makes sense if you make use of different execution contexts in the second method.
So having for example one for answering requests and another for blocking requests.
So you would use the normal playExecutionContext to keep you application running and answering and separate blocking operation in a different one.
def doSomething2(): Future[Boolean] = Future{
blocking { blockService.block() }
}( mySpecialExecutionContextForBlockingOperations )
For a little more information: http://docs.scala-lang.org/overviews/core/futures.html#blocking
You are correct. I don't see a point in doSomething1. It simply complicates the interface for the caller while not providing the benefits of an asynchronous API.
Does BlockService handle blocking operation?
Normally, use blocking ,as #Andreas remind,to make blocking operation into another thread is meanful.

iOS Threads Wait for Action

I have a processing thread that I use to fill a data buffer. Elsewhere a piece of hardware triggers a callback which reads from this data buffer. The processing thread then kicks in and refills the buffer.
When the buffer fills up I am currently telling the thread to wait by:
while( [self FreeWriteSpace] < mProcessBufferSize && InActive) {
[NSThread sleepForTimeInterval:.0001];
}
However when I profile I am getting a lot of CPU time spent in sleep. Is there a better way to wait? Do I even care if the profiles says time is spent in sleep?
Time spent in sleep is effectively free. In Instruments, look at "running samples" rather than "all samples." But this still isn't an ideal solution.
First, your sleep interval is crazy. Do you really need .1µs granularity? The system almost certainly isn't giving you because the processor isn't that fast. I have to believe you could up this to .1 or .01. But that's still busy-waiting which is not ideal if you can help it.
The better solution is to use an NSCondition. In this thread, wait on the condition, and in your processing thread, trigger the condition when there's room to write.
Do be careful with your naming. Do not name methods with leading caps (that indicates that it's a class name). And avoid accessing ivars directly (InActive) like this. "InActive" is also a very confusing name. Does it mean the system is active (In Active) or not active (inactive). Naming in Objective-C is extremely important. The compiler will not protect you the way it does in C# and C++. Good naming is how you keep your programs working, and many parts of ObjC rely on it.
You may also want to investigate Grand Central Dispatch, which is particularly designed for these kinds of problems. Look at dispatch_async() to run things when new data comes in.
However when I profile I am getting a
lot of CPU time spent in sleep. Is
there a better way to wait? Do I even
care if the profiles says time is
spent in sleep?
Yes -- never, never poll. Polling eats CPU, makes your app less responsive, eats battery, and is an all around waste.
Notify instead.
The easiest way is to use one of the variants of "perform selector on main thread" (see NSThread's documentation). Or dispatch to a queue (including something like dispatch_async(dispatch_get_main_queue(), ^{ ... yo, data be ready ...});).