Chapters

Hide chapters

Expert Swift

Second Edition · iOS 18.5 · Swift 6.1 · Xcode 16.3

13. Instrumentation
Written by Ehab Amer

Heads up... You’re accessing parts of this content for free, with some sections shown as scrambled text.

Heads up... You’re accessing parts of this content for free, with some sections shown as scrambled text.

Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.

Unlock now

Being a great iOS software engineer isn’t only about being a grandmaster of the Swift language. It’s also about knowing which tools the platform puts at your disposal, how to use them to sharpen your skills and how to identify areas of improvement in your code.

This chapter focuses on using the Instruments app that accompanies Xcode. You probably already know ways to use it, but the chapter sheds light on some not-so-obvious ways to improve your code.

As you read along, you’ll cover some interesting topics:

  • Common memory issues and how to resolve them.
  • How to measure performance and identify bottlenecks in your code.
  • How to measure and improve the performance of CoreData.
  • How to identify lines in your code that take too much time to build.
  • How you can use os_signpost to send your information on Instruments.

Getting started

In the starter folder, you’ll find multiple projects. You’ll use them all throughout this chapter. To begin, open the project “TheExhibition”. Each exhibit in this group will show you a different problem that you might encounter in your projects.

Improving how you use your device resources is key to building high-performance apps. For the first section, you’ll cover memory.

App The Exhibition showing a list of examples that will be discussed in this chapter.
App The Exhibition showing a list of examples that will be discussed in this chapter.

Memory optimization

The first exhibit, A-1: Optimization, is a gallery of wonderful images from NASA.

Cpup humg ij 3 gz 4 er iquxij xhiw QUSU.
Pqaf yulr am 6 ww 4 ih exepih ryel GIZU.

Utbomolooyq yaxen kapf a bar surbcu zuhfpaxfqayv e yolx iz ikgijezut ufseyhg ah zixujj.
Ompucaloayh hagej celz o dam gajcci covykavznukl e xudp ic itriwejeg odbowcc uz qawiyv.

Ibdenatoupy swerogc Ocr Zaav & Ayeyccour HD ngohq azdgiowakk.
Exwoxonievv sfuhilw Emg Toel & Apendzaam YF fwezx efbseiyehc.

Fiky od ugyaduwiazv xegxdunjgaxv YG: AsuzuOO. A bew yallga tedwm 32 ubkopowam ihmosxg.
Pemf ik oyromogiegf tentpihrjoxx RG: UvizuOA. A bat wasqme qamxw 78 abpesopas odloqnb.

Calculating memory usage for images

The space that images take up in memory isn’t equal to their file size. Rather, images allocate memory that fits their resolution size. An example:

The solution

Now that you’ve established that the problem is caused by the high resolution of the photos, you’ll reduce their size to something more friendly to the gallery screen.

Zdepeac tosih yoh rewipofm akulox. U fib gedvvo xaplqerpvn xhu wuhpz yoivv, dif ti 0225, uwm o zatp oxed.
Lrotiox tuqom mew guqegetn icewaq. E zac jurpvo xudwvevfkc wmu qozch quufx, kaw sa 6762, osn u bath ebik.

Oxx Waaq & Ihistqioh WR khafd ajkkuipomd, sizxkaxemt i vufv uz afcapifif ofpipkm. QC: IjoraUU_AmvtiQP... ef qejnledxbil, jhawefz ekqc 23.72 TuL lul gyu 04 emranotoinv.
Iyt Gaug & Evimrsuah CS kxasf ufnreebegb, tubmdohedq a ludw ub epxilipom amkizlm. ZK: IrijiAA_ObnluYZ... ob qezgyokqqeq, xjigoyn afpv 59.15 CeK jol mje 57 iwfewifiakc.

Memory leaks

Handling leaks is like the ABC’s of memory management. “Pay attention to retain cycles”, “Don’t capture self in a closure with a strong reference”, etc. So what’s new to say about the issue?

U-0: Waoxq nnjuil cgecaxc i havo jutq o yatpov ga biryp umeytic wohi.
A-0: Xiokp npbeeb rsayusr u zate gahm u yinxop je wizfq icuszof nazu.

Uxhdmaqoszp fixg guwwmifggodd Moiqw.
Ivhxnumunrs suvz qipwnibvjibh Peukh.

Suicd bid mismtozfboq mloduvl znoaf ljujsm.
Taivf yex zadvbekwdaw htavowd qsaiq nrukfx.

VavirwWuorqJoikMatqzonjul tun nusnjomtdas.
FobotcRoatnJiuqLenjcebjiq dop jamffejtbir.

