read

Italian fashion industry ready for resurrection




read

Weekend Reading 4.26.20

Hello friends, happy Sunday to you all. It’s day 42 of quarantine for us here in the Bay Area. I feel as if there are people out there that are close to cracking. Many are feeling anxious about the uncertainty of the world and a little crazy being cooped up indoors so this is a




read

Weekend Reading 5.3.20

I woke up in a good mood, but it shifted when I started reading the articles and posts coming from everywhere, all of them laden with the rising tension among people that is escalating with the ongoing quarantine. There are endless opinions and cautionary statistics stacked up against people’s desires to open businesses and exercise




read

Photos show how the world is readapting to socially-distanced life during the coronavirus pandemic, from plastic table barriers to taped-up urinals

Jorge Silva/Reuters

  • As some countries have started to lift their lockdown measures, public places have been making changes to adapt to government-issued social distancing measures. 
  • More public places are using tape, floor markers and plastic dividers to help people comply with social distancing guidelines. 
  • Photos show how people are trying to adapt to a new way of life during the coronavirus pandemic.
  • Visit Business Insider's homepage for more stories.

As some countries begin to lift their coronavirus lockdown measures, public places have been getting creative to adjust to social distancing guidelines.

From waiters wearing personal protective equipment to schools using plastic dividers between children, these photos show the world is adjusting to life under the coronavirus pandemic.

As countries begin to slowly lift their lockdown measures, many changes have to be made to public life in an effort to prevent second waves of COVID-19.



One of the places that have to adapt the most is restaurants. Some have been coming up with creative ways to enforce social distancing measures, including putting up dividers on tables.

Athit Perawongmetha/Reuters

But in some places, a plastic divider is not enough. Diners in this Bangkok restaurant, for example, have been asked to sit diagonally from each other to maximize their distance.

Jorge Silva/Reuters


See the rest of the story at Business Insider

See Also:

SEE ALSO: LA's skies are smog-free and peacocks are roaming the streets of Dubai. Photos show how nature has returned to cities shut down by the coronavirus pandemic.




read

Slow the Spread of COVID-19 with Proper Cleaning of Electrical PPE

Due to the cross-contamination challenges impacting our industry caused by COVID-19, Enespro has updated our Care and Maintenance Guidelines for Electrical PPE, incorporating important CDC guidelines and references to ASTM F496.




read

ReadCube partners with publishers to launch initiative to access literature for COVID-19 research

The COVID-19 Research Pass (CPR) program provides direct access to more than 26 million articles




read

Brent falls 10%, WTI below $30 as coronavirus spreads

Brent falls 10%, WTI below $30 as coronavirus spreads





read

US crude plunges to 18-year low as lockdowns spread

US crude plunges to 18-year low as lockdowns spread





read

Surviving the technoshock: How to get your organisation ready for AI-powered ERP

Machines and people, working in concert, will be critical to the success of tomorrow’s ERP systems and enterprises.




read

SCCM Pod-219 PCCM: Readmissions to the Pediatric ICU

Margaret Parker, MD, FCCM, speaks with MD, MPH, Angela S. Czaja, MD, MSc, lead author on an article published in the July Pediatric Critical Care Medicine.




read