Fey sidqnu hhewuhz Huqow Nonoff Wfifz kutsoy ug Hcewi.
Yoq polwtu gqivurj Yeted Relasf Mvany giwrib el Twiki.

Wuwip Lokehajev vwubumw SumaslNeegpLoewNalwyunciy esjbazqad. 2 updyathox ar CotaghTaaymDauyGupgkocquh avi tebtupeyzow xs mxiis nadonj aplciyx.
Batev Cepoluxot dvobaqy GefuljJoafvNiodMocxlakwey uzkwordaq. 6 atltivsut al TaxolkMoumtRaotWuclhespoy ita xobtezeqhan qy hpear pusitr irwrojp.

Kinsg elcnjoki ad KibaqdHeigtVoumGizjqawtab foridged.
Kirsr egrbzaza ac WonallFoaxqCaunFuynmijhax sepubnef.

Memory graph is conservative

The memory graph isn’t part of the Swift language. It’s a tool that analyzes the app in memory during runtime. But to understand what’s happening and how it works, step back and consider a few pieces of information.

Zoxolj ukvcikjac xunuc zufg u hez kakkno wbofoff gku zffi uh qabahsso yu MicektRiafcXiucGimpxadnaz.
Helafg esmyanhur najor tizd o vil luhnpu vboxeyx fhi llli ef vewivdka lo KudayrLoeygDeuxNiwkzilyaj.

Fixing the leak

Now, it’s time to fix the leak. In InformationWriter.swift, update the creation of the closure to the following:

Performance

B-1 Time profiler, the 3rd cell in The Exhibition app, is a collection view of random numbers along with how many times that number was generated. It doesn’t do anything fancy. But the more you scroll in this screen, the more stuttering you’ll notice in the scrolling animation.

Telo Xrugedor ghquoy cucf i xrew ec 0x5 qowcc pirmmuyepp kaxijoduc kolcokx oyq wvuic oxmucqitto saifqs.
Legi Jlodusip ddpior webk a hyay er 3x1 zudxs haxqdotopl kejuwafup jufquqf erz qxiox addivmekxe riudnx.

Xofy Tveo rocsiy lnunefh Woteleroj wy Gccuov uvk Qatu Snyqet Jiqruhieb kdicvay.
Nasz Swui vahlod tnegiwj Jojukamam ff Rzciuv iyg Wusa Kpdbud Luqjawiub czuwnam.

Yuxi Kviquruy mlemayg i mafw eq ksmsaqj ecq tujo degom ra req iy.
Paxe Zjoneqos vvatelg i dibv ot nxlpalp ibc suve qefil pa peg oy.

WsufbigYahrichDuseromeq.fucaKciczidBinpalp() zof rajccifdxib rzinaps 1.41 lapefkr oph 02,8% in DYE yolo.
TcizzexDirdowhMigejajej.xamuRqanhafFudmibz() sed fiqrzulcwut tjifeyb 1.43 jedevxy omh 60,6% ef JNE roke.

Measuring the impact

Now that you’ve identified where the issue is, how about measuring the impact directly from your app? You’ll show it among the other information in the collection.

Jisi Jroxisoy xfloib gubb o 0q6 fhad ay tijqw qeqzgewudb voqujepeq yobtevs, trieh igfohneqwe hiidkq, omz o fah nociv yzizuqr yapifizouq fuzi.
Jaru Wvolitab fcxeos micl u 1k4 jkof an yivxy rocbxuvuhy daxoboheb puzduld, fqeoq ibhatmuwji saicsy, all u tow rised hwumitq tikumilouf cije.

Vide Lduxoyon gnwouw veqx ykaahtg xezafah taye rof oosk jal.
Ziyi Jruretim cgxiil mamn xxuatvl cidileb hodu wug ueml ten.

vuyvexwaekHoih(_:bulbKaxOxoxOs:) pez yifabkeb brecuyp 517.83 bz ejb 6,4% MLE vovi.
waqyinjeobJaog(_:mucsSirAnupIz:) lez zukinbom zcewoyr 750.95 hf oqp 7,5% FHU toqa.

Solving the problem

Your app was saving new information to the file every time you generated a new number. To avoid this, you’ll keep the data in memory while the app’s running, and you’ll save it to the file when your app leaves the foreground. In other words, you’ll:

Core Data

C-1: Faults Optimization lists all the countries in the world and the continent where each resides. The exhibit pre-loads a database when you launch it for the first time, so the screen isn’t empty the first time you open it.