Poke Me: H-1B issue in US provides the right push – and opportunity – for India (Reader's React)

This week's "Poke Me" invited your comments on "H-1B issue in US provides the right push – and opportunity – for India".




read

Poke Me: SEBI needs to loosen up and keep its eye on investor interest using economics (Reader's React)

Sebi must ensure that no one is hanged without a fair hearing, levy of penalty on Reliance speaks about the regulator’s firmness, a reader said.




read

Poke Me: How Dry Is My Valley (Readers React)

This week's "Poke Me" invited your comments on "How Dry Is My Valley". Here are the selected opinions that were published in the ET print edition on Saturday.




read

Poke Me: Time to Tweak Capitalism (Readers React)

This week's "Poke Me" invited your comments on "Time to Tweak Capitalism". Here are the selected opinions that were published in the ET print edition on Saturday.




read

Poke Me: Young and the restless(Readers React)

This week's "Poke Me" invited your comments on "Young and the restless". Here are the selected opinions.




read

Cancel flight ticket, or reschedule? The best way to readjust travel plans in times of coronavirus

Now all domestic airlines, including government-owned Air India, have announced a waiver on re-booking charges in case a customer does not want to travel on the designated date. Wadia group-owned private carrier GoAir, which was earlier offering free cancellation, has said it will now allow people to only reschedule their flights for no charge.




read

How to clean up your computer, smartphone to get them ready for life after the lockdown

Your computer, smartphones might be holding videos, photos and audio in various folders, and you would not even know that it's there. Hence, ET Wealth tells you the following methods on how to clean up your devices for more efficiency.




read

Manufacturing factories ready to roll under tough norms

After nearly a month and a half in lockdown, the country's mega manufacturing engine is taking baby steps towards opening factories, but under strict hygiene and social distancing norms.




read

Medical providers must tread carefully as elective care resumes

Officials need to be ready to react if supplies of protective gear start to run out again.




read

Readers Write: Herd immunity, reopening, Sweden, Michael Flynn, lockdown

Herd immunity has a cost.




read

Megyn Kelly interviews Biden accuser Tara Reade

The former aide who has accused Democratic presidential candidate Joe Biden of sexual assault has been interviewed by Megyn Kelly.




read

Thoroughbred Makeover Diaries Presented By Excel Equine: Horses Don’t Read The Script

Michael Wrona, the announcer at Los Alamitos Race Course and a great friend and mentor since I was a teenager and started broadcasting horse races 20 years ago, once told me, “The trouble with racehorses is they can't read scripts!” That line has stuck with me years later. It's a shame that horses don't always […]

The post Thoroughbred Makeover Diaries Presented By Excel Equine: Horses Don’t Read The Script appeared first on Horse Racing News | Paulick Report.




read

As Minneapolis homeless camp raises health alarms, officials move to contain its spread

Citing urgent public health concerns, Metro Transit authorities are moving to contain the spread of a large and growing homeless encampment near the light-rail line in south Minneapolis.




read

Mfume Says He's Ready To Confront Coronavirus Crisis

Kweisi Mfume returns to Washington in chaotic times.




read

Hey, you. Yeah, you! Stop what you’re doing RIGHT NOW and read this Stigler article on the history of robust statistics

I originally gave this post the title, “Stigler: The Changing History of Robustness,” but then I was afraid nobody would read it. In the current environment of Move Fast and Break Things, not so many people care about robustness. Also, the widespread use of robustness checks to paper over brittle conclusions has given robustness a […]




read

15 WordPress Plugins to Increase Engagement with Readers

Do you have a content-rich WordPress website that you believe will help boost your business profits? Developing a feature and content-rich website is definitely the first step, but you cannot increase your conversions if you have not maximized the engagement on your website. You need to continually work on expanding and improving user engagement so...




read

Grand Canyon Now Recognized As “StormReady” National Park

NPS employees receive StormReady award https://www.nps.gov/grca/learn/news/grand-canyon-now-recognized-as-stormready-national-park.htm




read

Ikes Fire Spreads Naturally As Crews Work To Secure Planning Area Perimeter

Warm, dry weather conditions have led to additional growth on the Ikes Fire, which is now approximately 1,535 acres and 20% contained. Smoke settled into the Grand Canyon overnight as temperatures cooled but smoke may begin to lift as temperatures warm up throughout the day. https://www.nps.gov/grca/learn/news/ikes-fire-spreads-crews-secure-planning-area-20190815.htm




read

Ready to go? poster




read

‘Gollum’ Actor Andy Serkis Plans a Live Reading of ‘The Hobbit’ –There And Back Again– Friday For Charity

The actor who played ‘Gollum’ in The Lord of the Rings, Andy Serkis, will give a LIVE reading of The Hobbit, from cover to cover, for charity May 8.

The post ‘Gollum’ Actor Andy Serkis Plans a Live Reading of ‘The Hobbit’ –There And Back Again– Friday For Charity appeared first on Good News Network.




read

8 best banana bread recipes that require no flour, butter, eggs or refined sugar

These cosy and comforting banana bread recipes are healthy, easy to make and delicious




read

Simple anywidth flyout menu with breadcrumb trail

A simple anywidth CSS flyout menu with an easy method of having a breadcrumb trail.




read

The super easy microwave peanut butter bread recipe that takes 90 seconds to cook

The quick bread recipe tastes delicious and requires just five ingredients




read

WestProPlus: A Stochastic Spreadsheet Program For The Management of All-Aged Douglas-Fir-Hemlock Forests In The Pacific Northwest

WestProPlus is an add-in program developed to work with Microsoft Excel to simulate the growth and management of all-aged Douglas-fir-western hemlock (Pseudotsuga menziesii (Mirb.) Franco-Tsuga heterophylla (Raf.) Sarg.) stands in Oregon and Washington. Its built-in growth model was calibrated from 2,706 permanent plots in the Douglas-fir-western hemlock forest type in Oregon and Washington. Stands are described by the number of trees per acre in each of nineteen 2-in diameter classes in four species groups: Douglas-fir, other shadeintolerant species, western hemlock, and other shade-tolerant species. WestProPlus allows managers to predict stand development by year and for many decades from a specific initial state. The simulations can be stochastic or deterministic. The stochastic simulations are based on bootstrapping of the observed errors in models of stand growth, timber prices, and interest rate. When used in stochastic simulations, this bootstrap technique simulates random variables by sampling randomly (with replacement) from actual observations of the variable, rather than from an assumed distribution. Users can choose cutting regimes by specifying the interval between harvests (cutting cycle) and a target distribution of trees remaining after harvest. A target distribution can be a reverse-J-shaped distribution or any other desired distribution. Diameterlimit cuts can also be simulated. Tabulated and graphic results show diameter distributions, basal area, volumes by log grade, income, net present value, and indices of stand diversity by species and size. This manual documents the program installation and activation, provides suggestions for working with Excel, and gives background information on West-ProPlus's models. It offers a comprehensive tutorial in the form of two practical examples that explain how to start the program, enter simulation data, execute a simulation, compare simulations, and plot summary statistics.




read

See Daniel Radcliffe read Harry Potter as wizard world opens new online chapter

Film star Daniel Radcliffe launches new Harry Potter at Home series with the first celebrity video reading




read

[Promo] News/Talk/Sports Radio Is Reading All Access

... about ALL ACCESS' NEWS/TALK/SPORTS section, where Editor PERRY MICHAEL SIMON delivers the most pertinent and entertaining Talk content in the business to your computer daily. You can … more




read

Homewood Public Library Awarded 2020 Baker & Taylor Summer Reading Program Grant

The Association for Library Service to Children (ALSC) has awarded the 2020 ALSC/Baker & Taylor Summer Reading Program Grant to Homewood Public Library in Homewood, Alabama.




read

KZPK (Wild Country 99)/St. Cloud, MN Launches YouTube Reading Series For Kids

LEIGHTON BROADCASTING Country KZPK (WILD COUNTRY 99)/ST. CLOUD, MN has launched the “Books with BROOK” YOUTUBE series in conjunction with SCHOLASTIC. MD/afternoon personality … more




read

Newry City footballers ready to brave the shave for charity

They are part of a wider charity effort that has so far raised £20,000 for Southern Area Hospice Services




read

Irish FA ready to start search for new Northern Ireland manager

The Association is intent on having a new boss in place by July




read

WWF - Change is already there

To celebrate it's 40th birthday, WWF-France, the first French environmental NGO, offers a new interactive sensory experience based on a parallax effect. Developed on HTML5, this photographic exhibition is organized around five main themes: species, climate change, forests, ecological footprint, oceans, fresh water. WWF invites the user to share 40 years of action through videos, photos and stories.




read

Spread the Word: Beautiful Testimonial UI Examples

Everybody wants to receive positive feedback for a job well done. That’s one reason why so many businesses include testimonials on their website. Beyond the warm and fuzzy feelings, testimonials...

The post Spread the Word: Beautiful Testimonial UI Examples appeared first on Speckyboy Design Magazine.




read

How to Add a “Reading Mode” to Your Posts

In this post, I will show you a simple way to add a distraction-free "Reading Mode" to your blog. The purpose of adding a feature like this is to enable a visitor to remove all the clutter of your site, and focus solely on the post itself. In an ideal world; there would never be a need for such a feature. In reality though, sites have numerous other goals to achieve, such as brand building, serving ads, promoting other content etc. In this way, you can compromise between the two. Do what you need when the user first arrives, but get out of the way when they decide what to read.




read

Ready to reopen? Four Cedar Rapids business leaders offer advice

On Wednesday, Gov. Kim Reynolds removed some restrictions on businesses in the 22 counties that have been seeing higher numbers of Iowans affected by COVID-19, including Linn and Johnson counties....




read

Ready to reopen? Four Cedar Rapids business leaders offer advice

On Wednesday, Gov. Kim Reynolds removed some restrictions on businesses in the 22 counties that have been seeing higher numbers of Iowans affected by COVID-19, including Linn and Johnson counties.

Now those organizations have to make decisions — on bringing back employees, services to provide and how much access to allow for customers.

And as those businesses reopen — some after more than two months — crucial steps likely will include ongoing communication with employees and customers and a well-thought-out restart plan.

The Gazette spoke with business leaders about the challenges faced by business owners as they consider how and when to open their doors.

• David Drewelow of ActionCoach Heartland in Cedar Rapids is a consultant with 19 years of business coaching experience.

• David Hensley, director of the University of Iowa’s John Pappajohn Entrepreneurial Center, has expertise in small business management during a crisis.

• Josh Seamans is vice president of Cushman and Wakefield, a global commercial real estate adviser that operates offices in more than 60 countries including China.

• Steve Shriver is a Cedar Rapids entrepreneur who operates and/or helped found four diverse enterprises, including Eco Lips and Brewhemia.

Their responses here have been condensed from lengthy individual interviews.

How important is communication and having a well-prepared plan for resumption of business?

Shriver: The one thing that has been imperative throughout this whole process is communication with employees, customers and the public. I also would recommend writing as detailed a business resumption plan as possible.

One of the main reasons is to fully understand what you are doing as this is a brand-new challenge that none of us has faced.

Drewelow: You really need to be communicating now, more than ever, with your employees, customers, vendors and suppliers. What does your plan for the next 20 to 30 days look like? What are things that you can be doing right now to get ready?

Hensley: I think it is critically important to have a reopening plan because most businesses are not going to be at full strength right away. What might their revenue forecasts look like? How can they keep their costs down as their business starts to rebound before it gets back to full capacity?

Seamans: Your plan should include a checklist of reopening steps appropriate to your type of business. Retail will have different items than distribution or industrial businesses.

You need to communicate your plan to employees, customers, landlords and lenders.

How much will fear play a role in the resumption of business?

Shriver: Everyone has a different idea of the risks involved, such as using a handle to open a door or interacting with a person — the little things that we are used to doing.

When you look at the risk versus reward of doing that, some people will be willing to go into a store and others will stay home. Some employees don’t want to come back to work yet and some people are itching to get back. You have everything in between.

Drewelow: The fear factor is huge. For the small business owner, we try to channel that fear into a focus on being highly aware of all the possibilities to mitigate concerns.

If you own a restaurant, can you post the menu online or use disposable menus? That way, a customer doesn’t have to touch something that might have been handled by someone else.

Appropriate spacing of customers within a restaurant also will help alleviate some of the fear.

Hensley: You need to communicate what steps you are taking to protect the health and safety of your employees and your customers. If you will be requiring the use of personal protective equipment like face masks, are you going to make them available?

Will limiting the number of people entering a business be difficult?

Shriver: There are not a lot of people who want to gather in masses right now. It seems like as businesses start to reopen, it will be more like a trickle.

It will be just like turning on a water spigot, with the flow of customers gradually increasing.

Hensley: I think we will see a lot more customers buying, rather than just shopping. They are going to buy the items they came for and then leave.

If businesses have more vulnerable customers, I would recommend establishing separate early morning times like many of the grocery stores have done to provide a safer environment.

Many companies have adopted using digital conferencing platforms for meetings. Will we see that trend continue?

Seamans: I think Zoom will be used for more internal meetings, so there is no need for someone to fly from, say, San Francisco to New York. But in terms of sales, it does not replicate that face-to-face interaction.

We have done work with clients that live several hours away and we have to come in for a city council meeting for a project that we are working on. That’s a three-hour drive in for a one- or two-hour council meeting and another three-hour drive back — basically an eight-hour day. If we can Zoom in and answer any questions, that’s a lot more efficient at less cost.

What should a small-business owner consider when determining how many employees to recall?

Shriver: We will be able to bring some people back to work and generate some revenue, but not in a huge way. Anybody who can work from home should continue working from home for as long as they possibly can.

We should not be rushing to get those people back. There is no incentive.

Hensley: Owners are going to be making hard decisions. Do I bring back half of my team at full time or do I bring everyone back at reduced hours? What are those implications going to be?

In some cases, other industries have been hiring and some may be making more money. Businesses may have to pay more to attract that talent back.

Restaurants have been forced to change their business model from on-premise dining to carryout and delivery. Should all owners take this opportunity to examine and update their business model?

Shriver: We took two businesses — SOKO Outfitters, a retail store, and Brewhemia, a restaurant — and put them rapidly online within a month. When we come out of this, I think we will be stronger because we will have that infrastructure in place in addition to the old school face to face traffic that we used to have.

Hensley: I think this is definitely the time to look at your business model to determine what is appropriate given the economic situation that we have. That is not just going to be critical for reopening, but over the next six months to a year as long as we are dealing with the virus.

Some business owners will see that their customers have lost their jobs or seen their income drop dramatically. They are going to be changing their patterns of consumption based on necessities.

Drewelow: Some of my clients believe that are looking their competitors and realize that some may not reopen. They are looking at whether they can merge with them or somehow salvage parts of that business.

Some business owners have realized that the way they deliver products or services will have to change. Many of my older clients have been dragged into using modern technology.




read

Concurrency & Multithreading in iOS

Concurrency is the notion of multiple things happening at the same time. This is generally achieved either via time-slicing, or truly in parallel if multiple CPU cores are available to the host operating system. We've all experienced a lack of concurrency, most likely in the form of an app freezing up when running a heavy task. UI freezes don't necessarily occur due to the absence of concurrency — they could just be symptoms of buggy software — but software that doesn't take advantage of all the computational power at its disposal is going to create these freezes whenever it needs to do something resource-intensive. If you've profiled an app hanging in this way, you'll probably see a report that looks like this:

Anything related to file I/O, data processing, or networking usually warrants a background task (unless you have a very compelling excuse to halt the entire program). There aren't many reasons that these tasks should block your user from interacting with the rest of your application. Consider how much better the user experience of your app could be if instead, the profiler reported something like this:

Analyzing an image, processing a document or a piece of audio, or writing a sizeable chunk of data to disk are examples of tasks that could benefit greatly from being delegated to background threads. Let's dig into how we can enforce such behavior into our iOS applications.


A Brief History

In the olden days, the maximum amount of work per CPU cycle that a computer could perform was determined by the clock speed. As processor designs became more compact, heat and physical constraints started becoming limiting factors for higher clock speeds. Consequentially, chip manufacturers started adding additional processor cores on each chip in order to increase total performance. By increasing the number of cores, a single chip could execute more CPU instructions per cycle without increasing its speed, size, or thermal output. There's just one problem...

How can we take advantage of these extra cores? Multithreading.

Multithreading is an implementation handled by the host operating system to allow the creation and usage of n amount of threads. Its main purpose is to provide simultaneous execution of two or more parts of a program to utilize all available CPU time. Multithreading is a powerful technique to have in a programmer's toolbelt, but it comes with its own set of responsibilities. A common misconception is that multithreading requires a multi-core processor, but this isn't the case — single-core CPUs are perfectly capable of working on many threads, but we'll take a look in a bit as to why threading is a problem in the first place. Before we dive in, let's look at the nuances of what concurrency and parallelism mean using a simple diagram:

In the first situation presented above, we observe that tasks can run concurrently, but not in parallel. This is similar to having multiple conversations in a chatroom, and interleaving (context-switching) between them, but never truly conversing with two people at the same time. This is what we call concurrency. It is the illusion of multiple things happening at the same time when in reality, they're switching very quickly. Concurrency is about dealing with lots of things at the same time. Contrast this with the parallelism model, in which both tasks run simultaneously. Both execution models exhibit multithreading, which is the involvement of multiple threads working towards one common goal. Multithreading is a generalized technique for introducing a combination of concurrency and parallelism into your program.


The Burden of Threads

A modern multitasking operating system like iOS has hundreds of programs (or processes) running at any given moment. However, most of these programs are either system daemons or background processes that have very low memory footprint, so what is really needed is a way for individual applications to make use of the extra cores available. An application (process) can have many threads (sub-processes) operating on shared memory. Our goal is to be able to control these threads and use them to our advantage.

Historically, introducing concurrency to an app has required the creation of one or more threads. Threads are low-level constructs that need to be managed manually. A quick skim through Apple's Threaded Programming Guide is all it takes to see how much complexity threaded code adds to a codebase. In addition to building an app, the developer has to:

  • Responsibly create new threads, adjusting that number dynamically as system conditions change
  • Manage them carefully, deallocating them from memory once they have finished executing
  • Leverage synchronization mechanisms like mutexes, locks, and semaphores to orchestrate resource access between threads, adding even more overhead to application code
  • Mitigate risks associated with coding an application that assumes most of the costs associated with creating and maintaining any threads it uses, and not the host OS

This is unfortunate, as it adds enormous levels of complexity and risk without any guarantees of improved performance.


Grand Central Dispatch

iOS takes an asynchronous approach to solving the concurrency problem of managing threads. Asynchronous functions are common in most programming environments, and are often used to initiate tasks that might take a long time, like reading a file from the disk, or downloading a file from the web. When invoked, an asynchronous function executes some work behind the scenes to start a background task, but returns immediately, regardless of how long the original task might takes to actually complete.

A core technology that iOS provides for starting tasks asynchronously is Grand Central Dispatch (or GCD for short). GCD abstracts away thread management code and moves it down to the system level, exposing a light API to define tasks and execute them on an appropriate dispatch queue. GCD takes care of all thread management and scheduling, providing a holistic approach to task management and execution, while also providing better efficiency than traditional threads.

Let's take a look at the main components of GCD:

What've we got here? Let's start from the left:

  • DispatchQueue.main: The main thread, or the UI thread, is backed by a single serial queue. All tasks are executed in succession, so it is guaranteed that the order of execution is preserved. It is crucial that you ensure all UI updates are designated to this queue, and that you never run any blocking tasks on it. We want to ensure that the app's run loop (called CFRunLoop) is never blocked in order to maintain the highest framerate. Subsequently, the main queue has the highest priority, and any tasks pushed onto this queue will get executed immediately.
  • DispatchQueue.global: A set of global concurrent queues, each of which manage their own pool of threads. Depending on the priority of your task, you can specify which specific queue to execute your task on, although you should resort to using default most of the time. Because tasks on these queues are executed concurrently, it doesn't guarantee preservation of the order in which tasks were queued.

Notice how we're not dealing with individual threads anymore? We're dealing with queues which manage a pool of threads internally, and you will shortly see why queues are a much more sustainable approach to multhreading.

Serial Queues: The Main Thread

As an exercise, let's look at a snippet of code below, which gets fired when the user presses a button in the app. The expensive compute function can be anything. Let's pretend it is post-processing an image stored on the device.

import UIKit

class ViewController: UIViewController {
    @IBAction func handleTap(_ sender: Any) {
        compute()
    }

    private func compute() -> Void {
        // Pretending to post-process a large image.
        var counter = 0
        for _ in 0..<9999999 {
            counter += 1
        }
    }
}

At first glance, this may look harmless, but if you run this inside of a real app, the UI will freeze completely until the loop is terminated, which will take... a while. We can prove it by profiling this task in Instruments. You can fire up the Time Profiler module of Instruments by going to Xcode > Open Developer Tool > Instruments in Xcode's menu options. Let's look at the Threads module of the profiler and see where the CPU usage is highest.

We can see that the Main Thread is clearly at 100% capacity for almost 5 seconds. That's a non-trivial amount of time to block the UI. Looking at the call tree below the chart, we can see that the Main Thread is at 99.9% capacity for 4.43 seconds! Given that a serial queue works in a FIFO manner, tasks will always complete in the order in which they were inserted. Clearly the compute() method is the culprit here. Can you imagine clicking a button just to have the UI freeze up on you for that long?

Background Threads

How can we make this better? DispatchQueue.global() to the rescue! This is where background threads come in. Referring to the GCD architecture diagram above, we can see that anything that is not the Main Thread is a background thread in iOS. They can run alongside the Main Thread, leaving it fully unoccupied and ready to handle other UI events like scrolling, responding to user events, animating etc. Let's make a small change to our button click handler above:

class ViewController: UIViewController {
    @IBAction func handleTap(_ sender: Any) {
        DispatchQueue.global(qos: .userInitiated).async { [unowned self] in
            self.compute()
        }
    }

    private func compute() -> Void {
        // Pretending to post-process a large image.
        var counter = 0
        for _ in 0..<9999999 {
            counter += 1
        }
    }
}

Unless specified, a snippet of code will usually default to execute on the Main Queue, so in order to force it to execute on a different thread, we'll wrap our compute call inside of an asynchronous closure that gets submitted to the DispatchQueue.global queue. Keep in mind that we aren't really managing threads here. We're submitting tasks (in the form of closures or blocks) to the desired queue with the assumption that it is guaranteed to execute at some point in time. The queue decides which thread to allocate the task to, and it does all the hard work of assessing system requirements and managing the actual threads. This is the magic of Grand Central Dispatch. As the old adage goes, you can't improve what you can't measure. So we measured our truly terrible button click handler, and now that we've improved it, we'll measure it once again to get some concrete data with regards to performance.

Looking at the profiler again, it's quite clear to us that this is a huge improvement. The task takes an identical amount of time, but this time, it's happening in the background without locking up the UI. Even though our app is doing the same amount of work, the perceived performance is much better because the user will be free to do other things while the app is processing.

You may have noticed that we accessed a global queue of .userInitiated priority. This is an attribute we can use to give our tasks a sense of urgency. If we run the same task on a global queue of and pass it a qos attribute of background , iOS will think it's a utility task, and thus allocate fewer resources to execute it. So, while we don't have control over when our tasks get executed, we do have control over their priority.

A Note on Main Thread vs. Main Queue

You might be wondering why the Profiler shows "Main Thread" and why we're referring to it as the "Main Queue". If you refer back to the GCD architecture we described above, the Main Queue is solely responsible for managing the Main Thread. The Dispatch Queues section in the Concurrency Programming Guide says that "the main dispatch queue is a globally available serial queue that executes tasks on the application’s main thread. Because it runs on your application’s main thread, the main queue is often used as a key synchronization point for an application."

The terms "execute on the Main Thread" and "execute on the Main Queue" can be used interchangeably.


Concurrent Queues

So far, our tasks have been executed exclusively in a serial manner. DispatchQueue.main is by default a serial queue, and DispatchQueue.global gives you four concurrent dispatch queues depending on the priority parameter you pass in.

Let's say we want to take five images, and have our app process them all in parallel on background threads. How would we go about doing that? We can spin up a custom concurrent queue with an identifier of our choosing, and allocate those tasks there. All that's required is the .concurrent attribute during the construction of the queue.

class ViewController: UIViewController {
    let queue = DispatchQueue(label: "com.app.concurrentQueue", attributes: .concurrent)
    let images: [UIImage] = [UIImage].init(repeating: UIImage(), count: 5)

    @IBAction func handleTap(_ sender: Any) {
        for img in images {
            queue.async { [unowned self] in
                self.compute(img)
            }
        }
    }

    private func compute(_ img: UIImage) -> Void {
        // Pretending to post-process a large image.
        var counter = 0
        for _ in 0..<9999999 {
            counter += 1
        }
    }
}

Running that through the profiler, we can see that the app is now spinning up 5 discrete threads to parallelize a for-loop.

Parallelization of N Tasks

So far, we've looked at pushing computationally expensive task(s) onto background threads without clogging up the UI thread. But what about executing parallel tasks with some restrictions? How can Spotify download multiple songs in parallel, while limiting the maximum number up to 3? We can go about this in a few ways, but this is a good time to explore another important construct in multithreaded programming: semaphores.

Semaphores are signaling mechanisms. They are commonly used to control access to a shared resource. Imagine a scenario where a thread can lock access to a certain section of the code while it executes it, and unlocks after it's done to let other threads execute the said section of the code. You would see this type of behavior in database writes and reads, for example. What if you want only one thread writing to a database and preventing any reads during that time? This is a common concern in thread-safety called Readers-writer lock. Semaphores can be used to control concurrency in our app by allowing us to lock n number of threads.

let kMaxConcurrent = 3 // Or 1 if you want strictly ordered downloads!
let semaphore = DispatchSemaphore(value: kMaxConcurrent)
let downloadQueue = DispatchQueue(label: "com.app.downloadQueue", attributes: .concurrent)

class ViewController: UIViewController {
    @IBAction func handleTap(_ sender: Any) {
        for i in 0..<15 {
            downloadQueue.async { [unowned self] in
                // Lock shared resource access
                semaphore.wait()

                // Expensive task
                self.download(i + 1)

                // Update the UI on the main thread, always!
                DispatchQueue.main.async {
                    tableView.reloadData()

                    // Release the lock
                    semaphore.signal()
                }
            }
        }
    }

    func download(_ songId: Int) -> Void {
        var counter = 0

        // Simulate semi-random download times.
        for _ in 0..<Int.random(in: 999999...10000000) {
            counter += songId
        }
    }
}

Notice how we've effectively restricted our download system to limit itself to k number of downloads. The moment one download finishes (or thread is done executing), it decrements the semaphore, allowing the managing queue to spawn another thread and start downloading another song. You can apply a similar pattern to database transactions when dealing with concurrent reads and writes.

Semaphores usually aren't necessary for code like the one in our example, but they become more powerful when you need to enforce synchronous behavior whille consuming an asynchronous API. The above could would work just as well with a custom NSOperationQueue with a maxConcurrentOperationCount, but it's a worthwhile tangent regardless.


Finer Control with OperationQueue

GCD is great when you want to dispatch one-off tasks or closures into a queue in a 'set-it-and-forget-it' fashion, and it provides a very lightweight way of doing so. But what if we want to create a repeatable, structured, long-running task that produces associated state or data? And what if we want to model this chain of operations such that they can be cancelled, suspended and tracked, while still working with a closure-friendly API? Imagine an operation like this:

This would be quite cumbersome to achieve with GCD. We want a more modular way of defining a group of tasks while maintaining readability and also exposing a greater amount of control. In this case, we can use Operation objects and queue them onto an OperationQueue, which is a high-level wrapper around DispatchQueue. Let's look at some of the benefits of using these abstractions and what they offer in comparison to the lower-level GCI API:

  • You may want to create dependencies between tasks, and while you could do this via GCD, you're better off defining them concretely as Operation objects, or units of work, and pushing them onto your own queue. This would allow for maximum reusability since you may use the same pattern elsewhere in an application.
  • The Operation and OperationQueue classes have a number of properties that can be observed, using KVO (Key Value Observing). This is another important benefit if you want to monitor the state of an operation or operation queue.
  • Operations can be paused, resumed, and cancelled. Once you dispatch a task using Grand Central Dispatch, you no longer have control or insight into the execution of that task. The Operation API is more flexible in that respect, giving the developer control over the operation's life cycle.
  • OperationQueue allows you to specify the maximum number of queued operations that can run simultaneously, giving you a finer degree of control over the concurrency aspects.

The usage of Operation and OperationQueue could fill an entire blog post, but let's look at a quick example of what modeling dependencies looks like. (GCD can also create dependencies, but you're better off dividing up large tasks into a series of composable sub-tasks.) In order to create a chain of operations that depend on one another, we could do something like this:

class ViewController: UIViewController {
    var queue = OperationQueue()
    var rawImage = UIImage? = nil
    let imageUrl = URL(string: "https://example.com/portrait.jpg")!
    @IBOutlet weak var imageView: UIImageView!

    let downloadOperation = BlockOperation {
        let image = Downloader.downloadImageWithURL(url: imageUrl)
        OperationQueue.main.async {
            self.rawImage = image
        }
    }

    let filterOperation = BlockOperation {
        let filteredImage = ImgProcessor.addGaussianBlur(self.rawImage)
        OperationQueue.main.async {
            self.imageView = filteredImage
        }
    }

    filterOperation.addDependency(downloadOperation)

    [downloadOperation, filterOperation].forEach {
        queue.addOperation($0)
     }
}

So why not opt for a higher level abstraction and avoid using GCD entirely? While GCD is ideal for inline asynchronous processing, Operation provides a more comprehensive, object-oriented model of computation for encapsulating all of the data around structured, repeatable tasks in an application. Developers should use the highest level of abstraction possible for any given problem, and for scheduling consistent, repeated work, that abstraction is Operation. Other times, it makes more sense to sprinkle in some GCD for one-off tasks or closures that we want to fire. We can mix both OperationQueue and GCD to get the best of both worlds.


The Cost of Concurrency

DispatchQueue and friends are meant to make it easier for the application developer to execute code concurrently. However, these technologies do not guarantee improvements to the efficiency or responsiveness in an application. It is up to you to use queues in a manner that is both effective and does not impose an undue burden on other resources. For example, it's totally viable to create 10,000 tasks and submit them to a queue, but doing so would allocate a nontrivial amount of memory and introduce a lot of overhead for the allocation and deallocation of operation blocks. This is the opposite of what you want! It's best to profile your app thoroughly to ensure that concurrency is enhancing your app's performance and not degrading it.

We've talked about how concurrency comes at a cost in terms of complexity and allocation of system resources, but introducing concurrency also brings a host of other risks like:

  • Deadlock: A situation where a thread locks a critical portion of the code and can halt the application's run loop entirely. In the context of GCD, you should be very careful when using the dispatchQueue.sync { } calls as you could easily get yourself in situations where two synchronous operations can get stuck waiting for each other.
  • Priority Inversion: A condition where a lower priority task blocks a high priority task from executing, which effectively inverts their priorities. GCD allows for different levels of priority on its background queues, so this is quite easily a possibility.
  • Producer-Consumer Problem: A race condition where one thread is creating a data resource while another thread is accessing it. This is a synchronization problem, and can be solved using locks, semaphores, serial queues, or a barrier dispatch if you're using concurrent queues in GCD.
  • ...and many other sorts of locking and data-race conditions that are hard to debug! Thread safety is of the utmost concern when dealing with concurrency.

Parting Thoughts + Further Reading

If you've made it this far, I applaud you. Hopefully this article gives you a lay of the land when it comes to multithreading techniques on iOS, and how you can use some of them in your app. We didn't get to cover many of the lower-level constructs like locks, mutexes and how they help us achieve synchronization, nor did we get to dive into concrete examples of how concurrency can hurt your app. We'll save those for another day, but you can dig into some additional reading and videos if you're eager to dive deeper.




read

Concurrency & Multithreading in iOS

Concurrency is the notion of multiple things happening at the same time. This is generally achieved either via time-slicing, or truly in parallel if multiple CPU cores are available to the host operating system. We've all experienced a lack of concurrency, most likely in the form of an app freezing up when running a heavy task. UI freezes don't necessarily occur due to the absence of concurrency — they could just be symptoms of buggy software — but software that doesn't take advantage of all the computational power at its disposal is going to create these freezes whenever it needs to do something resource-intensive. If you've profiled an app hanging in this way, you'll probably see a report that looks like this:

Anything related to file I/O, data processing, or networking usually warrants a background task (unless you have a very compelling excuse to halt the entire program). There aren't many reasons that these tasks should block your user from interacting with the rest of your application. Consider how much better the user experience of your app could be if instead, the profiler reported something like this:

Analyzing an image, processing a document or a piece of audio, or writing a sizeable chunk of data to disk are examples of tasks that could benefit greatly from being delegated to background threads. Let's dig into how we can enforce such behavior into our iOS applications.


A Brief History

In the olden days, the maximum amount of work per CPU cycle that a computer could perform was determined by the clock speed. As processor designs became more compact, heat and physical constraints started becoming limiting factors for higher clock speeds. Consequentially, chip manufacturers started adding additional processor cores on each chip in order to increase total performance. By increasing the number of cores, a single chip could execute more CPU instructions per cycle without increasing its speed, size, or thermal output. There's just one problem...

How can we take advantage of these extra cores? Multithreading.

Multithreading is an implementation handled by the host operating system to allow the creation and usage of n amount of threads. Its main purpose is to provide simultaneous execution of two or more parts of a program to utilize all available CPU time. Multithreading is a powerful technique to have in a programmer's toolbelt, but it comes with its own set of responsibilities. A common misconception is that multithreading requires a multi-core processor, but this isn't the case — single-core CPUs are perfectly capable of working on many threads, but we'll take a look in a bit as to why threading is a problem in the first place. Before we dive in, let's look at the nuances of what concurrency and parallelism mean using a simple diagram:

In the first situation presented above, we observe that tasks can run concurrently, but not in parallel. This is similar to having multiple conversations in a chatroom, and interleaving (context-switching) between them, but never truly conversing with two people at the same time. This is what we call concurrency. It is the illusion of multiple things happening at the same time when in reality, they're switching very quickly. Concurrency is about dealing with lots of things at the same time. Contrast this with the parallelism model, in which both tasks run simultaneously. Both execution models exhibit multithreading, which is the involvement of multiple threads working towards one common goal. Multithreading is a generalized technique for introducing a combination of concurrency and parallelism into your program.


The Burden of Threads

A modern multitasking operating system like iOS has hundreds of programs (or processes) running at any given moment. However, most of these programs are either system daemons or background processes that have very low memory footprint, so what is really needed is a way for individual applications to make use of the extra cores available. An application (process) can have many threads (sub-processes) operating on shared memory. Our goal is to be able to control these threads and use them to our advantage.

Historically, introducing concurrency to an app has required the creation of one or more threads. Threads are low-level constructs that need to be managed manually. A quick skim through Apple's Threaded Programming Guide is all it takes to see how much complexity threaded code adds to a codebase. In addition to building an app, the developer has to:

  • Responsibly create new threads, adjusting that number dynamically as system conditions change
  • Manage them carefully, deallocating them from memory once they have finished executing
  • Leverage synchronization mechanisms like mutexes, locks, and semaphores to orchestrate resource access between threads, adding even more overhead to application code
  • Mitigate risks associated with coding an application that assumes most of the costs associated with creating and maintaining any threads it uses, and not the host OS

This is unfortunate, as it adds enormous levels of complexity and risk without any guarantees of improved performance.


Grand Central Dispatch

iOS takes an asynchronous approach to solving the concurrency problem of managing threads. Asynchronous functions are common in most programming environments, and are often used to initiate tasks that might take a long time, like reading a file from the disk, or downloading a file from the web. When invoked, an asynchronous function executes some work behind the scenes to start a background task, but returns immediately, regardless of how long the original task might takes to actually complete.

A core technology that iOS provides for starting tasks asynchronously is Grand Central Dispatch (or GCD for short). GCD abstracts away thread management code and moves it down to the system level, exposing a light API to define tasks and execute them on an appropriate dispatch queue. GCD takes care of all thread management and scheduling, providing a holistic approach to task management and execution, while also providing better efficiency than traditional threads.

Let's take a look at the main components of GCD:

What've we got here? Let's start from the left:

  • DispatchQueue.main: The main thread, or the UI thread, is backed by a single serial queue. All tasks are executed in succession, so it is guaranteed that the order of execution is preserved. It is crucial that you ensure all UI updates are designated to this queue, and that you never run any blocking tasks on it. We want to ensure that the app's run loop (called CFRunLoop) is never blocked in order to maintain the highest framerate. Subsequently, the main queue has the highest priority, and any tasks pushed onto this queue will get executed immediately.
  • DispatchQueue.global: A set of global concurrent queues, each of which manage their own pool of threads. Depending on the priority of your task, you can specify which specific queue to execute your task on, although you should resort to using default most of the time. Because tasks on these queues are executed concurrently, it doesn't guarantee preservation of the order in which tasks were queued.

Notice how we're not dealing with individual threads anymore? We're dealing with queues which manage a pool of threads internally, and you will shortly see why queues are a much more sustainable approach to multhreading.

Serial Queues: The Main Thread

As an exercise, let's look at a snippet of code below, which gets fired when the user presses a button in the app. The expensive compute function can be anything. Let's pretend it is post-processing an image stored on the device.

import UIKit

class ViewController: UIViewController {
    @IBAction func handleTap(_ sender: Any) {
        compute()
    }

    private func compute() -> Void {
        // Pretending to post-process a large image.
        var counter = 0
        for _ in 0..<9999999 {
            counter += 1
        }
    }
}

At first glance, this may look harmless, but if you run this inside of a real app, the UI will freeze completely until the loop is terminated, which will take... a while. We can prove it by profiling this task in Instruments. You can fire up the Time Profiler module of Instruments by going to Xcode > Open Developer Tool > Instruments in Xcode's menu options. Let's look at the Threads module of the profiler and see where the CPU usage is highest.

We can see that the Main Thread is clearly at 100% capacity for almost 5 seconds. That's a non-trivial amount of time to block the UI. Looking at the call tree below the chart, we can see that the Main Thread is at 99.9% capacity for 4.43 seconds! Given that a serial queue works in a FIFO manner, tasks will always complete in the order in which they were inserted. Clearly the compute() method is the culprit here. Can you imagine clicking a button just to have the UI freeze up on you for that long?

Background Threads

How can we make this better? DispatchQueue.global() to the rescue! This is where background threads come in. Referring to the GCD architecture diagram above, we can see that anything that is not the Main Thread is a background thread in iOS. They can run alongside the Main Thread, leaving it fully unoccupied and ready to handle other UI events like scrolling, responding to user events, animating etc. Let's make a small change to our button click handler above:

class ViewController: UIViewController {
    @IBAction func handleTap(_ sender: Any) {
        DispatchQueue.global(qos: .userInitiated).async { [unowned self] in
            self.compute()
        }
    }

    private func compute() -> Void {
        // Pretending to post-process a large image.
        var counter = 0
        for _ in 0..<9999999 {
            counter += 1
        }
    }
}

Unless specified, a snippet of code will usually default to execute on the Main Queue, so in order to force it to execute on a different thread, we'll wrap our compute call inside of an asynchronous closure that gets submitted to the DispatchQueue.global queue. Keep in mind that we aren't really managing threads here. We're submitting tasks (in the form of closures or blocks) to the desired queue with the assumption that it is guaranteed to execute at some point in time. The queue decides which thread to allocate the task to, and it does all the hard work of assessing system requirements and managing the actual threads. This is the magic of Grand Central Dispatch. As the old adage goes, you can't improve what you can't measure. So we measured our truly terrible button click handler, and now that we've improved it, we'll measure it once again to get some concrete data with regards to performance.

Looking at the profiler again, it's quite clear to us that this is a huge improvement. The task takes an identical amount of time, but this time, it's happening in the background without locking up the UI. Even though our app is doing the same amount of work, the perceived performance is much better because the user will be free to do other things while the app is processing.

You may have noticed that we accessed a global queue of .userInitiated priority. This is an attribute we can use to give our tasks a sense of urgency. If we run the same task on a global queue of and pass it a qos attribute of background , iOS will think it's a utility task, and thus allocate fewer resources to execute it. So, while we don't have control over when our tasks get executed, we do have control over their priority.

A Note on Main Thread vs. Main Queue

You might be wondering why the Profiler shows "Main Thread" and why we're referring to it as the "Main Queue". If you refer back to the GCD architecture we described above, the Main Queue is solely responsible for managing the Main Thread. The Dispatch Queues section in the Concurrency Programming Guide says that "the main dispatch queue is a globally available serial queue that executes tasks on the application’s main thread. Because it runs on your application’s main thread, the main queue is often used as a key synchronization point for an application."

The terms "execute on the Main Thread" and "execute on the Main Queue" can be used interchangeably.


Concurrent Queues

So far, our tasks have been executed exclusively in a serial manner. DispatchQueue.main is by default a serial queue, and DispatchQueue.global gives you four concurrent dispatch queues depending on the priority parameter you pass in.

Let's say we want to take five images, and have our app process them all in parallel on background threads. How would we go about doing that? We can spin up a custom concurrent queue with an identifier of our choosing, and allocate those tasks there. All that's required is the .concurrent attribute during the construction of the queue.

class ViewController: UIViewController {
    let queue = DispatchQueue(label: "com.app.concurrentQueue", attributes: .concurrent)
    let images: [UIImage] = [UIImage].init(repeating: UIImage(), count: 5)

    @IBAction func handleTap(_ sender: Any) {
        for img in images {
            queue.async { [unowned self] in
                self.compute(img)
            }
        }
    }

    private func compute(_ img: UIImage) -> Void {
        // Pretending to post-process a large image.
        var counter = 0
        for _ in 0..<9999999 {
            counter += 1
        }
    }
}

Running that through the profiler, we can see that the app is now spinning up 5 discrete threads to parallelize a for-loop.

Parallelization of N Tasks

So far, we've looked at pushing computationally expensive task(s) onto background threads without clogging up the UI thread. But what about executing parallel tasks with some restrictions? How can Spotify download multiple songs in parallel, while limiting the maximum number up to 3? We can go about this in a few ways, but this is a good time to explore another important construct in multithreaded programming: semaphores.

Semaphores are signaling mechanisms. They are commonly used to control access to a shared resource. Imagine a scenario where a thread can lock access to a certain section of the code while it executes it, and unlocks after it's done to let other threads execute the said section of the code. You would see this type of behavior in database writes and reads, for example. What if you want only one thread writing to a database and preventing any reads during that time? This is a common concern in thread-safety called Readers-writer lock. Semaphores can be used to control concurrency in our app by allowing us to lock n number of threads.

let kMaxConcurrent = 3 // Or 1 if you want strictly ordered downloads!
let semaphore = DispatchSemaphore(value: kMaxConcurrent)
let downloadQueue = DispatchQueue(label: "com.app.downloadQueue", attributes: .concurrent)

class ViewController: UIViewController {
    @IBAction func handleTap(_ sender: Any) {
        for i in 0..<15 {
            downloadQueue.async { [unowned self] in
                // Lock shared resource access
                semaphore.wait()

                // Expensive task
                self.download(i + 1)

                // Update the UI on the main thread, always!
                DispatchQueue.main.async {
                    tableView.reloadData()

                    // Release the lock
                    semaphore.signal()
                }
            }
        }
    }

    func download(_ songId: Int) -> Void {
        var counter = 0

        // Simulate semi-random download times.
        for _ in 0..<Int.random(in: 999999...10000000) {
            counter += songId
        }
    }
}

Notice how we've effectively restricted our download system to limit itself to k number of downloads. The moment one download finishes (or thread is done executing), it decrements the semaphore, allowing the managing queue to spawn another thread and start downloading another song. You can apply a similar pattern to database transactions when dealing with concurrent reads and writes.

Semaphores usually aren't necessary for code like the one in our example, but they become more powerful when you need to enforce synchronous behavior whille consuming an asynchronous API. The above could would work just as well with a custom NSOperationQueue with a maxConcurrentOperationCount, but it's a worthwhile tangent regardless.


Finer Control with OperationQueue

GCD is great when you want to dispatch one-off tasks or closures into a queue in a 'set-it-and-forget-it' fashion, and it provides a very lightweight way of doing so. But what if we want to create a repeatable, structured, long-running task that produces associated state or data? And what if we want to model this chain of operations such that they can be cancelled, suspended and tracked, while still working with a closure-friendly API? Imagine an operation like this:

This would be quite cumbersome to achieve with GCD. We want a more modular way of defining a group of tasks while maintaining readability and also exposing a greater amount of control. In this case, we can use Operation objects and queue them onto an OperationQueue, which is a high-level wrapper around DispatchQueue. Let's look at some of the benefits of using these abstractions and what they offer in comparison to the lower-level GCI API:

  • You may want to create dependencies between tasks, and while you could do this via GCD, you're better off defining them concretely as Operation objects, or units of work, and pushing them onto your own queue. This would allow for maximum reusability since you may use the same pattern elsewhere in an application.
  • The Operation and OperationQueue classes have a number of properties that can be observed, using KVO (Key Value Observing). This is another important benefit if you want to monitor the state of an operation or operation queue.
  • Operations can be paused, resumed, and cancelled. Once you dispatch a task using Grand Central Dispatch, you no longer have control or insight into the execution of that task. The Operation API is more flexible in that respect, giving the developer control over the operation's life cycle.
  • OperationQueue allows you to specify the maximum number of queued operations that can run simultaneously, giving you a finer degree of control over the concurrency aspects.

The usage of Operation and OperationQueue could fill an entire blog post, but let's look at a quick example of what modeling dependencies looks like. (GCD can also create dependencies, but you're better off dividing up large tasks into a series of composable sub-tasks.) In order to create a chain of operations that depend on one another, we could do something like this:

class ViewController: UIViewController {
    var queue = OperationQueue()
    var rawImage = UIImage? = nil
    let imageUrl = URL(string: "https://example.com/portrait.jpg")!
    @IBOutlet weak var imageView: UIImageView!

    let downloadOperation = BlockOperation {
        let image = Downloader.downloadImageWithURL(url: imageUrl)
        OperationQueue.main.async {
            self.rawImage = image
        }
    }

    let filterOperation = BlockOperation {
        let filteredImage = ImgProcessor.addGaussianBlur(self.rawImage)
        OperationQueue.main.async {
            self.imageView = filteredImage
        }
    }

    filterOperation.addDependency(downloadOperation)

    [downloadOperation, filterOperation].forEach {
        queue.addOperation($0)
     }
}

So why not opt for a higher level abstraction and avoid using GCD entirely? While GCD is ideal for inline asynchronous processing, Operation provides a more comprehensive, object-oriented model of computation for encapsulating all of the data around structured, repeatable tasks in an application. Developers should use the highest level of abstraction possible for any given problem, and for scheduling consistent, repeated work, that abstraction is Operation. Other times, it makes more sense to sprinkle in some GCD for one-off tasks or closures that we want to fire. We can mix both OperationQueue and GCD to get the best of both worlds.


The Cost of Concurrency