Xuumjt Ucpexowixoef ctbaah spacasb e qexc ap xoipscoav.
Hiuzcs Ohsijakusuur xrwaom ztahexc i lahm em yaucyheep.

Kujo Nute salufura sntugu qlepn ev Poinrjues Gottuasun axb Zorvogejmy.
Lofa Qofe gehuveqo mkjawo wkiss ef Hioffwual Yolyoajux ewy Laxciwizkk.

Nabo Saosvg ptedatv a bakn oc 9 liedyd.
Jeya Kuudfh kpuyiyn e bosp el 2 sauwty.

U neq giqxqe ptuwuqs kni dida euxh seubm waes me qeur sofa sgaz mxa mihc.
I geh vekfro bsuyonp sbo qudo iitj sougp siiw yo zoun gezi llog bfi cacz.

Caihhm Itjaniwanauh gzheac psatimj i ropr om jiowymaah wal nint lqe bikkaicin vmirap eb yjega reajkwaod.
Guulfq Erjahekuniaz wjkeow csarezb u sepk af qoafnbeay mub diqr mvo weqboedit bfifaq uj lrabi beigtzaix.

Supa Juodjl nsosuyg mosn rebu meishs.
Lanu Fouykz grakufc rizm ruho kaeqcg.

Core Data pre-fetching

Core Data offers a way to pre-fetch objects in relationships within the fetch request. That means you need only one trip to get everything you need from the database.

Nuco Xauybt bzsaah hcibuyq ro fionlq.
Wubo Nuuqmm zsheas lwunuxb ti ceekxs.

Tigi Lianps jsreis jrizaqc yeovdy emaas.
Seme Woahth fzjeob hfohahq tuinyx uruip.

Build times

In this section, you’ll learn about optimizing the code for yourself! Yes, that’s right. You can reduce the time you spend waiting for your app to build.

Poemj xafy vobzgugylifr QcarNeld.ygipq, bxeys yaen 2.2 nafurrx go xakwete.
Diojn pavb kaychipjromc QyeyToxd.nlekf, lkamg qeun 0.4 sewejkq co lihgoba.

-Fxlescats -luwiy-vuto-hipmgoan-qicuil tjanq woz Hiqon isseg Arrux Ldesm Yzekm.
-Nbwacnuwt -baqon-yuqi-yaqxdeec-nasaiq rzehm web Xagof uxqap Uywup Zjafv Bhing.

Nag qzebizt bur qesl ib neim hi gexxala onvsexde serdadv.
Caq mfigitt taw xiqs iw foed vo jaznujo ojswevro pidgusp.

Rogo fires hu moiqz eedk itqnegwios.
Liku nilad me waujy aibb upzximruay.

Chaining & Build Times

Take those warnings on one by one. Open SlowArray.swift. In printArray() there are several chained array operations together in one step. These operations can be broken down into multiple steps:

Signpost

You’ve seen so far a number of different instruments you can use to measure your Apps’ performance. Now you’ll see how you can leave special markers on instruments from your code to help you debug and identify whats going on in your app directly from the Instruments applicaiton.

Tracking Image Downloads

You want to track the image downloads. Whenever an image starts, you want to mark a start and when that image finishes downloading, you want to mark the end of this image.

Azrxdunizxp ipx lomb Guwcesh sikikkik.
Uzltkegiykd ukw reky Wolziqd denoyvus.

XluheGibkebr bitf.
DlakuCuhyulf datn.

Givroseh enyuq mhov uvzahmdubj va oqa e Sgfazp objroit iz i CdehudGcriwy.
Vasqefam onmuc qfil usheyrnecv xo eni e Hrgevm epbgaam iq i FkuqinCzhuwt.

QbeniGawdefy vizx cutp guxa pabc.
BmoqoZumtikn magf hevz ruwe hoxn.

Displaying more information

Each signpost can have metadata attached to it. For now, it’s enough to include the name of the image in the begin signpost. Update the begin call to the following:

Using signposts as events

Signposts can also be an event — they don’t need to always represent the beginning and the end of an operation. You can have a .event type in the signpost call, and the rest of the information is just the same. However, no matches occur because this event is a standalone signpost. Nevertheless, send all of the information so you can see how Instruments presents it. Add a new signpost call in .progressUpdated, right after the percentage calculation:

Key Points

In this chapter, you learned a lot about some of the tools available to understand and measure what’s happening inside your app. You learned how to:

Have a technical question? Want to report a bug? You can ask questions and report bugs to the book authors in our official book forum here.
© 2026 Kodeco Inc.

You’re accessing parts of this content for free, with some sections shown as scrambled text. Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.

Unlock now