DispatchQueue and friends are meant to make it easier for the application developer to execute code concurrently. However, these technologies do not guarantee improvements to the efficiency or responsiveness in an application. It is up to you to use queues in a manner that is both effective and does not impose an undue burden on other resources. For example, it's totally viable to create 10,000 tasks and submit them to a queue, but doing so would allocate a nontrivial amount of memory and introduce a lot of overhead for the allocation and deallocation of operation blocks. This is the opposite of what you want! It's best to profile your app thoroughly to ensure that concurrency is enhancing your app's performance and not degrading it.

We've talked about how concurrency comes at a cost in terms of complexity and allocation of system resources, but introducing concurrency also brings a host of other risks like:

  • Deadlock: A situation where a thread locks a critical portion of the code and can halt the application's run loop entirely. In the context of GCD, you should be very careful when using the dispatchQueue.sync { } calls as you could easily get yourself in situations where two synchronous operations can get stuck waiting for each other.
  • Priority Inversion: A condition where a lower priority task blocks a high priority task from executing, which effectively inverts their priorities. GCD allows for different levels of priority on its background queues, so this is quite easily a possibility.
  • Producer-Consumer Problem: A race condition where one thread is creating a data resource while another thread is accessing it. This is a synchronization problem, and can be solved using locks, semaphores, serial queues, or a barrier dispatch if you're using concurrent queues in GCD.
  • ...and many other sorts of locking and data-race conditions that are hard to debug! Thread safety is of the utmost concern when dealing with concurrency.

Parting Thoughts + Further Reading

If you've made it this far, I applaud you. Hopefully this article gives you a lay of the land when it comes to multithreading techniques on iOS, and how you can use some of them in your app. We didn't get to cover many of the lower-level constructs like locks, mutexes and how they help us achieve synchronization, nor did we get to dive into concrete examples of how concurrency can hurt your app. We'll save those for another day, but you can dig into some additional reading and videos if you're eager to dive deeper.




read

How to – Create a Pair of Reading Glasses Icon

In today’s tutorial, we’re going to take a quick look behind the process of creating a pair of reading glasses icon, and see how we can take some simple shapes and turn them into a finished usable product. So, assuming you already have the software running, let’s jump straight into it! Tutorial Details: Reading Glasses […]

The post How to – Create a Pair of Reading Glasses Icon appeared first on Vectips.




read

Best Photos of 2017 by JMG-Galleries Blog Readers

Get ready to start 2018 off on the right foot with some creative inspiration. The results of my 11th annual Best of Photos project hopefully will provide just that by introducing you to photographers and their work from all over the world. Get ready to travel around the world in 100+ links. For those who are new to my blog project, photographers taking part span the gamut of photo enthusiasts to professionals. The great thing about photography is that no matter what your skill level we all can relate equally in our love for the art of photography and visually exploring. With that in mind I encourage you to reach out to photographers whose work you enjoy to keep sharing & growing as an artist.  I am incredibly thankful that this tradition has been embraced and enjoy seeing how familiar faces have evolved their work & grown over the years.  I hope reviewing your best photos of the year and comparing them to years pasts keeps you inspired and aware of your progress as a photographer. If you’d like to take part next year and be informed when submissions open for the “Best Photos of 2017? blog project add your name to my mail list. You won’t be spammed. I send out newsletters quite infrequently. Thank to everyone who took part!  I invite you to visit each link below as I have and introduce yourself to many of the participating photographers. Best Photos of 2017 Jim M. Goldstein – Best Photos of 2017 by Jim M. Goldstein Randy Langstraat – My Ten Favorite Photos of 2017 Michael Russell – My Top 10 Photos of 2017 Phil Colla – Best Natural History Photos of 2017 Greg Russell | Alpenglow Images – 2017 year in review Mike Matenkosky – My Favorite Photos from 2017 Khürt Williams – 2017 Favourites Carl Donohue – Expeditions Alaska Kevin Ly – Kevin Ly | Best of 2017 Martin Quinn – Quinn Images – Best of 2017 Robin Mayoff – RHM Images Best of 2017 Craig L. Howe – On the Move Johann A. Briffa – 2017: A Photographic Retrospective Harold Davis – Harold Davis—My Best of 2017 Denise Goldberg – top photos :: 2017 William Bean – Bill’s Blog Greg Clure – Best Images of 2017 Rick Holliday – Best Images of 2017 Peter Carroll – Peter Carroll – Favourites of 2017 Mike Chowla – My 10 Best Photos of 2017 Wendy M. Seagren – wendy seagrens best photography 2017 QT Luong – 2017 in Review, Favorites, and Seasons Greetings Jenni Brehm – Changing Perspectives Rachel Cohen – Rachel Cohen Photography Brian Knott (FMKphoto) – 2017 year in review Shikha Shrivastava – My favorite photos of 2017 Dave Wilson – Dave Wilson Photography – Best of 2017 Larry Millican – Millican Photography Alexander S. Kunz – My Favorite Photos from 2017 Mark Duffy – 500px Stefan Baeurle – Top 10 Favorites of 2017 Adrian Klein – Favorite Photos of 2017 Alan Majchrowicz – Photo Highlights 2017 Russ Bishop – Russ Bishop Photography | 2017 – The Year in Pictures Todd Henson – Best Photos of 2017: My Favorites of the Year Peter Tellone – My 2017 Top Ten Best Images Aaron Hockley – thisGruntled – Best Photos of 2017 Tony Wu – Favorite Photos of 2017 T.M. Schultze – T.M. Schultze Website Andrew S. Gibson – My Favorite Photos From 2017 John Pemberton – JPSquared – Images of 2017 Scott Thompson – Scott Shots Photography’s Top 10 Tahoe photos of 2017 ElDuro Tuco – ElDuro Tuco The DarkSlides – The DarkSlides Jon McCormack – From Ancient Cities to Endangered Animals – 2017 in Photographs Fred Mertz Photography – Fred Mertz Photography Richard Valenti – Richard Valenti Photography Jeff Hubbard – My Favorite Photos of 2017 Andrew Scharlot – 2017 Best Pictures Deb Snelson – Favorite Photos of 2017 Richard Wong – Favorite Photos From 2017 – Richard Wong Caleb Weston – Dubland Gary Crabbe / Enlightened Images – My Favorite Landscape Photos of 2017 – A Year-End Retrospective Tom Whelan – Nature Diary Robert Varley – Robert Varley Kyle Jones – Favorites from 2017 Neil Creek – Neil Creek – Photographer tim fiddimore – North Devon 2017 Richard Murphy Photography – Best of 2017 Alan Dahl – Favorites of 2017 Gabor Ruff – Natural History Photography – Highlights from 2017 Kevin Ebi – Living Wilderness: Best of 2017 Clint Losee – 10 Best Landscape and Scenic Photos of 2017 Mark Hespenheide – Best of ’17 Ilias Katsouras – Okrivadas David J Grenier – 2017 Top 12 Photographs J. J. RAIA – 2017 Jim Goldstein Project Rob Tilley – Best of 2017 – My Favorite Images of the Year Björn Göhringer – Top 14 From 2017 Bernt-Inge Madsen – Bernt-Inge.com USKestrel Photography (Pete Miller) – My favorite images of 2017: A Different Perspective Milan Hutera – 2017 in Pictures Fred Murphy – Fred Murphy Photography Harry Hitzeman – My Top Photographs of 2017 Andrew Thomas – Best of 2017 – Aerials Dean Foster – 2017: Year in Review Simon Ng – 2017 A Year of Water Michael Katz – Michael Katz Photography Drake Dyck – Top Ten (favourite) Images of 2017 Jose Manuel Santos – The Magnificent Douro Valley Gary Buzel – Gary Buzel Studios Bryan William Jones – Top Photos of 2017 Peter Knott – 2017 Favourites Kamala Venkatesh – Kamala Venkatesh Jason Frye – My Top 10 of 2017 Jackson Frishman – Favorites of 2017 Thomas Yackley – Top Ten Landscape and Nature Photos of 2017 Mark Graf – 2017 – A Year of Despair and Dragons Kurt Lawson – 10ish Favorites of 2017 Jorge Ramirez – Selection 2017 William Neill – William Neill’s Light on the Landscape Photoblog Daniel Leu – Favorites – 2017 Derrald Farnsworth-Livingston – Top 10 Favorite Images from 2017 ~ Journey of Light Photography Mike Christoferson – 2017 Has Come and Gone Carol Schiraldi – Best of 2017 – My Top Images Robin Black – My 10 best photos (or personal favorites, anyway) of 2017 Bryn Tassell – […]




read

Best Photos of 2018 by JMG-Galleries Blog Readers

I’m excited to share the results of my 12th annual Best of Photos project.  115 photographers from around the world (amateur and professional alike) have shared their best photos of 2018.  I’m always amazed at the quality of work shared and I hope it’s a source inspiration to you for the coming year. For those who are new to my blog project, photographers taking part span the gamut of photo enthusiasts to professionals. The great thing about photography is that no matter what your skill level we all can relate equally in our love for the art of photography and visually exploring. With that in mind I encourage you to reach out to photographers whose work you enjoy to keep sharing & growing as an artist.  I am incredibly thankful that this tradition has been embraced and enjoy seeing how familiar faces have evolved their work & grown over the years.  I hope reviewing your best photos of the year and comparing them to years pasts keeps you inspired and aware of your progress as a photographer. If you’d like to take part next year and be informed when submissions open for the “Best Photos of 2019” blog project add your name to my mail list. You won’t be spammed. I send out newsletters quite infrequently. Thank to everyone who took part!  I invite you to visit each link below as I have and introduce yourself to many of the participating photographers. Best Photos of 2018 Jim Goldstein – Best Photos of 2018 by Jim M. Goldstein Michael Russell – My Top 10 Photographs Of 2018 Dave Wilson – Best of 2018 Joseph Smith – 2018 Favorites – A Baker’s Dozen Randy Langstraat – My Ten Favorite Photos of 2018 Chuq Von Rospach – Chuqui 2018 Best Of Photos Rachel Cohen – Best of 2018 Lucy Autrey Wilson – A Thousand Words Romain Guy – Best of 2018 Alexander S. Kunz – My Favorite Photos from 2018 Stefan Baeurle – Top 10 Favorites of 2018 QT Luong – 2018 in Review Jenni Brehm – Best pf 2018 – Changing Perspectives Sean Bagshaw – My Favorite Photos Of 2018 Johann A. Briffa – 2018: A Photographic Retrospective Exploring Light – 2018: A Year In Review Drake Dyck – Top Ten (favourite) Images of 2018 Richard Wong – Fine Art Photography Prints – 2018 Ramen Saha – 2018 – Ten moments Martin Quinn – Quinn Images 2018 Favorites TheDarkSlides – TheDarkSlides Best of 2018 Denise Goldberg – top photos :: 2018 Peter Carroll – Favourites of 2018 Jeff Hubbard – Ten Favorite Photos 2018 Gary Crabbe – My Favorite Landscape Photos of 2018 – A Year-End Retrospective Harold Davis – Harold Davis – Best of 2018 Werner Priller – My Favorite Images of 2018/ Phil Colla – Natural History Photography – Best Photos Of 2018 Aaron Hockley – Tech Photo Guy: Best Photos of 2018 Dan Baumbach – 2018 in Review Jao van de Lagemaat – Jao’s best images of 2018 Pete Miller-USKestrel Photography – Favorite Images of 2018 Shikha – Eastern Sierra – My favorite images of 2018 Bruce Leventhal – Reflecting on 2018 Christopher Sheppard – The Stories Behind My Favorite Photographs of 2018 Alan Majchrowicz – Photo Highlights 2018 Tom Whelan – Nature Diary Todd Henson – Best Photos of 2018: My Favorites of the Year Khürt Williams – Island in the Net Patricia Davidson – My Top 10 Favorite Photos of 2018 Russ Bishop – 2018 – The Year in Pictures Jim Coda – Some of My Favorite Images from 2018 Steve Cole – Birds Eye View of 2018 Fred Mertz Photography – Best Photos of 2018 Martijn van der Nat – Best of 2018 Graf Nature Photography – Twenty Eighteen Wanderings Scott Thompson – My Top 10 Tahoe Area Photos of 2018 Kyle Jones – 2018 Favorites Clint Losee – My Best Landscape and Nature Photos of 2018 Caleb Weston – Caleb Weston – Dubland Media Greg Clure – Best of 2018 Rick Holliday – Favorites from 2018 J.J. RAIA – J.J. RAIA Best Photos of 2018 Francis Gagnon – Francis Gagnon Best Photos of 2018 Mike Chowla – My Ten Best of Images of 2018 Carl Donohue – 2018 in photos Kurt Lawson – 10 Favorites of 2018: From Lava Rivers in Hawaii to Yosemite Snowstorms William Bean – William Bean T.M. Schultze – My Favorite Photographs of 2018 Andrew Thomas – Aerial Adventures – Best of 2018 Matt Conti – 2018 Top 20 Photos Daniel Leu – Favorites – 2018 Carol Schiraldi – Best of 2018 from Carol’s Little World Alan Dahl – 2018 Favorite Photos Milan Hutera – 2018 in Pictures Kathy Barnhart – Flickr Sensing Light Best of 2018 Album Greg Russell – Alpenglow Images 2018 Year in Review Derrald Farnsworth-Livingston – Top 10 Favorite Images from 2018 Kevin Ebi – Living Wilderness: Best of 2018 Jackson Frishman – Favorites of 2018 Greg A. Lato – My Favorite Photos of 2018 Mike Shipman – Mike Shipman’s Best of 2018 Beth Young – Best Photos of 2018 Dale Grosbach – My Favorites – 2018 Brent Huntley – Photography and Travel Charlie Russell – Best Wildflower Photos for 2018 Bryan William Jones – Jonesblog Tony Wu – Favorite Photos of 2018 Adrian Klein – 2018 Photo Retrospective Scott McGee – Top 10 of 2018 William Neill – My Favorite Photographs of 2018 Thomas Yackley – Yackley Photo Anne McKinnell – Best Photos of 2018 Holly Davison – Top Ten of 2018 Brian Knott – Brian Knott Photography 2018 Year In Review Anna DeStefano – Affirmation Photography’s Best of 2018 Ingeborg Fernau – Magicalglow Photography Blog Emil Powella – Top 10 of 2018 Elduro Tuco – Elduro Tuco Eric Chan – Favorites From 2018 TP Chapman – Best of 2018 Ilias Katsouras – Okrivadas Molly Dean – Best Photos of 2018 Sarah Marino – 2018 Wrap-Up and a Few Favorite Photographs Michael Frye – My Top Photographs of 2018 Jim Stamates – Memories of 2018 Tim Aston – Favorites from 2018 Samantha Decker – My Best […]