-
-
Save milseman/737d74fd4a6817432b3b5f18c34d416d to your computer and use it in GitHub Desktop.
Mega string regressions
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// mega_string_regressions.swift | |
import Foundation | |
print("start") | |
public var _runningTotal = 0 | |
@inline(never) | |
public func identity<T>(_ t: T) -> T { | |
_runningTotal &+= 1 | |
return t | |
} | |
@inline(never) | |
public func getString(_ t: String) -> String { | |
_runningTotal &+= 1 | |
return t | |
} | |
@inline(never) | |
public func blackHole(_ x: Bool) { | |
if x { _runningTotal += 0 } | |
} | |
@inline(never) | |
public func blackHole(_ x: String) { | |
if x.isEmpty { _runningTotal += 1 } | |
} | |
@inline(never) | |
public func blackHole<T>(_ x: T) { | |
if x is String { _runningTotal += 1 } | |
} | |
@inline(never) | |
public func blackHole(_ x: Int) { | |
_runningTotal += Swift.min(_runningTotal, Swift.abs(x)) | |
_runningTotal /= 2 | |
} | |
@inline(never) | |
public func CheckResults(_ x: Bool) { | |
guard x else { fatalError() } | |
} | |
extension String { | |
func lines() -> [String] { | |
return self.split(separator: "\n").map { String($0) } | |
} | |
} | |
class Box<T : Hashable> : Hashable { | |
var value: T | |
init(_ v: T) { | |
value = v | |
} | |
func hash(into hasher: inout Hasher) { | |
hasher.combine(value) | |
} | |
static func ==(lhs: Box, rhs: Box) -> Bool { | |
return lhs.value == rhs.value | |
} | |
} | |
let words: [String] = [ | |
"woodshed", | |
"lakism", | |
"gastroperiodynia", | |
"afetal", | |
"ramsch", | |
"Nickieben", | |
"undutifulness", | |
"birdglue", | |
"ungentlemanize", | |
"menacingly", | |
"heterophile", | |
"leoparde", | |
"Casearia", | |
"decorticate", | |
"neognathic", | |
"mentionable", | |
"tetraphenol", | |
"pseudonymal", | |
"dislegitimate", | |
"Discoidea", | |
"intitule", | |
"ionium", | |
"Lotuko", | |
"timbering", | |
"nonliquidating", | |
"oarialgia", | |
"Saccobranchus", | |
"reconnoiter", | |
"criminative", | |
"disintegratory", | |
"executer", | |
"Cylindrosporium", | |
"complimentation", | |
"Ixiama", | |
"Araceae", | |
"silaginoid", | |
"derencephalus", | |
"Lamiidae", | |
"marrowlike", | |
"ninepin", | |
"dynastid", | |
"lampfly", | |
"feint", | |
"trihemimer", | |
"semibarbarous", | |
"heresy", | |
"tritanope", | |
"indifferentist", | |
"confound", | |
"hyperbolaeon", | |
"planirostral", | |
"philosophunculist", | |
"existence", | |
"fretless", | |
"Leptandra", | |
"Amiranha", | |
"handgravure", | |
"gnash", | |
"unbelievability", | |
"orthotropic", | |
"Susumu", | |
"teleutospore", | |
"sleazy", | |
"shapeliness", | |
"hepatotomy", | |
"exclusivism", | |
"stifler", | |
"cunning", | |
"isocyanuric", | |
"pseudepigraphy", | |
"carpetbagger", | |
"respectiveness", | |
"Jussi", | |
"vasotomy", | |
"proctotomy", | |
"ovatotriangular", | |
"aesthetic", | |
"schizogamy", | |
"disengagement", | |
"foray", | |
"haplocaulescent", | |
"noncoherent", | |
"astrocyte", | |
"unreverberated", | |
"presenile", | |
"lanson", | |
"enkraal", | |
"contemplative", | |
"Syun", | |
"sartage", | |
"unforgot", | |
"wyde", | |
"homeotransplant", | |
"implicational", | |
"forerunnership", | |
"calcaneum", | |
"stomatodeum", | |
"pharmacopedia", | |
"preconcessive", | |
"trypanosomatic", | |
"intracollegiate", | |
"rampacious", | |
"secundipara", | |
"isomeric", | |
"treehair", | |
"pulmonal", | |
"uvate", | |
"dugway", | |
"glucofrangulin", | |
"unglory", | |
"Amandus", | |
"icterogenetic", | |
"quadrireme", | |
"Lagostomus", | |
"brakeroot", | |
"anthracemia", | |
"fluted", | |
"protoelastose", | |
"thro", | |
"pined", | |
"Saxicolinae", | |
"holidaymaking", | |
"strigil", | |
"uncurbed", | |
"starling", | |
"redeemeress", | |
"Liliaceae", | |
"imparsonee", | |
"obtusish", | |
"brushed", | |
"mesally", | |
"probosciformed", | |
"Bourbonesque", | |
"histological", | |
"caroba", | |
"digestion", | |
"Vindemiatrix", | |
"triactinal", | |
"tattling", | |
"arthrobacterium", | |
"unended", | |
"suspectfulness", | |
"movelessness", | |
"chartist", | |
"Corynebacterium", | |
"tercer", | |
"oversaturation", | |
"Congoleum", | |
"antiskeptical", | |
"sacral", | |
"equiradiate", | |
"whiskerage", | |
"panidiomorphic", | |
"unplanned", | |
"anilopyrine", | |
"Queres", | |
"tartronyl", | |
"Ing", | |
"notehead", | |
"finestiller", | |
"weekender", | |
"kittenhood", | |
"competitrix", | |
"premillenarian", | |
"convergescence", | |
"microcoleoptera", | |
"slirt", | |
"asteatosis", | |
"Gruidae", | |
"metastome", | |
"ambuscader", | |
"untugged", | |
"uneducated", | |
"redistill", | |
"rushlight", | |
"freakish", | |
"dosology", | |
"papyrine", | |
"iconologist", | |
"Bidpai", | |
"prophethood", | |
"pneumotropic", | |
"chloroformize", | |
"intemperance", | |
"spongiform", | |
"superindignant", | |
"divider", | |
"starlit", | |
"merchantish", | |
"indexless", | |
"unidentifiably", | |
"coumarone", | |
"nomism", | |
"diaphanous", | |
"salve", | |
"option", | |
"anallantoic", | |
"paint", | |
"thiofurfuran", | |
"baddeleyite", | |
"Donne", | |
"heterogenicity", | |
"decess", | |
"eschynite", | |
"mamma", | |
"unmonarchical", | |
"Archiplata", | |
"widdifow", | |
"apathic", | |
"overline", | |
"chaetophoraceous", | |
"creaky", | |
"trichosporange", | |
"uninterlined", | |
"cometwise", | |
"hermeneut", | |
"unbedraggled", | |
"tagged", | |
"Sminthurus", | |
"somniloquacious", | |
"aphasiac", | |
"Inoperculata", | |
"photoactivity", | |
"mobship", | |
"unblightedly", | |
"lievrite", | |
"Khoja", | |
"Falerian", | |
"milfoil", | |
"protectingly", | |
"householder", | |
"cathedra", | |
"calmingly", | |
"tordrillite", | |
"rearhorse", | |
"Leonard", | |
"maracock", | |
"youngish", | |
"kammererite", | |
"metanephric", | |
"Sageretia", | |
"diplococcoid", | |
"accelerative", | |
"choreal", | |
"metalogical", | |
"recombination", | |
"unimprison", | |
"invocation", | |
"syndetic", | |
"toadback", | |
"vaned", | |
"cupholder", | |
"metropolitanship", | |
"paramandelic", | |
"dermolysis", | |
"Sheriyat", | |
"rhabdus", | |
"seducee", | |
"encrinoid", | |
"unsuppliable", | |
"cololite", | |
"timesaver", | |
"preambulate", | |
"sampling", | |
"roaster", | |
"springald", | |
"densher", | |
"protraditional", | |
"naturalesque", | |
"Hydrodamalis", | |
"cytogenic", | |
"shortly", | |
"cryptogrammatical", | |
"squat", | |
"genual", | |
"backspier", | |
"solubleness", | |
"macroanalytical", | |
"overcovetousness", | |
"Natalie", | |
"cuprobismutite", | |
"phratriac", | |
"Montanize", | |
"hymnologist", | |
"karyomiton", | |
"podger", | |
"unofficiousness", | |
"antisplasher", | |
"supraclavicular", | |
"calidity", | |
"disembellish", | |
"antepredicament", | |
"recurvirostral", | |
"pulmonifer", | |
"coccidial", | |
"botonee", | |
"protoglobulose", | |
"isonym", | |
"myeloid", | |
"premiership", | |
"unmonopolize", | |
"unsesquipedalian", | |
"unfelicitously", | |
"theftbote", | |
"undauntable", | |
"lob", | |
"praenomen", | |
"underriver", | |
"gorfly", | |
"pluckage", | |
"radiovision", | |
"tyrantship", | |
"fraught", | |
"doppelkummel", | |
"rowan", | |
"allosyndetic", | |
"kinesiology", | |
"psychopath", | |
"arrent", | |
"amusively", | |
"preincorporation", | |
"Montargis", | |
"pentacron", | |
"neomedievalism", | |
"sima", | |
"lichenicolous", | |
"Ecclesiastes", | |
"woofed", | |
"cardinalist", | |
"sandaracin", | |
"gymnasial", | |
"lithoglyptics", | |
"centimeter", | |
"quadrupedous", | |
"phraseology", | |
"tumuli", | |
"ankylotomy", | |
"myrtol", | |
"cohibitive", | |
"lepospondylous", | |
"silvendy", | |
"inequipotential", | |
"entangle", | |
"raveling", | |
"Zeugobranchiata", | |
"devastating", | |
"grainage", | |
"amphisbaenian", | |
"blady", | |
"cirrose", | |
"proclericalism", | |
"governmentalist", | |
"carcinomorphic", | |
"nurtureship", | |
"clancular", | |
"unsteamed", | |
"discernibly", | |
"pleurogenic", | |
"impalpability", | |
"Azotobacterieae", | |
"sarcoplasmic", | |
"alternant", | |
"fitly", | |
"acrorrheuma", | |
"shrapnel", | |
"pastorize", | |
"gulflike", | |
"foreglow", | |
"unrelated", | |
"cirriped", | |
"cerviconasal", | |
"sexuale", | |
"pussyfooter", | |
"gadolinic", | |
"duplicature", | |
"codelinquency", | |
"trypanolysis", | |
"pathophobia", | |
"incapsulation", | |
"nonaerating", | |
"feldspar", | |
"diaphonic", | |
"epiglottic", | |
"depopulator", | |
"wisecracker", | |
"gravitational", | |
"kuba", | |
"lactesce", | |
"Toxotes", | |
"periomphalic", | |
"singstress", | |
"fannier", | |
"counterformula", | |
"Acemetae", | |
"repugnatorial", | |
"collimator", | |
"Acinetina", | |
"unpeace", | |
"drum", | |
"tetramorphic", | |
"descendentalism", | |
"cementer", | |
"supraloral", | |
"intercostal", | |
"Nipponize", | |
"negotiator", | |
"vacationless", | |
"synthol", | |
"fissureless", | |
"resoap", | |
"pachycarpous", | |
"reinspiration", | |
"misappropriation", | |
"disdiazo", | |
"unheatable", | |
"streng", | |
"Detroiter", | |
"infandous", | |
"loganiaceous", | |
"desugar", | |
"Matronalia", | |
"myxocystoma", | |
"Gandhiism", | |
"kiddier", | |
"relodge", | |
"counterreprisal", | |
"recentralize", | |
"foliously", | |
"reprinter", | |
"gender", | |
"edaciousness", | |
"chondriomite", | |
"concordant", | |
"stockrider", | |
"pedary", | |
"shikra", | |
"blameworthiness", | |
"vaccina", | |
"Thamnophilinae", | |
"wrongwise", | |
"unsuperannuated", | |
"convalescency", | |
"intransmutable", | |
"dropcloth", | |
"Ceriomyces", | |
"ponderal", | |
"unstentorian", | |
"mem", | |
"deceleration", | |
"ethionic", | |
"untopped", | |
"wetback", | |
"bebar", | |
"undecaying", | |
"shoreside", | |
"energize", | |
"presacral", | |
"undismay", | |
"agricolite", | |
"cowheart", | |
"hemibathybian", | |
"postexilian", | |
"Phacidiaceae", | |
"offing", | |
"redesignation", | |
"skeptically", | |
"physicianless", | |
"bronchopathy", | |
"marabuto", | |
"proprietory", | |
"unobtruded", | |
"funmaker", | |
"plateresque", | |
"preadventure", | |
"beseeching", | |
"cowpath", | |
"pachycephalia", | |
"arthresthesia", | |
"supari", | |
"lengthily", | |
"Nepa", | |
"liberation", | |
"nigrify", | |
"belfry", | |
"entoolitic", | |
"bazoo", | |
"pentachromic", | |
"distinguishable", | |
"slideable", | |
"galvanoscope", | |
"remanage", | |
"cetene", | |
"bocardo", | |
"consummation", | |
"boycottism", | |
"perplexity", | |
"astay", | |
"Gaetuli", | |
"periplastic", | |
"consolidator", | |
"sluggarding", | |
"coracoscapular", | |
"anangioid", | |
"oxygenizer", | |
"Hunanese", | |
"seminary", | |
"periplast", | |
"Corylus", | |
"unoriginativeness", | |
"persecutee", | |
"tweaker", | |
"silliness", | |
"Dabitis", | |
"facetiousness", | |
"thymy", | |
"nonimperial", | |
"mesoblastema", | |
"turbiniform", | |
"churchway", | |
"cooing", | |
"frithbot", | |
"concomitantly", | |
"stalwartize", | |
"clingfish", | |
"hardmouthed", | |
"parallelepipedonal", | |
"coracoacromial", | |
"factuality", | |
"curtilage", | |
"arachnoidean", | |
"semiaridity", | |
"phytobacteriology", | |
"premastery", | |
"hyperpurist", | |
"mobed", | |
"opportunistic", | |
"acclimature", | |
"outdistance", | |
"sophister", | |
"condonement", | |
"oxygenerator", | |
"acetonic", | |
"emanatory", | |
"periphlebitis", | |
"nonsociety", | |
"spectroradiometric", | |
"superaverage", | |
"cleanness", | |
"posteroventral", | |
"unadvised", | |
"unmistakedly", | |
"pimgenet", | |
"auresca", | |
"overimitate", | |
"dipnoan", | |
"chromoxylograph", | |
"triakistetrahedron", | |
"Suessiones", | |
"uncopiable", | |
"oligomenorrhea", | |
"fribbling", | |
"worriable", | |
"flot", | |
"ornithotrophy", | |
"phytoteratology", | |
"setup", | |
"lanneret", | |
"unbraceleted", | |
"gudemother", | |
"Spica", | |
"unconsolatory", | |
"recorruption", | |
"premenstrual", | |
"subretinal", | |
"millennialist", | |
"subjectibility", | |
"rewardproof", | |
"counterflight", | |
"pilomotor", | |
"carpetbaggery", | |
"macrodiagonal", | |
"slim", | |
"indiscernible", | |
"cuckoo", | |
"moted", | |
"controllingly", | |
"gynecopathy", | |
"porrectus", | |
"wanworth", | |
"lutfisk", | |
"semiprivate", | |
"philadelphy", | |
"abdominothoracic", | |
"coxcomb", | |
"dambrod", | |
"Metanemertini", | |
"balminess", | |
"homotypy", | |
"waremaker", | |
"absurdity", | |
"gimcrack", | |
"asquat", | |
"suitable", | |
"perimorphous", | |
"kitchenwards", | |
"pielum", | |
"salloo", | |
"paleontologic", | |
"Olson", | |
"Tellinidae", | |
"ferryman", | |
"peptonoid", | |
"Bopyridae", | |
"fallacy", | |
"ictuate", | |
"aguinaldo", | |
"rhyodacite", | |
"Ligydidae", | |
"galvanometric", | |
"acquisitor", | |
"muscology", | |
"hemikaryon", | |
"ethnobotanic", | |
"postganglionic", | |
"rudimentarily", | |
"replenish", | |
"phyllorhine", | |
"popgunnery", | |
"summar", | |
"quodlibetary", | |
"xanthochromia", | |
"autosymbolically", | |
"preloreal", | |
"extent", | |
"strawberry", | |
"immortalness", | |
"colicwort", | |
"frisca", | |
"electiveness", | |
"heartbroken", | |
"affrightingly", | |
"reconfiscation", | |
"jacchus", | |
"imponderably", | |
"semantics", | |
"beennut", | |
"paleometeorological", | |
"becost", | |
"timberwright", | |
"resuppose", | |
"syncategorematical", | |
"cytolymph", | |
"steinbok", | |
"explantation", | |
"hyperelliptic", | |
"antescript", | |
"blowdown", | |
"antinomical", | |
"caravanserai", | |
"unweariedly", | |
"isonymic", | |
"keratoplasty", | |
"vipery", | |
"parepigastric", | |
"endolymphatic", | |
"Londonese", | |
"necrotomy", | |
"angelship", | |
"Schizogregarinida", | |
"steeplebush", | |
"sparaxis", | |
"connectedness", | |
"tolerance", | |
"impingent", | |
"agglutinin", | |
"reviver", | |
"hieroglyphical", | |
"dialogize", | |
"coestate", | |
"declamatory", | |
"ventilation", | |
"tauromachy", | |
"cotransubstantiate", | |
"pome", | |
"underseas", | |
"triquadrantal", | |
"preconfinemnt", | |
"electroindustrial", | |
"selachostomous", | |
"nongolfer", | |
"mesalike", | |
"hamartiology", | |
"ganglioblast", | |
"unsuccessive", | |
"yallow", | |
"bacchanalianly", | |
"platydactyl", | |
"Bucephala", | |
"ultraurgent", | |
"penalist", | |
"catamenial", | |
"lynnhaven", | |
"unrelevant", | |
"lunkhead", | |
"metropolitan", | |
"hydro", | |
"outsoar", | |
"vernant", | |
"interlanguage", | |
"catarrhal", | |
"Ionicize", | |
"keelless", | |
"myomantic", | |
"booker", | |
"Xanthomonas", | |
"unimpeded", | |
"overfeminize", | |
"speronaro", | |
"diaconia", | |
"overholiness", | |
"liquefacient", | |
"Spartium", | |
"haggly", | |
"albumose", | |
"nonnecessary", | |
"sulcalization", | |
"decapitate", | |
"cellated", | |
"unguirostral", | |
"trichiurid", | |
"loveproof", | |
"amakebe", | |
"screet", | |
"arsenoferratin", | |
"unfrizz", | |
"undiscoverable", | |
"procollectivistic", | |
"tractile", | |
"Winona", | |
"dermostosis", | |
"eliminant", | |
"scomberoid", | |
"tensile", | |
"typesetting", | |
"xylic", | |
"dermatopathology", | |
"cycloplegic", | |
"revocable", | |
"fissate", | |
"afterplay", | |
"screwship", | |
"microerg", | |
"bentonite", | |
"stagecoaching", | |
"beglerbeglic", | |
"overcharitably", | |
"Plotinism", | |
"Veddoid", | |
"disequalize", | |
"cytoproct", | |
"trophophore", | |
"antidote", | |
"allerion", | |
"famous", | |
"convey", | |
"postotic", | |
"rapillo", | |
"cilectomy", | |
"penkeeper", | |
"patronym", | |
"bravely", | |
"ureteropyelitis", | |
"Hildebrandine", | |
"missileproof", | |
"Conularia", | |
"deadening", | |
"Conrad", | |
"pseudochylous", | |
"typologically", | |
"strummer", | |
"luxuriousness", | |
"resublimation", | |
"glossiness", | |
"hydrocauline", | |
"anaglyph", | |
"personifiable", | |
"seniority", | |
"formulator", | |
"datiscaceous", | |
"hydracrylate", | |
"Tyranni", | |
"Crawthumper", | |
"overprove", | |
"masher", | |
"dissonance", | |
"Serpentinian", | |
"malachite", | |
"interestless", | |
"stchi", | |
"ogum", | |
"polyspermic", | |
"archegoniate", | |
"precogitation", | |
"Alkaphrah", | |
"craggily", | |
"delightfulness", | |
"bioplast", | |
"diplocaulescent", | |
"neverland", | |
"interspheral", | |
"chlorhydric", | |
"forsakenly", | |
"scandium", | |
"detubation", | |
"telega", | |
"Valeriana", | |
"centraxonial", | |
"anabolite", | |
"neger", | |
"miscellanea", | |
"whalebacker", | |
"stylidiaceous", | |
"unpropelled", | |
"Kennedya", | |
"Jacksonite", | |
"ghoulish", | |
"Dendrocalamus", | |
"paynimhood", | |
"rappist", | |
"unluffed", | |
"falling", | |
"Lyctus", | |
"uncrown", | |
"warmly", | |
"pneumatism", | |
"Morisonian", | |
"notate", | |
"isoagglutinin", | |
"Pelidnota", | |
"previsit", | |
"contradistinctly", | |
"utter", | |
"porometer", | |
"gie", | |
"germanization", | |
"betwixt", | |
"prenephritic", | |
"underpier", | |
"Eleutheria", | |
"ruthenious", | |
"convertor", | |
"antisepsin", | |
"winterage", | |
"tetramethylammonium", | |
"Rockaway", | |
"Penaea", | |
"prelatehood", | |
"brisket", | |
"unwishful", | |
"Minahassa", | |
"Briareus", | |
"semiaxis", | |
"disintegrant", | |
"peastick", | |
"iatromechanical", | |
"fastus", | |
"thymectomy", | |
"ladyless", | |
"unpreened", | |
"overflutter", | |
"sicker", | |
"apsidally", | |
"thiazine", | |
"guideway", | |
"pausation", | |
"tellinoid", | |
"abrogative", | |
"foraminulate", | |
"omphalos", | |
"Monorhina", | |
"polymyarian", | |
"unhelpful", | |
"newslessness", | |
"oryctognosy", | |
"octoradial", | |
"doxology", | |
"arrhythmy", | |
"gugal", | |
"mesityl", | |
"hexaplaric", | |
"Cabirian", | |
"hordeiform", | |
"eddyroot", | |
"internarial", | |
"deservingness", | |
"jawbation", | |
"orographically", | |
"semiprecious", | |
"seasick", | |
"thermically", | |
"grew", | |
"tamability", | |
"egotistically", | |
"fip", | |
"preabsorbent", | |
"leptochroa", | |
"ethnobotany", | |
"podolite", | |
"egoistic", | |
"semitropical", | |
"cero", | |
"spinelessness", | |
"onshore", | |
"omlah", | |
"tintinnabulist", | |
"machila", | |
"entomotomy", | |
"nubile", | |
"nonscholastic", | |
"burnt", | |
"Alea", | |
"befume", | |
"doctorless", | |
"Napoleonic", | |
"scenting", | |
"apokreos", | |
"cresylene", | |
"paramide", | |
"rattery", | |
"disinterested", | |
"idiopathetic", | |
"negatory", | |
"fervid", | |
"quintato", | |
"untricked", | |
"Metrosideros", | |
"mescaline", | |
"midverse", | |
"Musophagidae", | |
"fictionary", | |
"branchiostegous", | |
"yoker", | |
"residuum", | |
"culmigenous", | |
"fleam", | |
"suffragism", | |
"Anacreon", | |
"sarcodous", | |
"parodistic", | |
"writmaking", | |
"conversationism", | |
"retroposed", | |
"tornillo", | |
"presuspect", | |
"didymous", | |
"Saumur", | |
"spicing", | |
"drawbridge", | |
"cantor", | |
"incumbrancer", | |
"heterospory", | |
"Turkeydom", | |
"anteprandial", | |
"neighborship", | |
"thatchless", | |
"drepanoid", | |
"lusher", | |
"paling", | |
"ecthlipsis", | |
"heredosyphilitic", | |
"although", | |
"garetta", | |
"temporarily", | |
"Monotropa", | |
"proglottic", | |
"calyptro", | |
"persiflage", | |
"degradable", | |
"paraspecific", | |
"undecorative", | |
"Pholas", | |
"myelon", | |
"resteal", | |
"quadrantly", | |
"scrimped", | |
"airer", | |
"deviless", | |
"caliciform", | |
"Sefekhet", | |
"shastaite", | |
"togate", | |
"macrostructure", | |
"bipyramid", | |
"wey", | |
"didynamy", | |
"knacker", | |
"swage", | |
"supermanism", | |
"epitheton", | |
"overpresumptuous" | |
] | |
let sortedWords = words.sorted() | |
@inline(never) | |
func benchSortStrings(_ words: [String]) { | |
// Notice that we _copy_ the array of words before we sort it. | |
// Pass an explicit '<' predicate to benchmark reabstraction thunks. | |
var tempwords = words | |
tempwords.sort(by: <) | |
} | |
public func run_SortStrings(_ N: Int) { | |
for _ in 1...5*N { | |
benchSortStrings(words) | |
} | |
} | |
public func run_SortSortedStrings(_ N: Int) { | |
for _ in 1...5*N { | |
benchSortStrings(sortedWords) | |
} | |
} | |
var unicodeWords: [String] = [ | |
"❄️woodshed", | |
"❄️lakism", | |
"❄️gastroperiodynia", | |
"❄️afetal", | |
"❄️ramsch", | |
"❄️Nickieben", | |
"❄️undutifulness", | |
"❄️birdglue", | |
"❄️ungentlemanize", | |
"❄️menacingly", | |
"❄️heterophile", | |
"❄️leoparde", | |
"❄️Casearia", | |
"❄️decorticate", | |
"❄️neognathic", | |
"❄️mentionable", | |
"❄️tetraphenol", | |
"❄️pseudonymal", | |
"❄️dislegitimate", | |
"❄️Discoidea", | |
"❄️intitule", | |
"❄️ionium", | |
"❄️Lotuko", | |
"❄️timbering", | |
"❄️nonliquidating", | |
"❄️oarialgia", | |
"❄️Saccobranchus", | |
"❄️reconnoiter", | |
"❄️criminative", | |
"❄️disintegratory", | |
"❄️executer", | |
"❄️Cylindrosporium", | |
"❄️complimentation", | |
"❄️Ixiama", | |
"❄️Araceae", | |
"❄️silaginoid", | |
"❄️derencephalus", | |
"❄️Lamiidae", | |
"❄️marrowlike", | |
"❄️ninepin", | |
"❄️dynastid", | |
"❄️lampfly", | |
"❄️feint", | |
"❄️trihemimer", | |
"❄️semibarbarous", | |
"❄️heresy", | |
"❄️tritanope", | |
"❄️indifferentist", | |
"❄️confound", | |
"❄️hyperbolaeon", | |
"❄️planirostral", | |
"❄️philosophunculist", | |
"❄️existence", | |
"❄️fretless", | |
"❄️Leptandra", | |
"❄️Amiranha", | |
"❄️handgravure", | |
"❄️gnash", | |
"❄️unbelievability", | |
"❄️orthotropic", | |
"❄️Susumu", | |
"❄️teleutospore", | |
"❄️sleazy", | |
"❄️shapeliness", | |
"❄️hepatotomy", | |
"❄️exclusivism", | |
"❄️stifler", | |
"❄️cunning", | |
"❄️isocyanuric", | |
"❄️pseudepigraphy", | |
"❄️carpetbagger", | |
"❄️respectiveness", | |
"❄️Jussi", | |
"❄️vasotomy", | |
"❄️proctotomy", | |
"❄️ovatotriangular", | |
"❄️aesthetic", | |
"❄️schizogamy", | |
"❄️disengagement", | |
"❄️foray", | |
"❄️haplocaulescent", | |
"❄️noncoherent", | |
"❄️astrocyte", | |
"❄️unreverberated", | |
"❄️presenile", | |
"❄️lanson", | |
"❄️enkraal", | |
"❄️contemplative", | |
"❄️Syun", | |
"❄️sartage", | |
"❄️unforgot", | |
"❄️wyde", | |
"❄️homeotransplant", | |
"❄️implicational", | |
"❄️forerunnership", | |
"❄️calcaneum", | |
"❄️stomatodeum", | |
"❄️pharmacopedia", | |
"❄️preconcessive", | |
"❄️trypanosomatic", | |
"❄️intracollegiate", | |
"❄️rampacious", | |
"❄️secundipara", | |
"❄️isomeric", | |
"❄️treehair", | |
"❄️pulmonal", | |
"❄️uvate", | |
"❄️dugway", | |
"❄️glucofrangulin", | |
"❄️unglory", | |
"❄️Amandus", | |
"❄️icterogenetic", | |
"❄️quadrireme", | |
"❄️Lagostomus", | |
"❄️brakeroot", | |
"❄️anthracemia", | |
"❄️fluted", | |
"❄️protoelastose", | |
"❄️thro", | |
"❄️pined", | |
"❄️Saxicolinae", | |
"❄️holidaymaking", | |
"❄️strigil", | |
"❄️uncurbed", | |
"❄️starling", | |
"❄️redeemeress", | |
"❄️Liliaceae", | |
"❄️imparsonee", | |
"❄️obtusish", | |
"❄️brushed", | |
"❄️mesally", | |
"❄️probosciformed", | |
"❄️Bourbonesque", | |
"❄️histological", | |
"❄️caroba", | |
"❄️digestion", | |
"❄️Vindemiatrix", | |
"❄️triactinal", | |
"❄️tattling", | |
"❄️arthrobacterium", | |
"❄️unended", | |
"❄️suspectfulness", | |
"❄️movelessness", | |
"❄️chartist", | |
"❄️Corynebacterium", | |
"❄️tercer", | |
"❄️oversaturation", | |
"❄️Congoleum", | |
"❄️antiskeptical", | |
"❄️sacral", | |
"❄️equiradiate", | |
"❄️whiskerage", | |
"❄️panidiomorphic", | |
"❄️unplanned", | |
"❄️anilopyrine", | |
"❄️Queres", | |
"❄️tartronyl", | |
"❄️Ing", | |
"❄️notehead", | |
"❄️finestiller", | |
"❄️weekender", | |
"❄️kittenhood", | |
"❄️competitrix", | |
"❄️premillenarian", | |
"❄️convergescence", | |
"❄️microcoleoptera", | |
"❄️slirt", | |
"❄️asteatosis", | |
"❄️Gruidae", | |
"❄️metastome", | |
"❄️ambuscader", | |
"❄️untugged", | |
"❄️uneducated", | |
"❄️redistill", | |
"❄️rushlight", | |
"❄️freakish", | |
"❄️dosology", | |
"❄️papyrine", | |
"❄️iconologist", | |
"❄️Bidpai", | |
"❄️prophethood", | |
"❄️pneumotropic", | |
"❄️chloroformize", | |
"❄️intemperance", | |
"❄️spongiform", | |
"❄️superindignant", | |
"❄️divider", | |
"❄️starlit", | |
"❄️merchantish", | |
"❄️indexless", | |
"❄️unidentifiably", | |
"❄️coumarone", | |
"❄️nomism", | |
"❄️diaphanous", | |
"❄️salve", | |
"❄️option", | |
"❄️anallantoic", | |
"❄️paint", | |
"❄️thiofurfuran", | |
"❄️baddeleyite", | |
"❄️Donne", | |
"❄️heterogenicity", | |
"❄️decess", | |
"❄️eschynite", | |
"❄️mamma", | |
"❄️unmonarchical", | |
"❄️Archiplata", | |
"❄️widdifow", | |
"❄️apathic", | |
"❄️overline", | |
"❄️chaetophoraceous", | |
"❄️creaky", | |
"❄️trichosporange", | |
"❄️uninterlined", | |
"❄️cometwise", | |
"❄️hermeneut", | |
"❄️unbedraggled", | |
"❄️tagged", | |
"❄️Sminthurus", | |
"❄️somniloquacious", | |
"❄️aphasiac", | |
"❄️Inoperculata", | |
"❄️photoactivity", | |
"❄️mobship", | |
"❄️unblightedly", | |
"❄️lievrite", | |
"❄️Khoja", | |
"❄️Falerian", | |
"❄️milfoil", | |
"❄️protectingly", | |
"❄️householder", | |
"❄️cathedra", | |
"❄️calmingly", | |
"❄️tordrillite", | |
"❄️rearhorse", | |
"❄️Leonard", | |
"❄️maracock", | |
"❄️youngish", | |
"❄️kammererite", | |
"❄️metanephric", | |
"❄️Sageretia", | |
"❄️diplococcoid", | |
"❄️accelerative", | |
"❄️choreal", | |
"❄️metalogical", | |
"❄️recombination", | |
"❄️unimprison", | |
"❄️invocation", | |
"❄️syndetic", | |
"❄️toadback", | |
"❄️vaned", | |
"❄️cupholder", | |
"❄️metropolitanship", | |
"❄️paramandelic", | |
"❄️dermolysis", | |
"❄️Sheriyat", | |
"❄️rhabdus", | |
"❄️seducee", | |
"❄️encrinoid", | |
"❄️unsuppliable", | |
"❄️cololite", | |
"❄️timesaver", | |
"❄️preambulate", | |
"❄️sampling", | |
"❄️roaster", | |
"❄️springald", | |
"❄️densher", | |
"❄️protraditional", | |
"❄️naturalesque", | |
"❄️Hydrodamalis", | |
"❄️cytogenic", | |
"❄️shortly", | |
"❄️cryptogrammatical", | |
"❄️squat", | |
"❄️genual", | |
"❄️backspier", | |
"❄️solubleness", | |
"❄️macroanalytical", | |
"❄️overcovetousness", | |
"❄️Natalie", | |
"❄️cuprobismutite", | |
"❄️phratriac", | |
"❄️Montanize", | |
"❄️hymnologist", | |
"❄️karyomiton", | |
"❄️podger", | |
"❄️unofficiousness", | |
"❄️antisplasher", | |
"❄️supraclavicular", | |
"❄️calidity", | |
"❄️disembellish", | |
"❄️antepredicament", | |
"❄️recurvirostral", | |
"❄️pulmonifer", | |
"❄️coccidial", | |
"❄️botonee", | |
"❄️protoglobulose", | |
"❄️isonym", | |
"❄️myeloid", | |
"❄️premiership", | |
"❄️unmonopolize", | |
"❄️unsesquipedalian", | |
"❄️unfelicitously", | |
"❄️theftbote", | |
"❄️undauntable", | |
"❄️lob", | |
"❄️praenomen", | |
"❄️underriver", | |
"❄️gorfly", | |
"❄️pluckage", | |
"❄️radiovision", | |
"❄️tyrantship", | |
"❄️fraught", | |
"❄️doppelkummel", | |
"❄️rowan", | |
"❄️allosyndetic", | |
"❄️kinesiology", | |
"❄️psychopath", | |
"❄️arrent", | |
"❄️amusively", | |
"❄️preincorporation", | |
"❄️Montargis", | |
"❄️pentacron", | |
"❄️neomedievalism", | |
"❄️sima", | |
"❄️lichenicolous", | |
"❄️Ecclesiastes", | |
"❄️woofed", | |
"❄️cardinalist", | |
"❄️sandaracin", | |
"❄️gymnasial", | |
"❄️lithoglyptics", | |
"❄️centimeter", | |
"❄️quadrupedous", | |
"❄️phraseology", | |
"❄️tumuli", | |
"❄️ankylotomy", | |
"❄️myrtol", | |
"❄️cohibitive", | |
"❄️lepospondylous", | |
"❄️silvendy", | |
"❄️inequipotential", | |
"❄️entangle", | |
"❄️raveling", | |
"❄️Zeugobranchiata", | |
"❄️devastating", | |
"❄️grainage", | |
"❄️amphisbaenian", | |
"❄️blady", | |
"❄️cirrose", | |
"❄️proclericalism", | |
"❄️governmentalist", | |
"❄️carcinomorphic", | |
"❄️nurtureship", | |
"❄️clancular", | |
"❄️unsteamed", | |
"❄️discernibly", | |
"❄️pleurogenic", | |
"❄️impalpability", | |
"❄️Azotobacterieae", | |
"❄️sarcoplasmic", | |
"❄️alternant", | |
"❄️fitly", | |
"❄️acrorrheuma", | |
"❄️shrapnel", | |
"❄️pastorize", | |
"❄️gulflike", | |
"❄️foreglow", | |
"❄️unrelated", | |
"❄️cirriped", | |
"❄️cerviconasal", | |
"❄️sexuale", | |
"❄️pussyfooter", | |
"❄️gadolinic", | |
"❄️duplicature", | |
"❄️codelinquency", | |
"❄️trypanolysis", | |
"❄️pathophobia", | |
"❄️incapsulation", | |
"❄️nonaerating", | |
"❄️feldspar", | |
"❄️diaphonic", | |
"❄️epiglottic", | |
"❄️depopulator", | |
"❄️wisecracker", | |
"❄️gravitational", | |
"❄️kuba", | |
"❄️lactesce", | |
"❄️Toxotes", | |
"❄️periomphalic", | |
"❄️singstress", | |
"❄️fannier", | |
"❄️counterformula", | |
"❄️Acemetae", | |
"❄️repugnatorial", | |
"❄️collimator", | |
"❄️Acinetina", | |
"❄️unpeace", | |
"❄️drum", | |
"❄️tetramorphic", | |
"❄️descendentalism", | |
"❄️cementer", | |
"❄️supraloral", | |
"❄️intercostal", | |
"❄️Nipponize", | |
"❄️negotiator", | |
"❄️vacationless", | |
"❄️synthol", | |
"❄️fissureless", | |
"❄️resoap", | |
"❄️pachycarpous", | |
"❄️reinspiration", | |
"❄️misappropriation", | |
"❄️disdiazo", | |
"❄️unheatable", | |
"❄️streng", | |
"❄️Detroiter", | |
"❄️infandous", | |
"❄️loganiaceous", | |
"❄️desugar", | |
"❄️Matronalia", | |
"❄️myxocystoma", | |
"❄️Gandhiism", | |
"❄️kiddier", | |
"❄️relodge", | |
"❄️counterreprisal", | |
"❄️recentralize", | |
"❄️foliously", | |
"❄️reprinter", | |
"❄️gender", | |
"❄️edaciousness", | |
"❄️chondriomite", | |
"❄️concordant", | |
"❄️stockrider", | |
"❄️pedary", | |
"❄️shikra", | |
"❄️blameworthiness", | |
"❄️vaccina", | |
"❄️Thamnophilinae", | |
"❄️wrongwise", | |
"❄️unsuperannuated", | |
"❄️convalescency", | |
"❄️intransmutable", | |
"❄️dropcloth", | |
"❄️Ceriomyces", | |
"❄️ponderal", | |
"❄️unstentorian", | |
"❄️mem", | |
"❄️deceleration", | |
"❄️ethionic", | |
"❄️untopped", | |
"❄️wetback", | |
"❄️bebar", | |
"❄️undecaying", | |
"❄️shoreside", | |
"❄️energize", | |
"❄️presacral", | |
"❄️undismay", | |
"❄️agricolite", | |
"❄️cowheart", | |
"❄️hemibathybian", | |
"❄️postexilian", | |
"❄️Phacidiaceae", | |
"❄️offing", | |
"❄️redesignation", | |
"❄️skeptically", | |
"❄️physicianless", | |
"❄️bronchopathy", | |
"❄️marabuto", | |
"❄️proprietory", | |
"❄️unobtruded", | |
"❄️funmaker", | |
"❄️plateresque", | |
"❄️preadventure", | |
"❄️beseeching", | |
"❄️cowpath", | |
"❄️pachycephalia", | |
"❄️arthresthesia", | |
"❄️supari", | |
"❄️lengthily", | |
"❄️Nepa", | |
"❄️liberation", | |
"❄️nigrify", | |
"❄️belfry", | |
"❄️entoolitic", | |
"❄️bazoo", | |
"❄️pentachromic", | |
"❄️distinguishable", | |
"❄️slideable", | |
"❄️galvanoscope", | |
"❄️remanage", | |
"❄️cetene", | |
"❄️bocardo", | |
"❄️consummation", | |
"❄️boycottism", | |
"❄️perplexity", | |
"❄️astay", | |
"❄️Gaetuli", | |
"❄️periplastic", | |
"❄️consolidator", | |
"❄️sluggarding", | |
"❄️coracoscapular", | |
"❄️anangioid", | |
"❄️oxygenizer", | |
"❄️Hunanese", | |
"❄️seminary", | |
"❄️periplast", | |
"❄️Corylus", | |
"❄️unoriginativeness", | |
"❄️persecutee", | |
"❄️tweaker", | |
"❄️silliness", | |
"❄️Dabitis", | |
"❄️facetiousness", | |
"❄️thymy", | |
"❄️nonimperial", | |
"❄️mesoblastema", | |
"❄️turbiniform", | |
"❄️churchway", | |
"❄️cooing", | |
"❄️frithbot", | |
"❄️concomitantly", | |
"❄️stalwartize", | |
"❄️clingfish", | |
"❄️hardmouthed", | |
"❄️parallelepipedonal", | |
"❄️coracoacromial", | |
"❄️factuality", | |
"❄️curtilage", | |
"❄️arachnoidean", | |
"❄️semiaridity", | |
"❄️phytobacteriology", | |
"❄️premastery", | |
"❄️hyperpurist", | |
"❄️mobed", | |
"❄️opportunistic", | |
"❄️acclimature", | |
"❄️outdistance", | |
"❄️sophister", | |
"❄️condonement", | |
"❄️oxygenerator", | |
"❄️acetonic", | |
"❄️emanatory", | |
"❄️periphlebitis", | |
"❄️nonsociety", | |
"❄️spectroradiometric", | |
"❄️superaverage", | |
"❄️cleanness", | |
"❄️posteroventral", | |
"❄️unadvised", | |
"❄️unmistakedly", | |
"❄️pimgenet", | |
"❄️auresca", | |
"❄️overimitate", | |
"❄️dipnoan", | |
"❄️chromoxylograph", | |
"❄️triakistetrahedron", | |
"❄️Suessiones", | |
"❄️uncopiable", | |
"❄️oligomenorrhea", | |
"❄️fribbling", | |
"❄️worriable", | |
"❄️flot", | |
"❄️ornithotrophy", | |
"❄️phytoteratology", | |
"❄️setup", | |
"❄️lanneret", | |
"❄️unbraceleted", | |
"❄️gudemother", | |
"❄️Spica", | |
"❄️unconsolatory", | |
"❄️recorruption", | |
"❄️premenstrual", | |
"❄️subretinal", | |
"❄️millennialist", | |
"❄️subjectibility", | |
"❄️rewardproof", | |
"❄️counterflight", | |
"❄️pilomotor", | |
"❄️carpetbaggery", | |
"❄️macrodiagonal", | |
"❄️slim", | |
"❄️indiscernible", | |
"❄️cuckoo", | |
"❄️moted", | |
"❄️controllingly", | |
"❄️gynecopathy", | |
"❄️porrectus", | |
"❄️wanworth", | |
"❄️lutfisk", | |
"❄️semiprivate", | |
"❄️philadelphy", | |
"❄️abdominothoracic", | |
"❄️coxcomb", | |
"❄️dambrod", | |
"❄️Metanemertini", | |
"❄️balminess", | |
"❄️homotypy", | |
"❄️waremaker", | |
"❄️absurdity", | |
"❄️gimcrack", | |
"❄️asquat", | |
"❄️suitable", | |
"❄️perimorphous", | |
"❄️kitchenwards", | |
"❄️pielum", | |
"❄️salloo", | |
"❄️paleontologic", | |
"❄️Olson", | |
"❄️Tellinidae", | |
"❄️ferryman", | |
"❄️peptonoid", | |
"❄️Bopyridae", | |
"❄️fallacy", | |
"❄️ictuate", | |
"❄️aguinaldo", | |
"❄️rhyodacite", | |
"❄️Ligydidae", | |
"❄️galvanometric", | |
"❄️acquisitor", | |
"❄️muscology", | |
"❄️hemikaryon", | |
"❄️ethnobotanic", | |
"❄️postganglionic", | |
"❄️rudimentarily", | |
"❄️replenish", | |
"❄️phyllorhine", | |
"❄️popgunnery", | |
"❄️summar", | |
"❄️quodlibetary", | |
"❄️xanthochromia", | |
"❄️autosymbolically", | |
"❄️preloreal", | |
"❄️extent", | |
"❄️strawberry", | |
"❄️immortalness", | |
"❄️colicwort", | |
"❄️frisca", | |
"❄️electiveness", | |
"❄️heartbroken", | |
"❄️affrightingly", | |
"❄️reconfiscation", | |
"❄️jacchus", | |
"❄️imponderably", | |
"❄️semantics", | |
"❄️beennut", | |
"❄️paleometeorological", | |
"❄️becost", | |
"❄️timberwright", | |
"❄️resuppose", | |
"❄️syncategorematical", | |
"❄️cytolymph", | |
"❄️steinbok", | |
"❄️explantation", | |
"❄️hyperelliptic", | |
"❄️antescript", | |
"❄️blowdown", | |
"❄️antinomical", | |
"❄️caravanserai", | |
"❄️unweariedly", | |
"❄️isonymic", | |
"❄️keratoplasty", | |
"❄️vipery", | |
"❄️parepigastric", | |
"❄️endolymphatic", | |
"❄️Londonese", | |
"❄️necrotomy", | |
"❄️angelship", | |
"❄️Schizogregarinida", | |
"❄️steeplebush", | |
"❄️sparaxis", | |
"❄️connectedness", | |
"❄️tolerance", | |
"❄️impingent", | |
"❄️agglutinin", | |
"❄️reviver", | |
"❄️hieroglyphical", | |
"❄️dialogize", | |
"❄️coestate", | |
"❄️declamatory", | |
"❄️ventilation", | |
"❄️tauromachy", | |
"❄️cotransubstantiate", | |
"❄️pome", | |
"❄️underseas", | |
"❄️triquadrantal", | |
"❄️preconfinemnt", | |
"❄️electroindustrial", | |
"❄️selachostomous", | |
"❄️nongolfer", | |
"❄️mesalike", | |
"❄️hamartiology", | |
"❄️ganglioblast", | |
"❄️unsuccessive", | |
"❄️yallow", | |
"❄️bacchanalianly", | |
"❄️platydactyl", | |
"❄️Bucephala", | |
"❄️ultraurgent", | |
"❄️penalist", | |
"❄️catamenial", | |
"❄️lynnhaven", | |
"❄️unrelevant", | |
"❄️lunkhead", | |
"❄️metropolitan", | |
"❄️hydro", | |
"❄️outsoar", | |
"❄️vernant", | |
"❄️interlanguage", | |
"❄️catarrhal", | |
"❄️Ionicize", | |
"❄️keelless", | |
"❄️myomantic", | |
"❄️booker", | |
"❄️Xanthomonas", | |
"❄️unimpeded", | |
"❄️overfeminize", | |
"❄️speronaro", | |
"❄️diaconia", | |
"❄️overholiness", | |
"❄️liquefacient", | |
"❄️Spartium", | |
"❄️haggly", | |
"❄️albumose", | |
"❄️nonnecessary", | |
"❄️sulcalization", | |
"❄️decapitate", | |
"❄️cellated", | |
"❄️unguirostral", | |
"❄️trichiurid", | |
"❄️loveproof", | |
"❄️amakebe", | |
"❄️screet", | |
"❄️arsenoferratin", | |
"❄️unfrizz", | |
"❄️undiscoverable", | |
"❄️procollectivistic", | |
"❄️tractile", | |
"❄️Winona", | |
"❄️dermostosis", | |
"❄️eliminant", | |
"❄️scomberoid", | |
"❄️tensile", | |
"❄️typesetting", | |
"❄️xylic", | |
"❄️dermatopathology", | |
"❄️cycloplegic", | |
"❄️revocable", | |
"❄️fissate", | |
"❄️afterplay", | |
"❄️screwship", | |
"❄️microerg", | |
"❄️bentonite", | |
"❄️stagecoaching", | |
"❄️beglerbeglic", | |
"❄️overcharitably", | |
"❄️Plotinism", | |
"❄️Veddoid", | |
"❄️disequalize", | |
"❄️cytoproct", | |
"❄️trophophore", | |
"❄️antidote", | |
"❄️allerion", | |
"❄️famous", | |
"❄️convey", | |
"❄️postotic", | |
"❄️rapillo", | |
"❄️cilectomy", | |
"❄️penkeeper", | |
"❄️patronym", | |
"❄️bravely", | |
"❄️ureteropyelitis", | |
"❄️Hildebrandine", | |
"❄️missileproof", | |
"❄️Conularia", | |
"❄️deadening", | |
"❄️Conrad", | |
"❄️pseudochylous", | |
"❄️typologically", | |
"❄️strummer", | |
"❄️luxuriousness", | |
"❄️resublimation", | |
"❄️glossiness", | |
"❄️hydrocauline", | |
"❄️anaglyph", | |
"❄️personifiable", | |
"❄️seniority", | |
"❄️formulator", | |
"❄️datiscaceous", | |
"❄️hydracrylate", | |
"❄️Tyranni", | |
"❄️Crawthumper", | |
"❄️overprove", | |
"❄️masher", | |
"❄️dissonance", | |
"❄️Serpentinian", | |
"❄️malachite", | |
"❄️interestless", | |
"❄️stchi", | |
"❄️ogum", | |
"❄️polyspermic", | |
"❄️archegoniate", | |
"❄️precogitation", | |
"❄️Alkaphrah", | |
"❄️craggily", | |
"❄️delightfulness", | |
"❄️bioplast", | |
"❄️diplocaulescent", | |
"❄️neverland", | |
"❄️interspheral", | |
"❄️chlorhydric", | |
"❄️forsakenly", | |
"❄️scandium", | |
"❄️detubation", | |
"❄️telega", | |
"❄️Valeriana", | |
"❄️centraxonial", | |
"❄️anabolite", | |
"❄️neger", | |
"❄️miscellanea", | |
"❄️whalebacker", | |
"❄️stylidiaceous", | |
"❄️unpropelled", | |
"❄️Kennedya", | |
"❄️Jacksonite", | |
"❄️ghoulish", | |
"❄️Dendrocalamus", | |
"❄️paynimhood", | |
"❄️rappist", | |
"❄️unluffed", | |
"❄️falling", | |
"❄️Lyctus", | |
"❄️uncrown", | |
"❄️warmly", | |
"❄️pneumatism", | |
"❄️Morisonian", | |
"❄️notate", | |
"❄️isoagglutinin", | |
"❄️Pelidnota", | |
"❄️previsit", | |
"❄️contradistinctly", | |
"❄️utter", | |
"❄️porometer", | |
"❄️gie", | |
"❄️germanization", | |
"❄️betwixt", | |
"❄️prenephritic", | |
"❄️underpier", | |
"❄️Eleutheria", | |
"❄️ruthenious", | |
"❄️convertor", | |
"❄️antisepsin", | |
"❄️winterage", | |
"❄️tetramethylammonium", | |
"❄️Rockaway", | |
"❄️Penaea", | |
"❄️prelatehood", | |
"❄️brisket", | |
"❄️unwishful", | |
"❄️Minahassa", | |
"❄️Briareus", | |
"❄️semiaxis", | |
"❄️disintegrant", | |
"❄️peastick", | |
"❄️iatromechanical", | |
"❄️fastus", | |
"❄️thymectomy", | |
"❄️ladyless", | |
"❄️unpreened", | |
"❄️overflutter", | |
"❄️sicker", | |
"❄️apsidally", | |
"❄️thiazine", | |
"❄️guideway", | |
"❄️pausation", | |
"❄️tellinoid", | |
"❄️abrogative", | |
"❄️foraminulate", | |
"❄️omphalos", | |
"❄️Monorhina", | |
"❄️polymyarian", | |
"❄️unhelpful", | |
"❄️newslessness", | |
"❄️oryctognosy", | |
"❄️octoradial", | |
"❄️doxology", | |
"❄️arrhythmy", | |
"❄️gugal", | |
"❄️mesityl", | |
"❄️hexaplaric", | |
"❄️Cabirian", | |
"❄️hordeiform", | |
"❄️eddyroot", | |
"❄️internarial", | |
"❄️deservingness", | |
"❄️jawbation", | |
"❄️orographically", | |
"❄️semiprecious", | |
"❄️seasick", | |
"❄️thermically", | |
"❄️grew", | |
"❄️tamability", | |
"❄️egotistically", | |
"❄️fip", | |
"❄️preabsorbent", | |
"❄️leptochroa", | |
"❄️ethnobotany", | |
"❄️podolite", | |
"❄️egoistic", | |
"❄️semitropical", | |
"❄️cero", | |
"❄️spinelessness", | |
"❄️onshore", | |
"❄️omlah", | |
"❄️tintinnabulist", | |
"❄️machila", | |
"❄️entomotomy", | |
"❄️nubile", | |
"❄️nonscholastic", | |
"❄️burnt", | |
"❄️Alea", | |
"❄️befume", | |
"❄️doctorless", | |
"❄️Napoleonic", | |
"❄️scenting", | |
"❄️apokreos", | |
"❄️cresylene", | |
"❄️paramide", | |
"❄️rattery", | |
"❄️disinterested", | |
"❄️idiopathetic", | |
"❄️negatory", | |
"❄️fervid", | |
"❄️quintato", | |
"❄️untricked", | |
"❄️Metrosideros", | |
"❄️mescaline", | |
"❄️midverse", | |
"❄️Musophagidae", | |
"❄️fictionary", | |
"❄️branchiostegous", | |
"❄️yoker", | |
"❄️residuum", | |
"❄️culmigenous", | |
"❄️fleam", | |
"❄️suffragism", | |
"❄️Anacreon", | |
"❄️sarcodous", | |
"❄️parodistic", | |
"❄️writmaking", | |
"❄️conversationism", | |
"❄️retroposed", | |
"❄️tornillo", | |
"❄️presuspect", | |
"❄️didymous", | |
"❄️Saumur", | |
"❄️spicing", | |
"❄️drawbridge", | |
"❄️cantor", | |
"❄️incumbrancer", | |
"❄️heterospory", | |
"❄️Turkeydom", | |
"❄️anteprandial", | |
"❄️neighborship", | |
"❄️thatchless", | |
"❄️drepanoid", | |
"❄️lusher", | |
"❄️paling", | |
"❄️ecthlipsis", | |
"❄️heredosyphilitic", | |
"❄️although", | |
"❄️garetta", | |
"❄️temporarily", | |
"❄️Monotropa", | |
"❄️proglottic", | |
"❄️calyptro", | |
"❄️persiflage", | |
"❄️degradable", | |
"❄️paraspecific", | |
"❄️undecorative", | |
"❄️Pholas", | |
"❄️myelon", | |
"❄️resteal", | |
"❄️quadrantly", | |
"❄️scrimped", | |
"❄️airer", | |
"❄️deviless", | |
"❄️caliciform", | |
"❄️Sefekhet", | |
"❄️shastaite", | |
"❄️togate", | |
"❄️macrostructure", | |
"❄️bipyramid", | |
"❄️wey", | |
"❄️didynamy", | |
"❄️knacker", | |
"❄️swage", | |
"❄️supermanism", | |
"❄️epitheton", | |
"❄️overpresumptuous" | |
] | |
public func run_SortStringsUnicode(_ N: Int) { | |
for _ in 1...5*N { | |
benchSortStrings(unicodeWords) | |
} | |
} | |
@inline(never) | |
func buildString(_ i: String, reservingCapacity: Bool = false) -> String { | |
var sb = getString(i) | |
if reservingCapacity { | |
sb.reserveCapacity(10) | |
} | |
for str in ["b","c","d","pizza"] { | |
sb += str | |
} | |
return sb | |
} | |
@inline(never) | |
public func run_StringBuilder(_ N: Int) { | |
for _ in 1...5000*N { | |
blackHole(buildString("a")) | |
} | |
} | |
@inline(never) | |
public func run_StringBuilderSmallReservingCapacity(_ N: Int) { | |
for _ in 1...5000*N { | |
blackHole(buildString("a", reservingCapacity: true)) | |
} | |
} | |
@inline(never) | |
func addString(_ i: String) -> String { | |
let s = getString(i) + "b" + "c" + "d" + "pizza" | |
return s | |
} | |
@inline(never) | |
public func run_StringAdder(_ N: Int) { | |
for _ in 1...5000*N { | |
blackHole(addString("a")) | |
} | |
} | |
@inline(never) | |
func buildStringUTF16(_ i: String) -> String { | |
var sb = getString(i) | |
for str in ["🎉","c","d","pizza"] { | |
sb += str | |
} | |
return sb | |
} | |
@inline(never) | |
func buildStringFromSmallSubstrings(_ i: String) -> String { | |
var sb = getString(i) | |
for str in ["_🎉","cd","de","pizza"] { | |
sb += str.dropFirst() | |
} | |
return sb | |
} | |
@inline(never) | |
public func run_StringUTF16Builder(_ N: Int) { | |
for _ in 1...5000*N { | |
blackHole(buildStringUTF16("a")) | |
} | |
} | |
@inline(never) | |
public func run_StringUTF16SubstringBuilder(_ N: Int) { | |
for _ in 1...5000*N { | |
blackHole(buildStringFromSmallSubstrings("a")) | |
} | |
} | |
func getLongString() -> String { | |
let long = """ | |
Swift is a multi-paradigm, compiled programming language created for | |
iOS, OS X, watchOS, tvOS and Linux development by Apple Inc. Swift is | |
designed to work with Apple's Cocoa and Cocoa Touch frameworks and the | |
large body of existing Objective-C code written for Apple products. Swift | |
is intended to be more resilient to erroneous code (\"safer\") than | |
Objective-C and also more concise. It is built with the LLVM compiler | |
framework included in Xcode 6 and later and uses the Objective-C runtime, | |
which allows C, Objective-C, C++ and Swift code to run within a single | |
program. | |
""" | |
return getString(long) | |
} | |
@inline(never) | |
func buildStringLong(_ i: String) -> String { | |
var sb = getString(i) | |
sb += getLongString() | |
return sb | |
} | |
@inline(never) | |
func buildStringWithLongSubstring(_ i: String) -> String { | |
var sb = getString(i) | |
sb += getLongString().dropFirst() | |
return sb | |
} | |
@inline(never) | |
public func run_StringBuilderLong(_ N: Int) { | |
for _ in 1...5000*N { | |
blackHole(buildStringLong("👻")) | |
} | |
} | |
@inline(never) | |
public func run_StringBuilderWithLongSubstring(_ N: Int) { | |
for _ in 1...5000*N { | |
blackHole(buildStringWithLongSubstring("👻")) | |
} | |
} | |
@inline(never) | |
func buildString( | |
word: String, | |
count: Int, | |
reservingCapacity: Bool | |
) -> String { | |
let word = getString(word) | |
var sb = "" | |
if reservingCapacity { | |
sb.reserveCapacity(count * word.unicodeScalars.count) | |
} | |
for _ in 0 ..< count { | |
sb += word | |
} | |
return sb | |
} | |
@inline(never) | |
public func run_StringWordBuilder(_ N: Int) { | |
blackHole(buildString( | |
word: "bumfuzzle", count: 50_000 * N, reservingCapacity: false)) | |
} | |
@inline(never) | |
public func run_StringWordBuilderReservingCapacity(_ N: Int) { | |
blackHole(buildString( | |
word: "bumfuzzle", count: 50_000 * N, reservingCapacity: true)) | |
} | |
@inline(never) | |
public func run_StrComplexWalk(_ N: Int) { | |
var s = "निरन्तरान्धकारिता-दिगन्तर-कन्दलदमन्द-सुधारस-बिन्दु-सान्द्रतर-घनाघन-वृन्द-सन्देहकर-स्यन्दमान-मकरन्द-बिन्दु-बन्धुरतर-माकन्द-तरु-कुल-तल्प-कल्प-मृदुल-सिकता-जाल-जटिल-मूल-तल-मरुवक-मिलदलघु-लघु-लय-कलित-रमणीय-पानीय-शालिका-बालिका-करार-विन्द-गलन्तिका-गलदेला-लवङ्ग-पाटल-घनसार-कस्तूरिकातिसौरभ-मेदुर-लघुतर-मधुर-शीतलतर-सलिलधारा-निराकरिष्णु-तदीय-विमल-विलोचन-मयूख-रेखापसारित-पिपासायास-पथिक-लोकान्" | |
let ref_result = 379 | |
for _ in 1...2000*N { | |
var count = 0 | |
for _ in s.unicodeScalars { | |
count += 1 | |
} | |
CheckResults(count == ref_result) | |
} | |
} | |
struct Workload { | |
static let N = 100 | |
let name: String | |
let payload: [String] | |
var scaleMultiplier: Double | |
init(name: String, payload: [String], scaleMultiplier: Double = 1.0) { | |
self.name = name | |
self.payload = payload | |
self.scaleMultiplier = scaleMultiplier | |
} | |
var tripCount: Int { | |
return Int(Double(Workload.N) * scaleMultiplier) | |
} | |
static let ascii = Workload( | |
name: "ASCII", | |
payload: """ | |
woodshed | |
lakism | |
gastroperiodynia | |
afetal | |
Casearia | |
ramsch | |
Nickieben | |
undutifulness | |
decorticate | |
neognathic | |
mentionable | |
tetraphenol | |
pseudonymal | |
dislegitimate | |
Discoidea | |
criminative | |
disintegratory | |
executer | |
Cylindrosporium | |
complimentation | |
Ixiama | |
Araceae | |
silaginoid | |
derencephalus | |
Lamiidae | |
marrowlike | |
ninepin | |
trihemimer | |
semibarbarous | |
heresy | |
existence | |
fretless | |
Amiranha | |
handgravure | |
orthotropic | |
Susumu | |
teleutospore | |
sleazy | |
shapeliness | |
hepatotomy | |
exclusivism | |
stifler | |
cunning | |
isocyanuric | |
pseudepigraphy | |
carpetbagger | |
unglory | |
""".lines(), | |
scaleMultiplier: 0.25 | |
) | |
static let latin1 = Workload( | |
name: "Latin1", | |
payload: """ | |
café | |
résumé | |
caférésumé | |
¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º | |
1+1=3 | |
¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹ | |
¡¢£¤¥¦§¨©ª«¬® | |
»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍ | |
ÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãä | |
åæçèéêëìíîïðñò | |
ÎÏÐÑÒÓÔÕÖëìíîïðñò | |
óôõö÷øùúûüýþÿ | |
123.456£=>¥ | |
123.456 | |
""".lines() | |
) | |
static let fastPrenormal = Workload( | |
name: "FastPrenormal", | |
payload: """ | |
ĀāĂ㥹ĆćĈĉĊċČčĎďĐđĒēĔĕĖėĘęĚěĜĝĞğĠġĢģĤĥ | |
ĦħĨĩĪīĬĭĮįİıIJijĴĵĶķĸ | |
ĹĺĻļĽľĿŀŁłŃńŅņŇňʼnŊŋŌōŎŏŐőŒœŔŕŖŗŘřŚśŜŝŞşŠšŢţŤťŦŧŨũŪūŬŭŮůŰűŲ | |
ųŴŵŶŷŸŹźŻżŽžſƀƁƂƃƄƅƆ | |
ƇƈƉƊƋƌƍƎƏƐƑƒƓƔƕƖƗƘƙƚƛƜƝƞƟƠơƢƣƤƥƦƧƨƩƪƫƬƭƮƯưƱƲƳƴƵƶƷƸƹƺƻƼƽƾƿǀ | |
Ƈ | |
ǁǂǃDŽDždžLJLjljNJNjnjǍǎǏǐǑǒǓǔǕǖ | |
ǗǘǙǚǛǜǝǞǟǠǡǢǣǤǥǦǧǨǩǪǫǬǭǮǯǰDZDzdzǴǵǶǷǸǹǺǻǼǽǾǿȀȁȂȃȄȅȆȇȈȉȊȋȌȍȎȏȐȑ | |
ȒȓȔȕȖȗȘșȚțȜȝȞȟȠȡȢȣȤȥȦȧȨȩȪȫȬ | |
ȒȓȔȕȖȗȘșȚțȜȝȞȟȠȡȢȣȤȥȦȧȨȩȪȫȬDzdzǴǵǶǷǸǹǺǻǼǽǾǿȀȁȂȃȄȅȆȇȈȉȊȋȌȍȎȏȐȑ | |
ȭȮȯȰȱȲȳȴȵȶȷȸȹȺȻȼȽȾȿɀɁɂɃɄɅɆɇɈɉɊɋɌɍɎɏɐɑɒɓɔɕɖɗɘəɚɛɜɝɞɟɠɡɢɣɤɥɦɧɨɩɪɫɬɭɮɯɰ | |
ɱɲɳɴɵɶɷɸɹɺɻɼɽɾɿʀʁʂʃʄ | |
ɱɲɳɴɵɶɷɸɹɺɻɼɽɾɿʀʁʂʃ | |
ʅʆʇʈʉʊʋʌʍʎʏʐʑʒʓʔʕʖʗʘʙʚʛʜʝʞʟʠʡʢʣʤʥʦʧʨʩʪʫʬʭʮʯʰ | |
ʱʲʳʴʵʶʷʸʹʺʻʼʽʾʿˀˁ˂˃˄˅ˆˇˈˉˊˋˌˍˎˏːˑ˒˓˔˕˖˗˘˙˚˛˜˝˞˟ˠˡˢˣˤ˥˦ | |
˧˨˩˪˫ˬ˭ˮ˯˰˱˲˳˴˵˶˷˸˹˺˻˼˽˾ | |
""".lines() | |
) | |
static let slowerPrenormal = Workload( | |
name: "SlowerPrenormal", | |
payload: """ | |
Swiftに大幅な改良が施され、 | |
安定していてしかも | |
直感的に使うことができる | |
向けプログラミング言語になりました。 | |
이번 업데이트에서는 강력하면서도 | |
\u{201c}Hello\u{2010}world\u{2026}\u{201d} | |
平台的编程语言 | |
功能强大且直观易用 | |
而本次更新对其进行了全面优化 | |
в чащах юга жил-был цитрус | |
\u{300c}\u{300e}今日は\u{3001}世界\u{3002}\u{300f}\u{300d} | |
но фальшивый экземпляр | |
""".lines() | |
) | |
// static let slowestPrenormal = """ | |
// """.lines() | |
static let nonBMPSlowestPrenormal = Workload( | |
name: "NonBMPSlowestPrenormal", | |
payload: """ | |
𓀀𓀤𓁓𓁲𓃔𓃗 | |
𓀀𓀁𓀂𓀃𓀄𓀇𓀈𓀉𓀊𓀋𓀌𓀍𓀎𓀏𓀓𓀔𓀕𓀖𓀗𓀘𓀙𓀚𓀛𓀜𓀞𓀟𓀠𓀡𓀢𓀣 | |
𓀤𓀥𓀦𓀧𓀨𓀩𓀪𓀫𓀬𓀭 | |
𓁡𓁢𓁣𓁤𓁥𓁦𓁧𓁨𓁩𓁫𓁬𓁭𓁮𓁯𓁰𓁱𓁲𓁳𓁴𓁵𓁶𓁷𓁸 | |
𓁹𓁺𓁓𓁔𓁕𓁻𓁼𓁽𓁾𓁿 | |
𓀀𓀁𓀂𓀃𓀄𓃒𓃓𓃔𓃕𓃻𓃼𓃽𓃾𓃿𓄀𓄁𓄂𓄃𓄄𓄅𓄆𓄇𓄈𓄉𓄊𓄋𓄌𓄍𓄎 | |
𓂿𓃀𓃁𓃂𓃃𓃄𓃅 | |
𓃘𓃙𓃚𓃛𓃠𓃡𓃢𓃣𓃦𓃧𓃨𓃩𓃬𓃭𓃮𓃯𓃰𓃲𓃳𓃴𓃵𓃶𓃷𓃸 | |
𓃘𓃙𓃚𓃛𓃠𓃡𓃢𓃣𓃦𓃧𓃨𓃩𓃬𓃭𓃮𓃯𓃰𓃲𓃳𓃴𓃵𓃶𓃷 | |
𓀀𓀁𓀂𓀃𓀄𓆇𓆈𓆉𓆊𓆋𓆌𓆍𓆎𓆏𓆐𓆑𓆒𓆓𓆔𓆗𓆘𓆙𓆚𓆛𓆝𓆞𓆟𓆠𓆡𓆢𓆣𓆤 | |
𓆥𓆦𓆧𓆨𓆩𓆪𓆫𓆬𓆭𓆮𓆯𓆰𓆱𓆲𓆳𓆴𓆵𓆶𓆷𓆸𓆹𓆺𓆻 | |
""".lines() | |
) | |
static let emoji = Workload( | |
name: "Emoji", | |
payload: """ | |
👍👩👩👧👧👨👨👦👦🇺🇸🇨🇦🇲🇽👍🏻👍🏼👍🏽👍🏾👍🏿 | |
👍👩👩👧👧👨👨👦👦🇺🇸🇨🇦🇲🇽👍🏿👍🏻👍🏼👍🏽👍🏾 | |
😀🧀😀😃😄😁🤣😂😅😆 | |
😺🎃🤖👾😸😹😻😼😾😿🙀😽🙌🙏🤝👍✌🏽 | |
☺️😊😇🙂😍😌😉🙃😘😗😙😚😛😝😜 | |
😋🤑🤗🤓😎😒😏🤠🤡😞😔😟😕😖😣☹️🙁😫😩😤😠😑😐😶😡😯 | |
😦😧😮😱😳😵😲😨😰😢😥 | |
😪😓😭🤤😴🙄🤔🤥🤧🤢🤐😬😷🤒🤕😈💩👺👹👿👻💀☠️👽 | |
""".lines() | |
) | |
static let abnormal = Workload( | |
name: "Abnormal", | |
payload: """ | |
ae\u{301}ae\u{301}ae\u{302}ae\u{303}ae\u{304}ae\u{305}ae\u{306}ae\u{307} | |
ae\u{301}ae\u{301}ae\u{301}ae\u{301}ae\u{301}ae\u{301}ae\u{301}ae\u{300} | |
\u{f900}\u{f901}\u{f902}\u{f903}\u{f904}\u{f905}\u{f906}\u{f907}\u{f908}\u{f909}\u{f90a} | |
\u{f90b}\u{f90c}\u{f90d}\u{f90e}\u{f90f}\u{f910}\u{f911}\u{f912}\u{f913}\u{f914}\u{f915}\u{f916}\u{f917}\u{f918}\u{f919} | |
\u{f900}\u{f91a}\u{f91b}\u{f91c}\u{f91d}\u{f91e}\u{f91f}\u{f920}\u{f921}\u{f922} | |
""".lines() | |
) | |
// static let pathological = """ | |
// """.lines() | |
static let zalgo = Workload( | |
name: "Zalgo", | |
payload: """ | |
ṭ̴̵̶̷̸̢̧̨̡̛̤̥̦̩̪̫̬̭̮̯̰̖̗̘̙̜̝̞̟̠̱̲̳̹̺̻̼͇͈͉͍͎̀́̂̃̄̅̆̇̈̉ͣͤ̊̋̌̍̎̏̐̑̒̓̔̽̾̿͂͆͊͋͌̕̚͜͟͢͝͞͠͡ͅ͏͓͔͕͖͙͚͐͑͒͗͛ͣͤͥͦͧͨͩͪͫͬͭͮ͘͜͟͢͝͞͠͡ | |
h̀́̂̃ | |
è͇͈͉͍͎́̂̃̄̅̆̇̈̉͊͋͌͏̡̢̧̨̛͓͔͕͖͙͚̖̗̘̙̜̝̞̟̠̣̤̥̦̩̪̫̬̭͇͈͉͍͎͐͑͒͗͛̊̋̌̍̎̏̐̑̒̓̔̀́͂̓̈́͆͊͋͌͘̕̚͜͟͝͞͠ͅ͏͓͔͕͖͐͑͒ | |
q̴̵̶̷̸̡̢̧̨̛̖̗̘̙̜̝̞̟̠̣̤̥̦̩̪̫̬̭̮̯̰̱̲̳̹̺̻̼͇̀́̂̃̄̅̆̇̈̉̊̋̌̍̎̏̐̑̒̓̔̽̾̿͂͆̕̚ͅ | |
ư̴̵̶̷̸̗̘̙̜̹̺̻̼͇͈͉͍͎̽̾̿̀́͂̓̈́͆͊͋͌̚ͅ͏͓͔͕͖͙͚͐͑͒͗͛ͣͤͥͦͧͨͩͪͫͬͭͮ͘͜͟͢͝͞͠͡ | |
ì̡̢̧̨̝̞̟̠̣̤̥̦̩̪̫̬̭̮̯̰̹̺̻̼͇͈͉͍͎́̂̃̄̉̊̋̌̍̎̏̐̑̒̓̽̾̿̀́͂̓̈́͆͊͋͌ͅ͏͓͔͕͖͙͐͑͒͗ͬͭͮ͘ | |
c̴̵̶̷̸̡̢̧̨̛̖̗̘̙̜̝̞̟̠̣̤̥̦̩̪̫̬̭̮̯̰̱̲̳̹̺̻̼̀́̂̃̄̔̽̾̿̀́͂̓̈́͆ͣͤͥͦͧͨͩͪͫͬͭͮ̕̚͢͡ͅ | |
k̴̵̶̷̸̡̢̧̨̛̖̗̘̙̜̝̞̟̠̣̤̥̦̩̪̫̬̭̮̯̰̱̲̳̹̺̻̼͇͈͉͍͎̀́̂̃̄̅̆̇̈̉̊̋̌̍̎̏̐̑̒̓̔̽̾̿͂͆͊͋͌̕̚ͅ͏͓͔͕͖͙͚͐͑͒͗͛ͣͤͥͦͧͨͩͪͫͬͭͮ͘͜͟͢͝͞͠͡ | |
b̴̵̶̷̸̡̢̛̗̘̙̜̝̞̟̠̹̺̻̼͇͈͉͍͎̽̾̿̀́͂̓̈́͆͊͋͌̚ͅ͏͓͔͕͖͙͚͐͑͒͗͛ͣͤͥͦͧͨͩͪͫͬͭͮ͘͜͟͢͝͞͠͡ | |
ŗ̴̵̶̷̸̨̛̩̪̫̯̰̱̲̳̹̺̻̼̬̭̮͇̗̘̙̜̝̞̟̤̥̦͉͍͎̽̾̿̀́͂̓̈́͆͊͋͌̚ͅ͏̡̢͓͔͕͖͙͚̠̣͐͑͒͗͛ͣͤͥͦͧͨͩͪͫͬͭͮ͘͜͟͢͝͞͠͡ | |
o | |
w̗̘͇͈͉͍͎̓̈́͆͊͋͌ͅ͏̛͓͔͕͖͙͚̙̜̹̺̻̼͐͑͒͗͛ͣͤͥͦ̽̾̿̀́͂ͧͨͩͪͫͬͭͮ͘̚͜͟͢͝͞͠͡ | |
n͇͈͉͍͎͊͋͌ͧͨͩͪͫͬͭͮ͏̛͓͔͕͖͙͚̗̘̙̜̹̺̻̼͐͑͒͗͛ͣͤͥͦ̽̾̿̀́͂̓̈́͆ͧͨͩͪͫͬͭͮ͘̚͜͟͢͝͞͠͡ͅ | |
f̛̗̘̙̜̹̺̻̼͇͈͉͍͎̽̾̿̀́͂̓̈́͆͊͋͌̚ͅ͏͓͔͕͖͙͚͐͑͒͗͛ͣͤͥͦ͘͜͟͢͝͞͠͡ | |
ơ̗̘̙̜̹̺̻̼͇͈͉͍͎̽̾̿̀́͂̓̈́͆͊͋͌̚ͅ͏͓͔͕͖͙͚͐͑͒͗͛ͥͦͧͨͩͪͫͬͭͮ͘ | |
xͣͤͥͦͧͨͩͪͫͬͭͮ | |
""".lines(), | |
scaleMultiplier: 0.25 | |
) | |
static let longSharedPrefix = Workload( | |
name: "LongSharedPrefix", | |
payload: """ | |
http://www.dogbook.com/dog/239495828/friends/mutual/2939493815 | |
http://www.dogbook.com/dog/239495828/friends/mutual/3910583739 | |
http://www.dogbook.com/dog/239495828/friends/mutual/3910583739/shared | |
http://www.dogbook.com/dog/239495828/friends/mutual/3910583739/shared | |
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. | |
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. | |
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.🤔 | |
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. | |
🤔Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.🤔 | |
""".lines() | |
) | |
static let longSharedPrefixAbnormal = Workload( | |
name: "LongSharedPrefix", | |
payload: """ | |
http://www.dogbook.com/dog/239495828/friends/mutual/a\u{301}2939493815 | |
http://www.dogbook.com/dog/239495828/friends/mutual/3910583739 | |
http://www.dogbook.com/dog/239495828/friends/mutual/3910583739/shared | |
http://www.dogbook.com/dog/239495828/friends/mutual/3910583739/shared | |
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. | |
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. | |
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.🤔 | |
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. | |
🤔Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.🤔 | |
""".lines() | |
) | |
} | |
var Workload_ascii: Workload! = Workload.ascii | |
@inline(never) | |
public func run_StringComparison_ascii(_ N: Int) { | |
let workload: Workload = Workload_ascii | |
let tripCount = workload.tripCount | |
let payload = workload.payload | |
for _ in 1...tripCount*N { | |
for s1 in payload { | |
for s2 in payload { | |
blackHole(s1 < s2) | |
} | |
} | |
} | |
} | |
@inline(never) | |
public func run_StringHashing_ascii(_ N: Int) { | |
let workload: Workload = Workload.ascii | |
let tripCount = workload.tripCount | |
let payload = workload.payload | |
for _ in 1...tripCount*N { | |
for str in payload { | |
blackHole(str.hashValue) | |
} | |
} | |
} | |
var Workload_latin1: Workload! = Workload.latin1 | |
@inline(never) | |
public func run_StringComparison_latin1(_ N: Int) { | |
let workload: Workload = Workload_latin1 | |
let tripCount = workload.tripCount | |
let payload = workload.payload | |
for _ in 1...tripCount*N { | |
for s1 in payload { | |
for s2 in payload { | |
blackHole(s1 < s2) | |
} | |
} | |
} | |
} | |
@inline(never) | |
public func run_StringHashing_latin1(_ N: Int) { | |
let workload: Workload = Workload.latin1 | |
let tripCount = workload.tripCount | |
let payload = workload.payload | |
for _ in 1...tripCount*N { | |
for str in payload { | |
blackHole(str.hashValue) | |
} | |
} | |
} | |
var Workload_fastPrenormal: Workload! = Workload.fastPrenormal | |
@inline(never) | |
public func run_StringComparison_fastPrenormal(_ N: Int) { | |
let workload: Workload = Workload_fastPrenormal | |
let tripCount = workload.tripCount | |
let payload = workload.payload | |
for _ in 1...tripCount*N { | |
for s1 in payload { | |
for s2 in payload { | |
blackHole(s1 < s2) | |
} | |
} | |
} | |
} | |
@inline(never) | |
public func run_StringHashing_fastPrenormal(_ N: Int) { | |
let workload: Workload = Workload.fastPrenormal | |
let tripCount = workload.tripCount | |
let payload = workload.payload | |
for _ in 1...tripCount*N { | |
for str in payload { | |
blackHole(str.hashValue) | |
} | |
} | |
} | |
var Workload_slowerPrenormal: Workload! = Workload.slowerPrenormal | |
@inline(never) | |
public func run_StringComparison_slowerPrenormal(_ N: Int) { | |
let workload: Workload = Workload_slowerPrenormal | |
let tripCount = workload.tripCount | |
let payload = workload.payload | |
for _ in 1...tripCount*N { | |
for s1 in payload { | |
for s2 in payload { | |
blackHole(s1 < s2) | |
} | |
} | |
} | |
} | |
@inline(never) | |
public func run_StringHashing_slowerPrenormal(_ N: Int) { | |
let workload: Workload = Workload.slowerPrenormal | |
let tripCount = workload.tripCount | |
let payload = workload.payload | |
for _ in 1...tripCount*N { | |
for str in payload { | |
blackHole(str.hashValue) | |
} | |
} | |
} | |
var Workload_nonBMPSlowestPrenormal: Workload! = Workload.nonBMPSlowestPrenormal | |
@inline(never) | |
public func run_StringComparison_nonBMPSlowestPrenormal(_ N: Int) { | |
let workload: Workload = Workload_nonBMPSlowestPrenormal | |
let tripCount = workload.tripCount | |
let payload = workload.payload | |
for _ in 1...tripCount*N { | |
for s1 in payload { | |
for s2 in payload { | |
blackHole(s1 < s2) | |
} | |
} | |
} | |
} | |
@inline(never) | |
public func run_StringHashing_nonBMPSlowestPrenormal(_ N: Int) { | |
let workload: Workload = Workload.nonBMPSlowestPrenormal | |
let tripCount = workload.tripCount | |
let payload = workload.payload | |
for _ in 1...tripCount*N { | |
for str in payload { | |
blackHole(str.hashValue) | |
} | |
} | |
} | |
var Workload_emoji: Workload! = Workload.emoji | |
@inline(never) | |
public func run_StringComparison_emoji(_ N: Int) { | |
let workload: Workload = Workload_emoji | |
let tripCount = workload.tripCount | |
let payload = workload.payload | |
for _ in 1...tripCount*N { | |
for s1 in payload { | |
for s2 in payload { | |
blackHole(s1 < s2) | |
} | |
} | |
} | |
} | |
@inline(never) | |
public func run_StringHashing_emoji(_ N: Int) { | |
let workload: Workload = Workload.emoji | |
let tripCount = workload.tripCount | |
let payload = workload.payload | |
for _ in 1...tripCount*N { | |
for str in payload { | |
blackHole(str.hashValue) | |
} | |
} | |
} | |
var Workload_abnormal: Workload! = Workload.abnormal | |
@inline(never) | |
public func run_StringComparison_abnormal(_ N: Int) { | |
let workload: Workload = Workload_abnormal | |
let tripCount = workload.tripCount | |
let payload = workload.payload | |
for _ in 1...tripCount*N { | |
for s1 in payload { | |
for s2 in payload { | |
blackHole(s1 < s2) | |
} | |
} | |
} | |
} | |
@inline(never) | |
public func run_StringHashing_abnormal(_ N: Int) { | |
let workload: Workload = Workload.abnormal | |
let tripCount = workload.tripCount | |
let payload = workload.payload | |
for _ in 1...tripCount*N { | |
for str in payload { | |
blackHole(str.hashValue) | |
} | |
} | |
} | |
var Workload_zalgo: Workload! = Workload.zalgo | |
@inline(never) | |
public func run_StringComparison_zalgo(_ N: Int) { | |
let workload: Workload = Workload_zalgo | |
let tripCount = workload.tripCount | |
let payload = workload.payload | |
for _ in 1...tripCount*N { | |
for s1 in payload { | |
for s2 in payload { | |
blackHole(s1 < s2) | |
} | |
} | |
} | |
} | |
@inline(never) | |
public func run_StringHashing_zalgo(_ N: Int) { | |
let workload: Workload = Workload.zalgo | |
let tripCount = workload.tripCount | |
let payload = workload.payload | |
for _ in 1...tripCount*N { | |
for str in payload { | |
blackHole(str.hashValue) | |
} | |
} | |
} | |
var Workload_longSharedPrefix: Workload! = Workload.longSharedPrefix | |
@inline(never) | |
public func run_StringComparison_longSharedPrefix(_ N: Int) { | |
let workload: Workload = Workload_longSharedPrefix | |
let tripCount = workload.tripCount | |
let payload = workload.payload | |
for _ in 1...tripCount*N { | |
for s1 in payload { | |
for s2 in payload { | |
blackHole(s1 < s2) | |
} | |
} | |
} | |
} | |
@inline(never) | |
public func run_StringHashing_longSharedPrefix(_ N: Int) { | |
let workload: Workload = Workload.longSharedPrefix | |
let tripCount = workload.tripCount | |
let payload = workload.payload | |
for _ in 1...tripCount*N { | |
for str in payload { | |
blackHole(str.hashValue) | |
} | |
} | |
} | |
struct ParseError: Error { | |
var message: String | |
} | |
let comma = ",".utf16.first! | |
let newline = "\n".utf16.first! | |
let carriageReturn = "\n".utf16.first! | |
let quote = "\"".utf16.first! | |
func parseQuotedField(_ remainder: inout Substring) throws -> Substring? { | |
var result: Substring = "" // we accumulate the result | |
while !remainder.isEmpty { | |
guard let nextQuoteIndex = remainder.firstIndex(of: "\"") else { | |
throw ParseError(message: "Expected a closing \"") | |
} | |
// Append until the next quote | |
result += remainder.prefix(upTo: nextQuoteIndex) | |
remainder.remove(upToAndIncluding: nextQuoteIndex) | |
if let peek = remainder.utf16.first { | |
switch peek { | |
case quote: // two quotes after each other is an escaped quote | |
remainder.removeFirst() | |
result.append("\"") | |
case comma: // field ending | |
remainder.removeFirst() | |
return result | |
default: | |
return result | |
} | |
} else { | |
// End of the string | |
return result | |
} | |
} | |
throw ParseError(message: "Expected a closing quote") | |
} | |
// Consume a single field from `remainder` | |
func parseField(_ remainder: inout Substring) throws -> Substring? { | |
guard let start = remainder.utf16.first else { return nil } | |
switch start { | |
case quote: | |
remainder.removeFirst() // remove the first quote | |
return try parseQuotedField(&remainder) | |
case newline: | |
return nil | |
default: | |
// This is the most common case and should ideally be super fast... | |
var index = remainder.utf16.startIndex | |
while index < remainder.utf16.endIndex { | |
switch remainder.utf16[index] { | |
case comma: | |
defer { remainder.remove(upToAndIncluding: index) } | |
return remainder.prefix(upTo: index) | |
case newline: | |
let result = remainder.prefix(upTo: index) | |
remainder.remove(upTo: index) | |
return result | |
default: | |
remainder.utf16.formIndex(after: &index) | |
} | |
} | |
let result = remainder | |
remainder.removeAll() | |
return result | |
} | |
} | |
extension Substring { | |
mutating func remove(upTo index: Index) { | |
self = suffix(from: index) | |
} | |
mutating func remove(upToAndIncluding index: Index) { | |
self = suffix(from: self.index(after: index)) | |
} | |
} | |
// Consume a single line from `remainder` | |
func parseLine<State>(_ remainder: inout Substring, result: inout State, processField: (inout State, Int, Substring) -> ()) throws -> Bool { | |
var fieldNumber = 0 | |
while let field = try parseField(&remainder) { | |
processField(&result, fieldNumber, field) | |
fieldNumber += 1 | |
} | |
if !remainder.isEmpty { | |
let next = remainder.utf16[remainder.utf16.startIndex] | |
guard next == carriageReturn || next == newline else { | |
throw ParseError(message: "Expected a newline or CR, got \(next)") | |
} | |
while let x = remainder.utf16.first, x == carriageReturn || x == newline { | |
remainder.utf16.removeFirst() | |
} | |
} | |
return !remainder.isEmpty && fieldNumber > 0 | |
} | |
extension String { | |
func parseAlt() -> [[String]] { | |
var result: [[String]] = [[]] | |
var currentField = "".unicodeScalars | |
var inQuotes = false | |
func flush() { | |
result[result.endIndex-1].append(String(currentField)) | |
currentField.removeAll() | |
} | |
for c in self.unicodeScalars { | |
switch (c, inQuotes) { | |
case (",", false): | |
flush() | |
case ("\n", false): | |
flush() | |
result.append([]) | |
case ("\"", _): | |
inQuotes = !inQuotes | |
currentField.append(c) | |
default: | |
currentField.append(c) | |
} | |
} | |
flush() | |
return result | |
} | |
func parseAltIndices() -> [[Substring]] { | |
var result: [[Substring]] = [[]] | |
var fieldStart = self.startIndex | |
var inQuotes = false | |
func flush(endingAt end: Index) { | |
result[result.endIndex-1].append(self[fieldStart..<end]) | |
} | |
for i in self.unicodeScalars.indices { | |
switch (self.unicodeScalars[i], inQuotes) { | |
case (",", false): | |
flush(endingAt: i) | |
fieldStart = self.unicodeScalars.index(after: i) | |
case ("\n", false): | |
flush(endingAt: i) | |
fieldStart = self.unicodeScalars.index(after: i) | |
result.append([]) | |
case ("\"", _): | |
inQuotes = !inQuotes | |
default: | |
continue | |
} | |
} | |
flush(endingAt: endIndex) | |
return result | |
} | |
} | |
let workloadBase = """ | |
Heading1,Heading2,Heading3,Heading4,Heading5,Heading6,Heading7 | |
FirstEntry,"secondentry",third,fourth,fifth,sixth,seventh | |
zéro,un,deux,trois,quatre,cinq,six | |
pagh,wa',cha',wej,IoS,vagh,jav | |
ᬦᬸᬮ᭄,ᬲᬶᬓᬶ,ᬤᬸᬯ,ᬢᭂᬮᬸ,ᬧᬧᬢ᭄,ᬮᬶᬫᬾ,ᬦᭂᬦᭂᬫ᭄ | |
unu,du,tri,kvar,kvin,ses,sep | |
"quoted", "f""i"e"l"d, "with a comma ',' in it", "and some \n for good measure", five, six, seven | |
𐌏𐌉𐌍𐌏,𐌃𐌏,𐌕𐌓𐌉,𐌐𐌄𐌕𐌏𐌓,𐌐𐌄𐌌𐌐𐌄,𐌔𐌖𐌄𐌊𐌏𐌔,𐌔𐌄𐌗𐌕𐌀𐌌 | |
zero,un,duo.tres.quantro,cinque,sex | |
nolla,yksi,kaksi,kolme,neljä,viisi,kuusi | |
really long field, because otherwise, small string opt,imizations may trivial,ize the copies that, were trying to also, measure here!!!! | |
нула,једин,два,три,четыри,петь,шесть | |
一,二,三,四,五,六,七, | |
saquui,ta'lo,tso'i,nvgi,hisgi,sudali,galiquogi | |
""" | |
let targetRowNumber = 500 | |
let repeatCount = targetRowNumber / workloadBase.split(separator: "\n").count | |
let workload: String = repeatElement(workloadBase, count: repeatCount).joined() | |
@inline(never) | |
public func run_CSVParsing(_ N: Int) { | |
let contents = workload | |
for _ in 0..<N { | |
var remainder = contents[...] | |
var result: Int = 0 | |
var x: () = () | |
while !remainder.isEmpty { | |
blackHole(try? parseLine(&remainder, result: &x, processField: { state, _, field in | |
() | |
})) | |
blackHole(x) | |
result += 1 | |
} | |
blackHole(result) | |
} | |
} | |
@inline(never) | |
public func run_CSVParsingAlt(_ N: Int) { | |
let contents = workload | |
for _ in 0..<N { | |
blackHole(contents.parseAlt()) | |
} | |
} | |
@inline(never) | |
public func run_CSVParsingAltIndices(_ N: Int) { | |
let contents = workload | |
for _ in 0..<N { | |
blackHole(contents.parseAltIndices()) | |
} | |
} | |
@inline(never) | |
func makeCharacter_UTF8Length1() -> Character { | |
return "a" | |
} | |
@inline(never) | |
func makeCharacter_UTF8Length2() -> Character { | |
return "\u{00a9}" | |
} | |
@inline(never) | |
func makeCharacter_UTF8Length3() -> Character { | |
return "a\u{0300}" | |
} | |
@inline(never) | |
func makeCharacter_UTF8Length4() -> Character { | |
return "\u{00a9}\u{0300}" | |
} | |
@inline(never) | |
func makeCharacter_UTF8Length5() -> Character { | |
return "a\u{0300}\u{0301}" | |
} | |
@inline(never) | |
func makeCharacter_UTF8Length6() -> Character { | |
return "\u{00a9}\u{0300}\u{0301}" | |
} | |
@inline(never) | |
func makeCharacter_UTF8Length7() -> Character { | |
return "a\u{0300}\u{0301}\u{0302}" | |
} | |
@inline(never) | |
func makeCharacter_UTF8Length8() -> Character { | |
return "\u{00a9}\u{0300}\u{0301}\u{0302}" | |
} | |
@inline(never) | |
func makeLiterals() { | |
blackHole(makeCharacter_UTF8Length1()) | |
blackHole(makeCharacter_UTF8Length2()) | |
blackHole(makeCharacter_UTF8Length3()) | |
blackHole(makeCharacter_UTF8Length4()) | |
blackHole(makeCharacter_UTF8Length5()) | |
blackHole(makeCharacter_UTF8Length6()) | |
blackHole(makeCharacter_UTF8Length7()) | |
blackHole(makeCharacter_UTF8Length8()) | |
} | |
public func run_CharacterLiteralsSmall(_ N: Int) { | |
for _ in 0...10000 * N { | |
makeLiterals() | |
} | |
} | |
// A string that doesn't fit in small string storage and doesn't fit in Latin-1 | |
let longWide = "fὢasὢodὢijὢadὢolὢsjὢalὢsdὢjlὢasὢdfὢijὢliὢsdὢjøὢslὢdiὢalὢiὢ" | |
@inline(never) | |
public func run_SubstringFromLongString(_ N: Int) { | |
var s = longWide | |
s += "!" // ensure the string has a real buffer | |
for _ in 1...N*500 { | |
blackHole(Substring(s)) | |
} | |
} | |
func create<T : RangeReplaceableCollection, U : Collection>( | |
_: T.Type, from source: U | |
) where T.Element == U.Element { | |
blackHole(T(source)) | |
} | |
@inline(never) | |
public func run_SubstringFromLongStringGeneric(_ N: Int) { | |
var s = longWide | |
s += "!" // ensure the string has a real buffer | |
for _ in 1...N*500 { | |
create(Substring.self, from: s) | |
} | |
} | |
@inline(never) | |
public func run_StringFromLongWholeSubstring(_ N: Int) { | |
var s0 = longWide | |
s0 += "!" // ensure the string has a real buffer | |
let s = Substring(s0) | |
for _ in 1...N*500 { | |
blackHole(String(s)) | |
} | |
} | |
@inline(never) | |
public func run_StringFromLongWholeSubstringGeneric(_ N: Int) { | |
var s0 = longWide | |
s0 += "!" // ensure the string has a real buffer | |
let s = Substring(s0) | |
for _ in 1...N*500 { | |
create(String.self, from: s) | |
} | |
} | |
private func equivalentWithDistinctBuffers() -> (String, Substring) { | |
var s0 = longWide | |
withUnsafeMutablePointer(to: &s0) { blackHole($0) } | |
s0 += "!" | |
// These two should be equal but with distinct buffers, both refcounted. | |
let a = Substring(s0).dropFirst() | |
let b = String(a) | |
return (b, a) | |
} | |
@inline(never) | |
public func run_EqualStringSubstring(_ N: Int) { | |
let (a, b) = equivalentWithDistinctBuffers() | |
for _ in 1...N*500 { | |
blackHole(a == b) | |
} | |
} | |
@inline(never) | |
public func run_EqualSubstringString(_ N: Int) { | |
let (a, b) = equivalentWithDistinctBuffers() | |
for _ in 1...N*500 { | |
blackHole(b == a) | |
} | |
} | |
@inline(never) | |
public func run_EqualSubstringSubstring(_ N: Int) { | |
let (_, a) = equivalentWithDistinctBuffers() | |
let (_, b) = equivalentWithDistinctBuffers() | |
for _ in 1...N*500 { | |
blackHole(a == b) | |
} | |
} | |
@inline(never) | |
public func run_EqualSubstringSubstringGenericEquatable(_ N: Int) { | |
let (_, a) = equivalentWithDistinctBuffers() | |
let (_, b) = equivalentWithDistinctBuffers() | |
func check<T>(_ x: T, _ y: T) where T : Equatable { | |
blackHole(x == y) | |
} | |
for _ in 1...N*500 { | |
check(a, b) | |
} | |
} | |
/* | |
func checkEqual<T, U>(_ x: T, _ y: U) | |
where T : StringProtocol, U : StringProtocol { | |
blackHole(x == y) | |
} | |
@inline(never) | |
public func run _EqualStringSubstringGenericStringProtocol(_ N: Int) { | |
let (a, b) = equivalentWithDistinctBuffers() | |
for _ in 1...N*500 { | |
checkEqual(a, b) | |
} | |
} | |
@inline(never) | |
public func run _EqualSubstringStringGenericStringProtocol(_ N: Int) { | |
let (a, b) = equivalentWithDistinctBuffers() | |
for _ in 1...N*500 { | |
checkEqual(b, a) | |
} | |
} | |
@inline(never) | |
public func run _EqualSubstringSubstringGenericStringProtocol(_ N: Int) { | |
let (_, a) = equivalentWithDistinctBuffers() | |
let (_, b) = equivalentWithDistinctBuffers() | |
for _ in 1...N*500 { | |
checkEqual(a, b) | |
} | |
} | |
*/ | |
//===----------------------------------------------------------------------===// | |
/* | |
@inline(never) | |
public func run _LessStringSubstring(_ N: Int) { | |
let (a, b) = equivalentWithDistinctBuffers() | |
for _ in 1...N*500 { | |
blackHole(a < b) | |
} | |
} | |
@inline(never) | |
public func run _LessSubstringString(_ N: Int) { | |
let (a, b) = equivalentWithDistinctBuffers() | |
for _ in 1...N*500 { | |
blackHole(b < a) | |
} | |
} | |
*/ | |
@inline(never) | |
public func run_LessSubstringSubstring(_ N: Int) { | |
let (_, a) = equivalentWithDistinctBuffers() | |
let (_, b) = equivalentWithDistinctBuffers() | |
for _ in 1...N*500 { | |
blackHole(a < b) | |
} | |
} | |
@inline(never) | |
public func run_LessSubstringSubstringGenericComparable(_ N: Int) { | |
let (_, a) = equivalentWithDistinctBuffers() | |
let (_, b) = equivalentWithDistinctBuffers() | |
func check<T>(_ x: T, _ y: T) where T : Comparable { | |
blackHole(x < y) | |
} | |
for _ in 1...N*500 { | |
check(a, b) | |
} | |
} | |
@inline(never) | |
public func run_SubstringEquatable(_ N: Int) { | |
var string = "pen,pineapple,apple,pen" | |
string += ",✒️,🍍,🍏,✒️" | |
let substrings = string.split(separator: ",") | |
var count = 0 | |
for _ in 1...N*500 { | |
for s in substrings { | |
if substrings.contains(s) { count = count &+ 1 } | |
} | |
} | |
CheckResults(count == 8*N*500) | |
} | |
enum MyState : String { | |
case Closed = "Closed" | |
case Opened = "Opened" | |
} | |
@inline(never) | |
func check_state(_ state : MyState) -> Int { | |
return state == .Opened ? 1 : 0 | |
} | |
@inline(never) | |
public func run_OpenClose(_ N: Int) { | |
var c = 0 | |
for _ in 1...N*10000 { | |
c += check_state(identity(MyState.Closed)) | |
} | |
CheckResults(c == 0) | |
} | |
// FIXME(string) | |
public func run_StringHasPrefixAscii(_ N: Int) { | |
#if _runtime(_ObjC) | |
let prefix = "prefix" | |
let testString = "prefixedString" | |
for _ in 0 ..< N { | |
for _ in 0 ..< 100_000 { | |
CheckResults(testString.hasPrefix(getString(prefix))) | |
} | |
} | |
#endif | |
} | |
// FIXME(string) | |
public func run_StringHasSuffixAscii(_ N: Int) { | |
#if _runtime(_ObjC) | |
let suffix = "Suffixed" | |
let testString = "StringSuffixed" | |
for _ in 0 ..< N { | |
for _ in 0 ..< 100_000 { | |
CheckResults(testString.hasSuffix(getString(suffix))) | |
} | |
} | |
#endif | |
} | |
// FIXME(string) | |
public func run_StringHasPrefixUnicode(_ N: Int) { | |
#if _runtime(_ObjC) | |
let prefix = "❄️prefix" | |
let testString = "❄️prefixedString" | |
for _ in 0 ..< N { | |
for _ in 0 ..< 100_000 { | |
CheckResults(testString.hasPrefix(getString(prefix))) | |
} | |
} | |
#endif | |
} | |
// FIXME(string) | |
public func run_StringHasSuffixUnicode(_ N: Int) { | |
#if _runtime(_ObjC) | |
let suffix = "❄️Suffixed" | |
let testString = "String❄️Suffixed" | |
for _ in 0 ..< N { | |
for _ in 0 ..< 100_000 { | |
CheckResults(testString.hasSuffix(getString(suffix))) | |
} | |
} | |
#endif | |
} | |
@inline(never) | |
internal func compareEqual(_ str1: String, _ str2: String) -> Bool { | |
return str1 == str2 | |
} | |
public func run_StringEqualPointerComparison(_ N: Int) { | |
let str1 = "The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. " | |
let str2 = str1 | |
for _ in 0 ..< N { | |
for _ in 0 ..< 100_000 { | |
CheckResults(compareEqual(str1, str2)) | |
} | |
} | |
} | |
@inline(never) | |
public func run_Dictionary3(_ N: Int) { | |
let size1 = 100 | |
let reps = 20 | |
let ref_result = "1 99 20 1980" | |
var hash1 = [String: Int]() | |
var hash2 = [String: Int]() | |
var res = "" | |
for _ in 1...N { | |
hash1 = [:] | |
for i in 0..<size1 { | |
hash1["foo_" + String(i)] = i | |
} | |
hash2 = hash1 | |
for _ in 1..<reps { | |
for (k, v) in hash1 { | |
hash2[k] = hash2[k]! + v | |
} | |
} | |
res = (String(hash1["foo_1"]!) + " " + String(hash1["foo_99"]!) + " " + | |
String(hash2["foo_1"]!) + " " + String(hash2["foo_99"]!)) | |
if res != ref_result { | |
break | |
} | |
} | |
CheckResults(res == ref_result) | |
} | |
var alphabetInput: [Character] = [ | |
"A", "B", "C", "D", "E", "F", "G", | |
"H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", | |
"S", "T", "U", | |
"V", "W", "X", "Y", "Z", "/", "f", "Z", "z", "6", "7", "C", "j", "f", "9", | |
"g", "g", "I", "J", "K", "c", "x", "i", ".", | |
"2", "a", "t", "i", "o", "e", "q", "n", "X", "Y", "Z", "?", "m", "Z", "," | |
] | |
@inline(never) | |
public func run_Chars(_ N: Int) { | |
// Permute some characters. | |
let alphabet: [Character] = alphabetInput | |
for _ in 0..<50*N { | |
for firstChar in alphabet { | |
for lastChar in alphabet { | |
blackHole(firstChar < lastChar) | |
blackHole(firstChar == lastChar) | |
blackHole(firstChar > lastChar) | |
blackHole(firstChar <= lastChar) | |
blackHole(firstChar >= lastChar) | |
} | |
} | |
} | |
} | |
let asciiText = """ | |
**Welcome to Swift!** | |
Swift is a high-performance system programming language. It has a clean and | |
modern syntax, offers seamless access to existing C and Objective-C code and | |
frameworks, and is memory safe by default. | |
Although inspired by Objective-C and many other languages, Swift is not itself a | |
C-derived language. As a complete and independent language, Swift packages core | |
features like flow control, data structures, and functions, with high-level | |
constructs like objects, protocols, closures, and generics. Swift embraces | |
modules, eliminating the need for headers and the code duplication they entail. | |
To learn more about the programming language, visit swift.org. | |
## Contributing to Swift | |
Contributions to Swift are welcomed and encouraged! Please see the | |
Contributing to Swift guide. | |
To be a truly great community, Swift.org needs to welcome developers from all | |
walks of life, with different backgrounds, and with a wide range of | |
experience. A diverse and friendly community will have more great ideas, more | |
unique perspectives, and produce more great code. We will work diligently to | |
make the Swift community welcoming to everyone. | |
To give clarity of what is expected of our members, Swift has adopted the code | |
of conduct defined by the Contributor Covenant. This document is used across | |
many open source communities, and we think it articulates our values well. For | |
more, see the Code of Conduct. | |
## Getting Started | |
These instructions give the most direct path to a working Swift development | |
environment. To build from source you will need 2 GB of disk space for the | |
source code and over 20 GB of disk space for the build artifacts. A clean build | |
can take multiple hours, but incremental builds will finish much faster. | |
""" | |
let utf16Text = """ | |
✨🌟 Welcome tö Swift! ⭐️✨ | |
Swift is a high-performance system programming language. It has a clean and | |
modern syntax, offers seamless access tö existing C and Objective-C code and | |
frameworks, and is memory safe by default. | |
Although inspired by Objective-C and many othér languages, Swift is not itself a | |
C-derived language. As a complete and independent language, Swift packages core | |
features li\u{30A}ke flow control, data structures, and functions, with | |
high-level constructs li\u{30A}ke objects, protöcols, closures, and | |
generics. Swift embraces modules, eliminating thé need for headers and thé code | |
duplication théy entail. | |
Tö learn more about thé programming language, visit swift.org. | |
☞ Contributing tö Swift | |
Contributions tö Swift are welcomed and encouraged! Please see thé | |
Contributing tö Swift guide. | |
Tö be a truly great community, Swift.org needs tö welcome developers from all | |
walks of life, with different backgrounds, and with a wide range of | |
experience. A diverse and friendly community will have more great ideas, more | |
unique perspectives, and produce more great code. We will work diligently tö | |
make thé Swift community welcoming tö everyone. | |
Tö give clarity of what is expected of our members, Swift has adopted thé code | |
of conduct defined by thé Contributör Covenant. This document is used across | |
many open source communities, and we think it articulates our values well. For | |
more, see thé Code of Conduct. | |
☞ Getting Started | |
Thése instructions give thé most direct path tö a working Swift development | |
environment. Tö build from source you will need 2 GB of disk space for thé | |
source code and over 20 GB of disk space for thé build artifacts. A clean build | |
can take multiple hours, but incremental builds will finish much faster. | |
""" | |
// A partial set of Unicode alphanumeric characters. (ASCII letters with at most | |
// one diacritic (of a limited selection), plus ASCII digits.) | |
let someAlphanumerics: Set<Character> = { | |
let baseAlphabet = Set( | |
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".unicodeScalars) | |
let someCombiningDiacriticalMarks: Set<Unicode.Scalar> = | |
Set((0x300..<0x310).map { Unicode.Scalar($0)! }) | |
var alphanumerics: Set<Character> = [] | |
for base in baseAlphabet { | |
alphanumerics.insert(Character(base)) | |
for mark in someCombiningDiacriticalMarks { | |
var v = String.UnicodeScalarView() | |
v.append(base) | |
v.append(mark) | |
alphanumerics.insert(Character(String(v))) | |
} | |
} | |
alphanumerics.formUnion("0123456789") | |
return alphanumerics | |
}() | |
extension Character { | |
var isAlphanumeric: Bool { | |
return someAlphanumerics.contains(self) | |
} | |
} | |
let romanTable: KeyValuePairs<String, Int> = [ | |
"M": 1000, | |
"CM": 900, | |
"D": 500, | |
"CD": 400, | |
"C": 100, | |
"XC": 90, | |
"L": 50, | |
"XL": 40, | |
"X": 10, | |
"IX": 9, | |
"V": 5, | |
"IV": 4, | |
"I": 1, | |
] | |
extension BinaryInteger { | |
var romanNumeral: String { | |
var result = "" | |
var value = self | |
outer: | |
while value > 0 { | |
var position = 0 | |
for (i, (key: s, value: v)) in romanTable[position...].enumerated() { | |
if value >= v { | |
result += s | |
value -= Self(v) | |
position = i | |
continue outer | |
} | |
} | |
fatalError("Unreachable") | |
} | |
return result | |
} | |
init?(romanNumeral: String) { | |
self = 0 | |
var input = Substring(romanNumeral) | |
outer: | |
while !input.isEmpty { | |
var position = 0 | |
for (i, (key: s, value: v)) in romanTable[position...].enumerated() { | |
if input.starts(with: s) { | |
self += Self(v) | |
input = input.dropFirst(s.count) | |
position = i | |
continue outer | |
} | |
} | |
return nil | |
} | |
} | |
} | |
@inline(never) | |
func checkRomanNumerals(upTo limit: Int) { | |
for i in 0 ..< limit { | |
CheckResults(Int(romanNumeral: identity(i.romanNumeral)) == i) | |
} | |
} | |
@inline(never) | |
public func run_RomanNumbers(_ N: Int) { | |
for _ in 0 ..< 10 * N { | |
checkRomanNumerals(upTo: 1100) | |
} | |
} | |
struct Words: IteratorProtocol, Sequence { | |
public typealias Iterator = Words | |
let text: String | |
var nextIndex: String.Index | |
init(_ text: String) { | |
self.text = text | |
self.nextIndex = text.startIndex | |
} | |
mutating func next() -> String? { | |
while nextIndex != text.endIndex && !text[nextIndex].isAlphanumeric { | |
text.formIndex(after: &nextIndex) | |
} | |
let start = nextIndex | |
while nextIndex != text.endIndex && text[nextIndex].isAlphanumeric { | |
text.formIndex(after: &nextIndex) | |
} | |
guard start < nextIndex else { return nil } | |
return String(text[start..<nextIndex]) | |
} | |
} | |
@inline(never) | |
public func run_WordSplitASCII(_ N: Int) { | |
for _ in 1...10*N { | |
let words = Array(Words(identity(asciiText))) | |
CheckResults(words.count == 280) | |
blackHole(words) | |
} | |
} | |
@inline(never) | |
public func run_WordSplitUTF16(_ N: Int) { | |
for _ in 1...10*N { | |
let words = Array(Words(identity(utf16Text))) | |
CheckResults(words.count == 280) | |
blackHole(words) | |
} | |
} | |
let asciiWords = Array(Words(asciiText)) | |
let utf16Words = Array(Words(utf16Text)) | |
@inline(never) | |
public func run_WordCountUniqueASCII(_ N: Int) { | |
for _ in 1...100*N { | |
let words = Set(identity(asciiWords)) | |
CheckResults(words.count == 168) | |
blackHole(words) | |
} | |
} | |
@inline(never) | |
public func run_WordCountUniqueUTF16(_ N: Int) { | |
for _ in 1...100*N { | |
let words = Set(identity(utf16Words)) | |
CheckResults(words.count == 168) | |
blackHole(words) | |
} | |
} | |
/// Returns an array of all words in the supplied string, along with their | |
/// number of occurances. The array is sorted by decreasing frequency. | |
/// (Words are case-sensitive and only support a limited subset of Unicode.) | |
@inline(never) | |
func histogram<S: Sequence>(for words: S) -> [(String, Int)] | |
where S.Element == String { | |
let histogram = Dictionary<String, Int>( | |
words.lazy.map { ($0, 1) }, | |
uniquingKeysWith: +) | |
return histogram.sorted { (-$0.1, $0.0) < (-$1.1, $1.0) } | |
} | |
@inline(never) | |
public func run_WordCountHistogramASCII(_ N: Int) { | |
for _ in 1...100*N { | |
let words = histogram(for: identity(asciiWords)) | |
CheckResults(words.count == 168) | |
CheckResults(words[0] == ("and", 15)) | |
blackHole(words) | |
} | |
} | |
@inline(never) | |
public func run_WordCountHistogramUTF16(_ N: Int) { | |
for _ in 1...100*N { | |
let words = histogram(for: identity(utf16Words)) | |
CheckResults(words.count == 168) | |
CheckResults(words[0] == ("and", 15)) | |
blackHole(words) | |
} | |
} | |
extension RangeReplaceableCollection { | |
mutating func removeWhere_quadratic(where match: (Element) throws -> Bool) rethrows { | |
for i in indices.reversed() { | |
if try match(self[i]) { | |
remove(at: i) | |
} | |
} | |
} | |
mutating func removeWhere_filter(where match: (Element) throws -> Bool) rethrows { | |
try self = self.filter { try !match($0) } | |
} | |
} | |
extension RangeReplaceableCollection where Self: MutableCollection { | |
mutating func removeWhere_move(where match: (Element) throws -> Bool) rethrows { | |
guard var i = try firstIndex(where: match) else { return } | |
var j = index(after: i) | |
while j != endIndex { | |
let element = self[j] | |
if try !match(element) { | |
self[i] = element | |
formIndex(after: &i) | |
} | |
formIndex(after: &j) | |
} | |
removeSubrange(i...) | |
} | |
mutating func removeWhere_swap(where match: (Element) throws -> Bool) rethrows { | |
guard var i = try firstIndex(where: match) else { return } | |
var j = index(after: i) | |
while j != endIndex { | |
if try !match(self[i]) { | |
self.swapAt(i,j) | |
formIndex(after: &i) | |
} | |
formIndex(after: &j) | |
} | |
removeSubrange(i...) | |
} | |
} | |
func testQuadratic<C: RangeReplaceableCollection>(workload: inout C) { | |
var i = 0 | |
workload.removeWhere_quadratic { _ in | |
i = i &+ 1 | |
return i%8 == 0 | |
} | |
} | |
func testFilter<C: RangeReplaceableCollection>(workload: inout C) { | |
var i = 0 | |
workload.removeWhere_filter { _ in | |
i = i &+ 1 | |
return i%8 == 0 | |
} | |
} | |
func testMove<C: RangeReplaceableCollection & MutableCollection>(workload: inout C) { | |
var i = 0 | |
workload.removeWhere_move { _ in | |
i = i &+ 1 | |
return i%8 == 0 | |
} | |
} | |
func testSwap<C: RangeReplaceableCollection & MutableCollection>(workload: inout C) { | |
var i = 0 | |
workload.removeWhere_swap { _ in | |
i = i &+ 1 | |
return i%8 == 0 | |
} | |
} | |
let n = 10_000 | |
let strings = (0..<n).map({ "\($0): A long enough string to defeat the SSO" }) | |
let ints = Array(0..<n) | |
let str = String(repeating: "A very long ASCII string.", count: n/50) | |
@inline(never) | |
func run_RemoveWhereQuadraticStrings(_ scale: Int) { | |
for _ in 0..<scale { | |
var workload = strings; workload.swapAt(0,1) | |
testQuadratic(workload: &workload) | |
} | |
} | |
@inline(never) | |
func run_RemoveWhereQuadraticInts(_ scale: Int) { | |
for _ in 0..<scale { | |
var workload = ints; workload.swapAt(0,1) | |
testQuadratic(workload: &workload) | |
} | |
} | |
@inline(never) | |
func run_RemoveWhereFilterStrings(_ scale: Int) { | |
for _ in 0..<scale { | |
var workload = strings; workload.swapAt(0,1) | |
testFilter(workload: &workload) | |
} | |
} | |
@inline(never) | |
func run_RemoveWhereFilterInts(_ scale: Int) { | |
for _ in 0..<scale { | |
var workload = ints; workload.swapAt(0,1) | |
testFilter(workload: &workload) | |
} | |
} | |
@inline(never) | |
func run_RemoveWhereMoveStrings(_ scale: Int) { | |
for _ in 0..<scale { | |
var workload = strings; workload.swapAt(0,1) | |
testMove(workload: &workload) | |
} | |
} | |
@inline(never) | |
func run_RemoveWhereMoveInts(_ scale: Int) { | |
for _ in 0..<scale { | |
var workload = ints; workload.swapAt(0,1) | |
testMove(workload: &workload) | |
} | |
} | |
@inline(never) | |
func run_RemoveWhereSwapStrings(_ scale: Int) { | |
for _ in 0..<scale { | |
var workload = strings; workload.swapAt(0,1) | |
testSwap(workload: &workload) | |
} | |
} | |
@inline(never) | |
func run_RemoveWhereSwapInts(_ scale: Int) { | |
for _ in 0..<scale { | |
var workload = ints; workload.swapAt(0,1) | |
testSwap(workload: &workload) | |
} | |
} | |
@inline(never) | |
func run_RemoveWhereFilterString(_ scale: Int) { | |
for _ in 0..<scale { | |
var workload = str | |
workload.append("!") | |
testFilter(workload: &workload) | |
} | |
} | |
@inline(never) | |
func run_RemoveWhereQuadraticString(_ scale: Int) { | |
for _ in 0..<scale { | |
var workload = str | |
workload.append("!") | |
testQuadratic(workload: &workload) | |
} | |
} | |
var count: Int = 0 | |
// | |
// Workloads | |
// | |
let ascii = | |
"siebenhundertsiebenundsiebzigtausendsiebenhundertsiebenundsiebzig" | |
let emoji = "👍👩👩👧👧👨👨👦👦🇺🇸🇨🇦🇲🇽👍🏻👍🏼👍🏽👍🏾👍🏿" | |
let utf16 = emoji + "the quick brown fox" + String(emoji.reversed() as Array<Character>) | |
let japanese = "今回のアップデートでSwiftに大幅な改良が施され、安定していてしかも直感的に使うことができるAppleプラットフォーム向けプログラミング言語になりました。" | |
let chinese = "Swift 是面向 Apple 平台的编程语言,功能强大且直观易用,而本次更新对其进行了全面优化。" | |
let korean = "이번 업데이트에서는 강력하면서도 직관적인 Apple 플랫폼용 프로그래밍 언어인 Swift를 완벽히 개선하였습니다." | |
let russian = "в чащах юга жил-был цитрус? да, но фальшивый экземпляр" | |
let punctuated = "\u{201c}Hello\u{2010}world\u{2026}\u{201d}" | |
let punctuatedJapanese = "\u{300c}\u{300e}今日は\u{3001}世界\u{3002}\u{300f}\u{300d}" | |
// A workload that's mostly Latin characters, with occasional emoji | |
// interspersed. Common for tweets. | |
let tweet = "Worst thing about working on String is that it breaks *everything*. Asserts, debuggers, and *especially* printf-style debugging 😭" | |
// | |
// Benchmarks | |
// | |
// Extended String benchmarks: | |
let baseMultiplier = 10_000 | |
let unicodeScalarsMultiplier = baseMultiplier | |
let charactersMultiplier = baseMultiplier / 5 | |
// | |
// Helper functionality | |
// | |
@inline(never) func count_unicodeScalars(_ s: String.UnicodeScalarView) { | |
for _ in s { | |
count += 1 | |
} | |
} | |
@inline(never) func count_characters(_ s: String) { | |
for _ in s { | |
count += 1 | |
} | |
} | |
@inline(never) func count_unicodeScalars_rev( | |
_ s: ReversedCollection<String.UnicodeScalarView> | |
) { | |
for _ in s { | |
count += 1 | |
} | |
} | |
@inline(never) func count_characters_rev( | |
_ s: ReversedCollection<String> | |
) { | |
for _ in s { | |
count += 1 | |
} | |
} | |
@inline(never) | |
public func run_StringWalk_ascii_unicodeScalars(_ N: Int) { | |
for _ in 1...unicodeScalarsMultiplier*N { | |
count_unicodeScalars(ascii.unicodeScalars) | |
} | |
} | |
@inline(never) | |
public func run_StringWalk_ascii_unicodeScalars_Backwards(_ N: Int) { | |
for _ in 1...unicodeScalarsMultiplier*N { | |
count_unicodeScalars_rev(ascii.unicodeScalars.reversed()) | |
} | |
} | |
@inline(never) | |
public func run_StringWalk_ascii_characters(_ N: Int) { | |
for _ in 1...charactersMultiplier*N { | |
count_characters(ascii) | |
} | |
} | |
@inline(never) | |
public func run_StringWalk_ascii_characters_Backwards(_ N: Int) { | |
for _ in 1...charactersMultiplier*N { | |
count_characters_rev(ascii.reversed()) | |
} | |
} | |
let asciiCharacters = Array(ascii) | |
@inline(never) | |
public func run_CharIteration_ascii_unicodeScalars(_ N: Int) { | |
for _ in 1...unicodeScalarsMultiplier*N { | |
for c in asciiCharacters { | |
for u in c.unicodeScalars { | |
count |= Int(u.value) | |
} | |
} | |
} | |
} | |
@inline(never) | |
public func run_CharIteration_ascii_unicodeScalars_Backwards(_ N: Int) { | |
for _ in 1...unicodeScalarsMultiplier*N { | |
for c in asciiCharacters { | |
for u in c.unicodeScalars.reversed() { | |
count |= Int(u.value) | |
} | |
} | |
} | |
} | |
@inline(never) | |
public func run_CharIndexing_ascii_unicodeScalars(_ N: Int) { | |
for _ in 1...unicodeScalarsMultiplier*N { | |
for c in asciiCharacters { | |
let s = c.unicodeScalars | |
for i in s.indices { | |
count |= Int(s[i].value) | |
} | |
} | |
} | |
} | |
@inline(never) | |
public func run_CharIndexing_ascii_unicodeScalars_Backwards(_ N: Int) { | |
for _ in 1...unicodeScalarsMultiplier*N { | |
for c in asciiCharacters { | |
let s = c.unicodeScalars | |
for i in s.indices.reversed() { | |
count |= Int(s[i].value) | |
} | |
} | |
} | |
} | |
@inline(never) | |
public func run_StringWalk_utf16_unicodeScalars(_ N: Int) { | |
for _ in 1...unicodeScalarsMultiplier*N { | |
count_unicodeScalars(utf16.unicodeScalars) | |
} | |
} | |
@inline(never) | |
public func run_StringWalk_utf16_unicodeScalars_Backwards(_ N: Int) { | |
for _ in 1...unicodeScalarsMultiplier*N { | |
count_unicodeScalars_rev(utf16.unicodeScalars.reversed()) | |
} | |
} | |
@inline(never) | |
public func run_StringWalk_utf16_characters(_ N: Int) { | |
for _ in 1...charactersMultiplier*N { | |
count_characters(utf16) | |
} | |
} | |
@inline(never) | |
public func run_StringWalk_utf16_characters_Backwards(_ N: Int) { | |
for _ in 1...charactersMultiplier*N { | |
count_characters_rev(utf16.reversed()) | |
} | |
} | |
let utf16Characters = Array(utf16) | |
@inline(never) | |
public func run_CharIteration_utf16_unicodeScalars(_ N: Int) { | |
for _ in 1...unicodeScalarsMultiplier*N { | |
for c in utf16Characters { | |
for u in c.unicodeScalars { | |
count |= Int(u.value) | |
} | |
} | |
} | |
} | |
@inline(never) | |
public func run_CharIteration_utf16_unicodeScalars_Backwards(_ N: Int) { | |
for _ in 1...unicodeScalarsMultiplier*N { | |
for c in utf16Characters { | |
for u in c.unicodeScalars.reversed() { | |
count |= Int(u.value) | |
} | |
} | |
} | |
} | |
@inline(never) | |
public func run_CharIndexing_utf16_unicodeScalars(_ N: Int) { | |
for _ in 1...unicodeScalarsMultiplier*N { | |
for c in utf16Characters { | |
let s = c.unicodeScalars | |
for i in s.indices { | |
count |= Int(s[i].value) | |
} | |
} | |
} | |
} | |
@inline(never) | |
public func run_CharIndexing_utf16_unicodeScalars_Backwards(_ N: Int) { | |
for _ in 1...unicodeScalarsMultiplier*N { | |
for c in utf16Characters { | |
let s = c.unicodeScalars | |
for i in s.indices.reversed() { | |
count |= Int(s[i].value) | |
} | |
} | |
} | |
} | |
@inline(never) | |
public func run_StringWalk_tweet_unicodeScalars(_ N: Int) { | |
for _ in 1...unicodeScalarsMultiplier*N { | |
count_unicodeScalars(tweet.unicodeScalars) | |
} | |
} | |
@inline(never) | |
public func run_StringWalk_tweet_unicodeScalars_Backwards(_ N: Int) { | |
for _ in 1...unicodeScalarsMultiplier*N { | |
count_unicodeScalars_rev(tweet.unicodeScalars.reversed()) | |
} | |
} | |
@inline(never) | |
public func run_StringWalk_tweet_characters(_ N: Int) { | |
for _ in 1...charactersMultiplier*N { | |
count_characters(tweet) | |
} | |
} | |
@inline(never) | |
public func run_StringWalk_tweet_characters_Backwards(_ N: Int) { | |
for _ in 1...charactersMultiplier*N { | |
count_characters_rev(tweet.reversed()) | |
} | |
} | |
let tweetCharacters = Array(tweet) | |
@inline(never) | |
public func run_CharIteration_tweet_unicodeScalars(_ N: Int) { | |
for _ in 1...unicodeScalarsMultiplier*N { | |
for c in tweetCharacters { | |
for u in c.unicodeScalars { | |
count |= Int(u.value) | |
} | |
} | |
} | |
} | |
@inline(never) | |
public func run_CharIteration_tweet_unicodeScalars_Backwards(_ N: Int) { | |
for _ in 1...unicodeScalarsMultiplier*N { | |
for c in tweetCharacters { | |
for u in c.unicodeScalars.reversed() { | |
count |= Int(u.value) | |
} | |
} | |
} | |
} | |
@inline(never) | |
public func run_CharIndexing_tweet_unicodeScalars(_ N: Int) { | |
for _ in 1...unicodeScalarsMultiplier*N { | |
for c in tweetCharacters { | |
let s = c.unicodeScalars | |
for i in s.indices { | |
count |= Int(s[i].value) | |
} | |
} | |
} | |
} | |
@inline(never) | |
public func run_CharIndexing_tweet_unicodeScalars_Backwards(_ N: Int) { | |
for _ in 1...unicodeScalarsMultiplier*N { | |
for c in tweetCharacters { | |
let s = c.unicodeScalars | |
for i in s.indices.reversed() { | |
count |= Int(s[i].value) | |
} | |
} | |
} | |
} | |
@inline(never) | |
public func run_StringWalk_japanese_unicodeScalars(_ N: Int) { | |
for _ in 1...unicodeScalarsMultiplier*N { | |
count_unicodeScalars(japanese.unicodeScalars) | |
} | |
} | |
@inline(never) | |
public func run_StringWalk_japanese_unicodeScalars_Backwards(_ N: Int) { | |
for _ in 1...unicodeScalarsMultiplier*N { | |
count_unicodeScalars_rev(japanese.unicodeScalars.reversed()) | |
} | |
} | |
@inline(never) | |
public func run_StringWalk_japanese_characters(_ N: Int) { | |
for _ in 1...charactersMultiplier*N { | |
count_characters(japanese) | |
} | |
} | |
@inline(never) | |
public func run_StringWalk_japanese_characters_Backwards(_ N: Int) { | |
for _ in 1...charactersMultiplier*N { | |
count_characters_rev(japanese.reversed()) | |
} | |
} | |
let japaneseCharacters = Array(japanese) | |
@inline(never) | |
public func run_CharIteration_japanese_unicodeScalars(_ N: Int) { | |
for _ in 1...unicodeScalarsMultiplier*N { | |
for c in japaneseCharacters { | |
for u in c.unicodeScalars { | |
count |= Int(u.value) | |
} | |
} | |
} | |
} | |
@inline(never) | |
public func run_CharIteration_japanese_unicodeScalars_Backwards(_ N: Int) { | |
for _ in 1...unicodeScalarsMultiplier*N { | |
for c in japaneseCharacters { | |
for u in c.unicodeScalars.reversed() { | |
count |= Int(u.value) | |
} | |
} | |
} | |
} | |
@inline(never) | |
public func run_CharIndexing_japanese_unicodeScalars(_ N: Int) { | |
for _ in 1...unicodeScalarsMultiplier*N { | |
for c in japaneseCharacters { | |
let s = c.unicodeScalars | |
for i in s.indices { | |
count |= Int(s[i].value) | |
} | |
} | |
} | |
} | |
@inline(never) | |
public func run_CharIndexing_japanese_unicodeScalars_Backwards(_ N: Int) { | |
for _ in 1...unicodeScalarsMultiplier*N { | |
for c in japaneseCharacters { | |
let s = c.unicodeScalars | |
for i in s.indices.reversed() { | |
count |= Int(s[i].value) | |
} | |
} | |
} | |
} | |
@inline(never) | |
public func run_StringWalk_chinese_unicodeScalars(_ N: Int) { | |
for _ in 1...unicodeScalarsMultiplier*N { | |
count_unicodeScalars(chinese.unicodeScalars) | |
} | |
} | |
@inline(never) | |
public func run_StringWalk_chinese_unicodeScalars_Backwards(_ N: Int) { | |
for _ in 1...unicodeScalarsMultiplier*N { | |
count_unicodeScalars_rev(chinese.unicodeScalars.reversed()) | |
} | |
} | |
@inline(never) | |
public func run_StringWalk_chinese_characters(_ N: Int) { | |
for _ in 1...charactersMultiplier*N { | |
count_characters(chinese) | |
} | |
} | |
@inline(never) | |
public func run_StringWalk_chinese_characters_Backwards(_ N: Int) { | |
for _ in 1...charactersMultiplier*N { | |
count_characters_rev(chinese.reversed()) | |
} | |
} | |
let chineseCharacters = Array(chinese) | |
@inline(never) | |
public func run_CharIteration_chinese_unicodeScalars(_ N: Int) { | |
for _ in 1...unicodeScalarsMultiplier*N { | |
for c in chineseCharacters { | |
for u in c.unicodeScalars { | |
count |= Int(u.value) | |
} | |
} | |
} | |
} | |
@inline(never) | |
public func run_CharIteration_chinese_unicodeScalars_Backwards(_ N: Int) { | |
for _ in 1...unicodeScalarsMultiplier*N { | |
for c in chineseCharacters { | |
for u in c.unicodeScalars.reversed() { | |
count |= Int(u.value) | |
} | |
} | |
} | |
} | |
@inline(never) | |
public func run_CharIndexing_chinese_unicodeScalars(_ N: Int) { | |
for _ in 1...unicodeScalarsMultiplier*N { | |
for c in chineseCharacters { | |
let s = c.unicodeScalars | |
for i in s.indices { | |
count |= Int(s[i].value) | |
} | |
} | |
} | |
} | |
@inline(never) | |
public func run_CharIndexing_chinese_unicodeScalars_Backwards(_ N: Int) { | |
for _ in 1...unicodeScalarsMultiplier*N { | |
for c in chineseCharacters { | |
let s = c.unicodeScalars | |
for i in s.indices.reversed() { | |
count |= Int(s[i].value) | |
} | |
} | |
} | |
} | |
@inline(never) | |
public func run_StringWalk_korean_unicodeScalars(_ N: Int) { | |
for _ in 1...unicodeScalarsMultiplier*N { | |
count_unicodeScalars(korean.unicodeScalars) | |
} | |
} | |
@inline(never) | |
public func run_StringWalk_korean_unicodeScalars_Backwards(_ N: Int) { | |
for _ in 1...unicodeScalarsMultiplier*N { | |
count_unicodeScalars_rev(korean.unicodeScalars.reversed()) | |
} | |
} | |
@inline(never) | |
public func run_StringWalk_korean_characters(_ N: Int) { | |
for _ in 1...charactersMultiplier*N { | |
count_characters(korean) | |
} | |
} | |
@inline(never) | |
public func run_StringWalk_korean_characters_Backwards(_ N: Int) { | |
for _ in 1...charactersMultiplier*N { | |
count_characters_rev(korean.reversed()) | |
} | |
} | |
let koreanCharacters = Array(korean) | |
@inline(never) | |
public func run_CharIteration_korean_unicodeScalars(_ N: Int) { | |
for _ in 1...unicodeScalarsMultiplier*N { | |
for c in koreanCharacters { | |
for u in c.unicodeScalars { | |
count |= Int(u.value) | |
} | |
} | |
} | |
} | |
@inline(never) | |
public func run_CharIteration_korean_unicodeScalars_Backwards(_ N: Int) { | |
for _ in 1...unicodeScalarsMultiplier*N { | |
for c in koreanCharacters { | |
for u in c.unicodeScalars.reversed() { | |
count |= Int(u.value) | |
} | |
} | |
} | |
} | |
@inline(never) | |
public func run_CharIndexing_korean_unicodeScalars(_ N: Int) { | |
for _ in 1...unicodeScalarsMultiplier*N { | |
for c in koreanCharacters { | |
let s = c.unicodeScalars | |
for i in s.indices { | |
count |= Int(s[i].value) | |
} | |
} | |
} | |
} | |
@inline(never) | |
public func run_CharIndexing_korean_unicodeScalars_Backwards(_ N: Int) { | |
for _ in 1...unicodeScalarsMultiplier*N { | |
for c in koreanCharacters { | |
let s = c.unicodeScalars | |
for i in s.indices.reversed() { | |
count |= Int(s[i].value) | |
} | |
} | |
} | |
} | |
@inline(never) | |
public func run_StringWalk_russian_unicodeScalars(_ N: Int) { | |
for _ in 1...unicodeScalarsMultiplier*N { | |
count_unicodeScalars(russian.unicodeScalars) | |
} | |
} | |
@inline(never) | |
public func run_StringWalk_russian_unicodeScalars_Backwards(_ N: Int) { | |
for _ in 1...unicodeScalarsMultiplier*N { | |
count_unicodeScalars_rev(russian.unicodeScalars.reversed()) | |
} | |
} | |
@inline(never) | |
public func run_StringWalk_russian_characters(_ N: Int) { | |
for _ in 1...charactersMultiplier*N { | |
count_characters(russian) | |
} | |
} | |
@inline(never) | |
public func run_StringWalk_russian_characters_Backwards(_ N: Int) { | |
for _ in 1...charactersMultiplier*N { | |
count_characters_rev(russian.reversed()) | |
} | |
} | |
let russianCharacters = Array(russian) | |
@inline(never) | |
public func run_CharIteration_russian_unicodeScalars(_ N: Int) { | |
for _ in 1...unicodeScalarsMultiplier*N { | |
for c in russianCharacters { | |
for u in c.unicodeScalars { | |
count |= Int(u.value) | |
} | |
} | |
} | |
} | |
@inline(never) | |
public func run_CharIteration_russian_unicodeScalars_Backwards(_ N: Int) { | |
for _ in 1...unicodeScalarsMultiplier*N { | |
for c in russianCharacters { | |
for u in c.unicodeScalars.reversed() { | |
count |= Int(u.value) | |
} | |
} | |
} | |
} | |
@inline(never) | |
public func run_CharIndexing_russian_unicodeScalars(_ N: Int) { | |
for _ in 1...unicodeScalarsMultiplier*N { | |
for c in russianCharacters { | |
let s = c.unicodeScalars | |
for i in s.indices { | |
count |= Int(s[i].value) | |
} | |
} | |
} | |
} | |
@inline(never) | |
public func run_CharIndexing_russian_unicodeScalars_Backwards(_ N: Int) { | |
for _ in 1...unicodeScalarsMultiplier*N { | |
for c in russianCharacters { | |
let s = c.unicodeScalars | |
for i in s.indices.reversed() { | |
count |= Int(s[i].value) | |
} | |
} | |
} | |
} | |
@inline(never) | |
public func run_StringWalk_punctuated_unicodeScalars(_ N: Int) { | |
for _ in 1...unicodeScalarsMultiplier*N { | |
count_unicodeScalars(punctuated.unicodeScalars) | |
} | |
} | |
@inline(never) | |
public func run_StringWalk_punctuated_unicodeScalars_Backwards(_ N: Int) { | |
for _ in 1...unicodeScalarsMultiplier*N { | |
count_unicodeScalars_rev(punctuated.unicodeScalars.reversed()) | |
} | |
} | |
@inline(never) | |
public func run_StringWalk_punctuated_characters(_ N: Int) { | |
for _ in 1...charactersMultiplier*N { | |
count_characters(punctuated) | |
} | |
} | |
@inline(never) | |
public func run_StringWalk_punctuated_characters_Backwards(_ N: Int) { | |
for _ in 1...charactersMultiplier*N { | |
count_characters_rev(punctuated.reversed()) | |
} | |
} | |
let punctuatedCharacters = Array(punctuated) | |
@inline(never) | |
public func run_CharIteration_punctuated_unicodeScalars(_ N: Int) { | |
for _ in 1...unicodeScalarsMultiplier*N { | |
for c in punctuatedCharacters { | |
for u in c.unicodeScalars { | |
count |= Int(u.value) | |
} | |
} | |
} | |
} | |
@inline(never) | |
public func run_CharIteration_punctuated_unicodeScalars_Backwards(_ N: Int) { | |
for _ in 1...unicodeScalarsMultiplier*N { | |
for c in punctuatedCharacters { | |
for u in c.unicodeScalars.reversed() { | |
count |= Int(u.value) | |
} | |
} | |
} | |
} | |
@inline(never) | |
public func run_CharIndexing_punctuated_unicodeScalars(_ N: Int) { | |
for _ in 1...unicodeScalarsMultiplier*N { | |
for c in punctuatedCharacters { | |
let s = c.unicodeScalars | |
for i in s.indices { | |
count |= Int(s[i].value) | |
} | |
} | |
} | |
} | |
@inline(never) | |
public func run_CharIndexing_punctuated_unicodeScalars_Backwards(_ N: Int) { | |
for _ in 1...unicodeScalarsMultiplier*N { | |
for c in punctuatedCharacters { | |
let s = c.unicodeScalars | |
for i in s.indices.reversed() { | |
count |= Int(s[i].value) | |
} | |
} | |
} | |
} | |
@inline(never) | |
public func run_StringWalk_punctuatedJapanese_unicodeScalars(_ N: Int) { | |
for _ in 1...unicodeScalarsMultiplier*N { | |
count_unicodeScalars(punctuatedJapanese.unicodeScalars) | |
} | |
} | |
@inline(never) | |
public func run_StringWalk_punctuatedJapanese_unicodeScalars_Backwards(_ N: Int) { | |
for _ in 1...unicodeScalarsMultiplier*N { | |
count_unicodeScalars_rev(punctuatedJapanese.unicodeScalars.reversed()) | |
} | |
} | |
@inline(never) | |
public func run_StringWalk_punctuatedJapanese_characters(_ N: Int) { | |
for _ in 1...charactersMultiplier*N { | |
count_characters(punctuatedJapanese) | |
} | |
} | |
@inline(never) | |
public func run_StringWalk_punctuatedJapanese_characters_Backwards(_ N: Int) { | |
for _ in 1...charactersMultiplier*N { | |
count_characters_rev(punctuatedJapanese.reversed()) | |
} | |
} | |
let punctuatedJapaneseCharacters = Array(punctuatedJapanese) | |
@inline(never) | |
public func run_CharIteration_punctuatedJapanese_unicodeScalars(_ N: Int) { | |
for _ in 1...unicodeScalarsMultiplier*N { | |
for c in punctuatedJapaneseCharacters { | |
for u in c.unicodeScalars { | |
count |= Int(u.value) | |
} | |
} | |
} | |
} | |
/* match: search for regexp anywhere in text */ | |
func match(regexp: String, text: String) -> Bool { | |
if regexp.first == "^" { | |
return matchHere(regexp.dropFirst(), text[...]) | |
} | |
var idx = text.startIndex | |
while true { // must look even if string is empty | |
if matchHere(regexp[...], text[idx..<text.endIndex]) { | |
return true | |
} | |
guard idx != text.endIndex else { break } | |
// do while sufficed in the original C version... | |
text.formIndex(after: &idx) | |
} // while idx++ != string.endIndex | |
return false | |
} | |
/* matchhere: search for regexp at beginning of text */ | |
func matchHere(_ regexp: Substring, _ text: Substring) -> Bool { | |
if regexp.isEmpty { | |
return true | |
} | |
if let c = regexp.first, regexp.dropFirst().first == "*" { | |
return matchStar(c, regexp.dropFirst(2), text) | |
} | |
if regexp.first == "$" && regexp.dropFirst().isEmpty { | |
return text.isEmpty | |
} | |
if let tc = text.first, let rc = regexp.first, rc == "." || tc == rc { | |
return matchHere(regexp.dropFirst(), text.dropFirst()) | |
} | |
return false | |
} | |
/* matchstar: search for c*regexp at beginning of text */ | |
func matchStar(_ c: Character, _ regexp: Substring, _ text: Substring) -> Bool { | |
var idx = text.startIndex | |
while true { /* a * matches zero or more instances */ | |
if matchHere(regexp, text[idx..<text.endIndex]) { | |
return true | |
} | |
if idx == text.endIndex || (text[idx] != c && c != ".") { | |
return false | |
} | |
text.formIndex(after: &idx) | |
} | |
} | |
// Pre-commit benchmark: simple scalar walk | |
@inline(never) | |
public func run_StringWalk(_ N: Int) { | |
return run_StringWalk_ascii_unicodeScalars(N) | |
} | |
let tests: KeyValuePairs = [ | |
"^h..lo*!$":"hellooooo!", | |
"^h..lo*!$":"hella noms", | |
".ab":"abracadabra!", | |
"s.*":"saaaad!", | |
"...e.$":"\"Ganymede,\" he continued, \"is the largest moon in the Solar System\"", | |
"🤠*":"even 🤠🤠🤠 are supported", | |
] | |
extension Character { | |
var firstScalar: UnicodeScalar { return unicodeScalars.first! } | |
} | |
// Fetch the CharacterSet for every call | |
func isControl(_ c: Character) -> Bool { | |
return CharacterSet.controlCharacters.contains(c.firstScalar) | |
} | |
func isAlphanumeric(_ c: Character) -> Bool { | |
return CharacterSet.alphanumerics.contains(c.firstScalar) | |
} | |
func isLowercase(_ c: Character) -> Bool { | |
return CharacterSet.lowercaseLetters.contains(c.firstScalar) | |
} | |
func isPunctuation(_ c: Character) -> Bool { | |
return CharacterSet.punctuationCharacters.contains(c.firstScalar) | |
} | |
func isWhitespace(_ c: Character) -> Bool { | |
return CharacterSet.whitespaces.contains(c.firstScalar) | |
} | |
func isLetter(_ c: Character) -> Bool { | |
return CharacterSet.letters.contains(c.firstScalar) | |
} | |
func isUppercase(_ c: Character) -> Bool { | |
return CharacterSet.uppercaseLetters.contains(c.firstScalar) | |
} | |
func isDecimal(_ c: Character) -> Bool { | |
return CharacterSet.decimalDigits.contains(c.firstScalar) | |
} | |
func isNewline(_ c: Character) -> Bool { | |
return CharacterSet.newlines.contains(c.firstScalar) | |
} | |
func isCapitalized(_ c: Character) -> Bool { | |
return CharacterSet.capitalizedLetters.contains(c.firstScalar) | |
} | |
// Stash the set | |
let controlCharacters = CharacterSet.controlCharacters | |
func isControlStashed(_ c: Character) -> Bool { | |
return controlCharacters.contains(c.firstScalar) | |
} | |
let alphanumerics = CharacterSet.alphanumerics | |
func isAlphanumericStashed(_ c: Character) -> Bool { | |
return alphanumerics.contains(c.firstScalar) | |
} | |
let lowercaseLetters = CharacterSet.lowercaseLetters | |
func isLowercaseStashed(_ c: Character) -> Bool { | |
return lowercaseLetters.contains(c.firstScalar) | |
} | |
let punctuationCharacters = CharacterSet.punctuationCharacters | |
func isPunctuationStashed(_ c: Character) -> Bool { | |
return punctuationCharacters.contains(c.firstScalar) | |
} | |
let whitespaces = CharacterSet.whitespaces | |
func isWhitespaceStashed(_ c: Character) -> Bool { | |
return whitespaces.contains(c.firstScalar) | |
} | |
let letters = CharacterSet.letters | |
func isLetterStashed(_ c: Character) -> Bool { | |
return letters.contains(c.firstScalar) | |
} | |
let uppercaseLetters = CharacterSet.uppercaseLetters | |
func isUppercaseStashed(_ c: Character) -> Bool { | |
return uppercaseLetters.contains(c.firstScalar) | |
} | |
let decimalDigits = CharacterSet.decimalDigits | |
func isDecimalStashed(_ c: Character) -> Bool { | |
return decimalDigits.contains(c.firstScalar) | |
} | |
let newlines = CharacterSet.newlines | |
func isNewlineStashed(_ c: Character) -> Bool { | |
return newlines.contains(c.firstScalar) | |
} | |
let capitalizedLetters = CharacterSet.capitalizedLetters | |
func isCapitalizedStashed(_ c: Character) -> Bool { | |
return capitalizedLetters.contains(c.firstScalar) | |
} | |
func setupStash() { | |
blackHole(workload) | |
blackHole(controlCharacters) | |
blackHole(alphanumerics) | |
blackHole(lowercaseLetters) | |
blackHole(punctuationCharacters) | |
blackHole(whitespaces) | |
blackHole(letters) | |
blackHole(uppercaseLetters) | |
blackHole(decimalDigits) | |
blackHole(newlines) | |
blackHole(capitalizedLetters) | |
} | |
// Memoize the stashed set | |
var controlCharactersMemo = Set<UInt32>() | |
func isControlStashedMemo(_ c: Character) -> Bool { | |
let scalar = c.firstScalar | |
if controlCharactersMemo.contains(scalar.value) { return true } | |
if controlCharacters.contains(scalar) { | |
controlCharactersMemo.insert(scalar.value) | |
return true | |
} | |
return false | |
} | |
var alphanumericsMemo = Set<UInt32>() | |
func isAlphanumericStashedMemo(_ c: Character) -> Bool { | |
let scalar = c.firstScalar | |
if alphanumericsMemo.contains(scalar.value) { return true } | |
if alphanumerics.contains(scalar) { | |
alphanumericsMemo.insert(scalar.value) | |
return true | |
} | |
return false | |
} | |
var lowercaseLettersMemo = Set<UInt32>() | |
func isLowercaseStashedMemo(_ c: Character) -> Bool { | |
let scalar = c.firstScalar | |
if lowercaseLettersMemo.contains(scalar.value) { return true } | |
if lowercaseLetters.contains(scalar) { | |
lowercaseLettersMemo.insert(scalar.value) | |
return true | |
} | |
return false | |
} | |
var punctuationCharactersMemo = Set<UInt32>() | |
func isPunctuationStashedMemo(_ c: Character) -> Bool { | |
let scalar = c.firstScalar | |
if punctuationCharactersMemo.contains(scalar.value) { return true } | |
if punctuationCharacters.contains(scalar) { | |
punctuationCharactersMemo.insert(scalar.value) | |
return true | |
} | |
return false | |
} | |
var whitespacesMemo = Set<UInt32>() | |
func isWhitespaceStashedMemo(_ c: Character) -> Bool { | |
let scalar = c.firstScalar | |
if whitespacesMemo.contains(scalar.value) { return true } | |
if whitespaces.contains(scalar) { | |
whitespacesMemo.insert(scalar.value) | |
return true | |
} | |
return false | |
} | |
var lettersMemo = Set<UInt32>() | |
func isLetterStashedMemo(_ c: Character) -> Bool { | |
let scalar = c.firstScalar | |
if lettersMemo.contains(scalar.value) { return true } | |
if letters.contains(scalar) { | |
lettersMemo.insert(scalar.value) | |
return true | |
} | |
return false | |
} | |
var uppercaseLettersMemo = Set<UInt32>() | |
func isUppercaseStashedMemo(_ c: Character) -> Bool { | |
let scalar = c.firstScalar | |
if uppercaseLettersMemo.contains(scalar.value) { return true } | |
if uppercaseLetters.contains(scalar) { | |
uppercaseLettersMemo.insert(scalar.value) | |
return true | |
} | |
return false | |
} | |
var decimalDigitsMemo = Set<UInt32>() | |
func isDecimalStashedMemo(_ c: Character) -> Bool { | |
let scalar = c.firstScalar | |
if decimalDigitsMemo.contains(scalar.value) { return true } | |
if decimalDigits.contains(scalar) { | |
decimalDigitsMemo.insert(scalar.value) | |
return true | |
} | |
return false | |
} | |
var newlinesMemo = Set<UInt32>() | |
func isNewlineStashedMemo(_ c: Character) -> Bool { | |
let scalar = c.firstScalar | |
if newlinesMemo.contains(scalar.value) { return true } | |
if newlines.contains(scalar) { | |
newlinesMemo.insert(scalar.value) | |
return true | |
} | |
return false | |
} | |
var capitalizedLettersMemo = Set<UInt32>() | |
func isCapitalizedStashedMemo(_ c: Character) -> Bool { | |
let scalar = c.firstScalar | |
if capitalizedLettersMemo.contains(scalar.value) { return true } | |
if capitalizedLetters.contains(scalar) { | |
capitalizedLettersMemo.insert(scalar.value) | |
return true | |
} | |
return false | |
} | |
func setupMemo() { | |
blackHole(workload) | |
blackHole(controlCharactersMemo) | |
blackHole(alphanumericsMemo) | |
blackHole(lowercaseLettersMemo) | |
blackHole(punctuationCharactersMemo) | |
blackHole(whitespacesMemo) | |
blackHole(lettersMemo) | |
blackHole(uppercaseLettersMemo) | |
blackHole(decimalDigitsMemo) | |
blackHole(newlinesMemo) | |
blackHole(capitalizedLettersMemo) | |
} | |
// Precompute whole scalar set | |
func precompute(_ charSet: CharacterSet) -> Set<UInt32> { | |
var result = Set<UInt32>() | |
for plane in 0...0x10 { | |
guard charSet.hasMember(inPlane: UInt8(plane)) else { continue } | |
let offset = plane &* 0x1_0000 | |
for codePoint in 0...0xFFFF { | |
guard let scalar = UnicodeScalar(codePoint &+ offset) else { continue } | |
if charSet.contains(scalar) { | |
result.insert(scalar.value) | |
} | |
} | |
} | |
return result | |
} | |
var controlCharactersPrecomputed: Set<UInt32> = precompute(controlCharacters) | |
func isControlPrecomputed(_ c: Character) -> Bool { | |
return controlCharactersPrecomputed.contains(c.firstScalar.value) | |
} | |
var alphanumericsPrecomputed: Set<UInt32> = precompute(alphanumerics) | |
func isAlphanumericPrecomputed(_ c: Character) -> Bool { | |
return alphanumericsPrecomputed.contains(c.firstScalar.value) | |
} | |
var lowercaseLettersPrecomputed: Set<UInt32> = precompute(lowercaseLetters) | |
func isLowercasePrecomputed(_ c: Character) -> Bool { | |
return lowercaseLettersPrecomputed.contains(c.firstScalar.value) | |
} | |
var punctuationCharactersPrecomputed: Set<UInt32> = precompute(punctuationCharacters) | |
func isPunctuationPrecomputed(_ c: Character) -> Bool { | |
return punctuationCharactersPrecomputed.contains(c.firstScalar.value) | |
} | |
var whitespacesPrecomputed: Set<UInt32> = precompute(whitespaces) | |
func isWhitespacePrecomputed(_ c: Character) -> Bool { | |
return whitespacesPrecomputed.contains(c.firstScalar.value) | |
} | |
var lettersPrecomputed: Set<UInt32> = precompute(letters) | |
func isLetterPrecomputed(_ c: Character) -> Bool { | |
return lettersPrecomputed.contains(c.firstScalar.value) | |
} | |
var uppercaseLettersPrecomputed: Set<UInt32> = precompute(uppercaseLetters) | |
func isUppercasePrecomputed(_ c: Character) -> Bool { | |
return uppercaseLettersPrecomputed.contains(c.firstScalar.value) | |
} | |
var decimalDigitsPrecomputed: Set<UInt32> = precompute(decimalDigits) | |
func isDecimalPrecomputed(_ c: Character) -> Bool { | |
return decimalDigitsPrecomputed.contains(c.firstScalar.value) | |
} | |
var newlinesPrecomputed: Set<UInt32> = precompute(newlines) | |
func isNewlinePrecomputed(_ c: Character) -> Bool { | |
return newlinesPrecomputed.contains(c.firstScalar.value) | |
} | |
var capitalizedLettersPrecomputed: Set<UInt32> = precompute(capitalizedLetters) | |
func isCapitalizedPrecomputed(_ c: Character) -> Bool { | |
return capitalizedLettersPrecomputed.contains(c.firstScalar.value) | |
} | |
func setupPrecomputed() { | |
blackHole(workload) | |
blackHole(controlCharactersPrecomputed) | |
blackHole(alphanumericsPrecomputed) | |
blackHole(lowercaseLettersPrecomputed) | |
blackHole(punctuationCharactersPrecomputed) | |
blackHole(whitespacesPrecomputed) | |
blackHole(lettersPrecomputed) | |
blackHole(uppercaseLettersPrecomputed) | |
blackHole(decimalDigitsPrecomputed) | |
blackHole(newlinesPrecomputed) | |
blackHole(capitalizedLettersPrecomputed) | |
} | |
// Compute on the fly | |
// | |
// TODO: If UnicodeScalars ever exposes category, etc., implement the others! | |
func isNewlineComputed(_ c: Character) -> Bool { | |
switch c.firstScalar.value { | |
case 0x000A...0x000D: return true | |
case 0x0085: return true | |
case 0x2028...0x2029: return true | |
default: return false | |
} | |
} | |
let workload_2 = """ | |
the quick brown 🦊 jumped over the lazy 🐶. | |
в чащах юга жил-был цитрус? да, но фальшивый экземпляр | |
𓀀𓀤𓁓𓁲𓃔𓃗𓃀𓃁𓃂𓃃𓆌𓆍𓆎𓆏𓆐𓆑𓆒𓆲𓁿 | |
🝁ꃕ躍‾∾📦⺨ | |
👍👩👩👧👧👨👨👦👦🇺🇸🇨🇦🇲🇽👍🏻👍🏼👍🏽👍🏾👍🏿 | |
Lorem ipsum something something something... | |
""" | |
@inline(never) | |
public func run_CharacterPropertiesFetch(_ N: Int) { | |
for _ in 1...N*10 { | |
for c in workload_2 { | |
blackHole(isControl(c)) | |
blackHole(isAlphanumeric(c)) | |
blackHole(isLowercase(c)) | |
blackHole(isPunctuation(c)) | |
blackHole(isWhitespace(c)) | |
blackHole(isLetter(c)) | |
blackHole(isUppercase(c)) | |
blackHole(isDecimal(c)) | |
blackHole(isNewline(c)) | |
blackHole(isCapitalized(c)) | |
} | |
} | |
} | |
@inline(never) | |
public func run_CharacterPropertiesStashed(_ N: Int) { | |
for _ in 1...N*10 { | |
for c in workload_2 { | |
blackHole(isControlStashed(c)) | |
blackHole(isAlphanumericStashed(c)) | |
blackHole(isLowercaseStashed(c)) | |
blackHole(isPunctuationStashed(c)) | |
blackHole(isWhitespaceStashed(c)) | |
blackHole(isLetterStashed(c)) | |
blackHole(isUppercaseStashed(c)) | |
blackHole(isDecimalStashed(c)) | |
blackHole(isNewlineStashed(c)) | |
blackHole(isCapitalizedStashed(c)) | |
} | |
} | |
} | |
@inline(never) | |
public func run_CharacterPropertiesStashedMemo(_ N: Int) { | |
for _ in 1...N*10 { | |
for c in workload_2 { | |
blackHole(isControlStashedMemo(c)) | |
blackHole(isAlphanumericStashedMemo(c)) | |
blackHole(isLowercaseStashedMemo(c)) | |
blackHole(isPunctuationStashedMemo(c)) | |
blackHole(isWhitespaceStashedMemo(c)) | |
blackHole(isLetterStashedMemo(c)) | |
blackHole(isUppercaseStashedMemo(c)) | |
blackHole(isDecimalStashedMemo(c)) | |
blackHole(isNewlineStashedMemo(c)) | |
blackHole(isCapitalizedStashedMemo(c)) | |
} | |
} | |
} | |
class RefTypePrintable : CustomStringConvertible { | |
var description: String { | |
return "01234567890123456789012345678901234567890123456789" | |
} | |
} | |
@inline(never) | |
public func run_StringInterpolation(_ N: Int) { | |
let reps = 100 | |
let refResult = reps | |
let anInt: Int64 = 0x1234567812345678 | |
let aRefCountedObject = RefTypePrintable() | |
for _ in 1...100*N { | |
var result = 0 | |
for _ in 1...reps { | |
let s: String = getString( | |
"\(anInt) abcdefdhijklmn \(aRefCountedObject) abcdefdhijklmn \u{01}") | |
let utf16 = s.utf16 | |
// FIXME: if String is not stored as UTF-16 on this platform, then the | |
// following operation has a non-trivial cost and needs to be replaced | |
// with an operation on the native storage type. | |
result = result &+ Int(utf16.last!) | |
blackHole(s) | |
} | |
CheckResults(result == refResult) | |
} | |
} | |
@inline(never) | |
public func run_StringInterpolationSmall(_ N: Int) { | |
let reps = 100 | |
let refResult = reps | |
let anInt: Int64 = 0x42 | |
for _ in 1...100*N { | |
var result = 0 | |
for _ in 1...reps { | |
let s: String = getString( | |
"\(getString("int")): \(anInt) \(getString("abc")) \u{01}") | |
result = result &+ Int(s.utf8.last!) | |
blackHole(s) | |
} | |
CheckResults(result == refResult) | |
} | |
} | |
@inline(never) | |
public func run_StringInterpolationManySmallSegments(_ N: Int) { | |
let numHex = min(UInt64(N), 0x0FFF_FFFF_FFFF_FFFF) | |
let numOct = min(UInt64(N), 0x0000_03FF_FFFF_FFFF) | |
let numBin = min(UInt64(N), 0x7FFF) | |
let segments = [ | |
"abc", | |
String(numHex, radix: 16), | |
"0123456789", | |
String(Double.pi/2), | |
"*barely* small!", | |
String(numOct, radix: 8), | |
"", | |
String(numBin, radix: 2), | |
] | |
assert(segments.count == 8) | |
func getSegment(_ i: Int) -> String { | |
return getString(segments[i]) | |
} | |
let reps = 100 | |
for _ in 1...100*N { | |
for _ in 1...reps { | |
blackHole(""" | |
\(getSegment(0)) \(getSegment(1))/\(getSegment(2))_\(getSegment(3)) | |
\(getSegment(4)) \(getSegment(5)), \(getSegment(6))~~\(getSegment(7)) | |
""") | |
} | |
} | |
} | |
@inline(never) | |
public func run_CharacterPropertiesPrecomputed(_ N: Int) { | |
for _ in 1...N*10 { | |
for c in workload { | |
blackHole(isControlPrecomputed(c)) | |
blackHole(isAlphanumericPrecomputed(c)) | |
blackHole(isLowercasePrecomputed(c)) | |
blackHole(isPunctuationPrecomputed(c)) | |
blackHole(isWhitespacePrecomputed(c)) | |
blackHole(isLetterPrecomputed(c)) | |
blackHole(isUppercasePrecomputed(c)) | |
blackHole(isDecimalPrecomputed(c)) | |
blackHole(isNewlinePrecomputed(c)) | |
blackHole(isCapitalizedPrecomputed(c)) | |
} | |
} | |
} | |
@inline(never) | |
public func run_StringMatch(_ N: Int) { | |
for _ in 1...N*100 { | |
for (regex, text) in tests { | |
_ = match(regexp: regex,text: text) | |
} | |
} | |
} | |
@inline(never) | |
public func run_CharIteration_punctuatedJapanese_unicodeScalars_Backwards(_ N: Int) { | |
for _ in 1...unicodeScalarsMultiplier*N { | |
for c in punctuatedJapaneseCharacters { | |
for u in c.unicodeScalars.reversed() { | |
count |= Int(u.value) | |
} | |
} | |
} | |
} | |
@inline(never) | |
public func run_CharIndexing_punctuatedJapanese_unicodeScalars(_ N: Int) { | |
for _ in 1...unicodeScalarsMultiplier*N { | |
for c in punctuatedJapaneseCharacters { | |
let s = c.unicodeScalars | |
for i in s.indices { | |
count |= Int(s[i].value) | |
} | |
} | |
} | |
} | |
@inline(never) | |
public func run_CharIndexing_punctuatedJapanese_unicodeScalars_Backwards(_ N: Int) { | |
for _ in 1...unicodeScalarsMultiplier*N { | |
for c in punctuatedJapaneseCharacters { | |
let s = c.unicodeScalars | |
for i in s.indices.reversed() { | |
count |= Int(s[i].value) | |
} | |
} | |
} | |
} | |
@inline(never) | |
public func run_Dictionary3OfObjects(_ N: Int) { | |
let size1 = 100 | |
let reps = 20 | |
let ref_result = "1 99 20 1980" | |
var hash1 : [ Box<String> : Box<Int> ] = [:] | |
var hash2 : [ Box<String> : Box<Int> ] = [:] | |
var res = "" | |
for _ in 1...N { | |
hash1 = [:] | |
for i in 0..<size1 { | |
hash1[Box("foo_" + String(i))] = Box(i) | |
} | |
hash2 = hash1 | |
for _ in 1..<reps { | |
for (k, v) in hash1 { | |
hash2[k] = Box(hash2[k]!.value + v.value) | |
} | |
} | |
res = (String(hash1[Box("foo_1")]!.value) + " " + String(hash1[Box("foo_99")]!.value) + " " + | |
String(hash2[Box("foo_1")]!.value) + " " + String(hash2[Box("foo_99")]!.value)) | |
if res != ref_result { | |
break | |
} | |
} | |
CheckResults(res == ref_result) | |
} | |
@inline(never) | |
func my_atoi_impl(_ input : String) -> Int { | |
switch input { | |
case "0": return 0 | |
case "1": return 1 | |
case "2": return 2 | |
case "3": return 3 | |
case "4": return 4 | |
case "5": return 5 | |
case "6": return 6 | |
case "7": return 7 | |
case "8": return 8 | |
case "9": return 9 | |
default: return 0 | |
} | |
} | |
#if _runtime(_ObjC) | |
var decimals : [NSDecimalNumber]! | |
func decimals(_ n: Int) { | |
decimals = (0..<n).map { NSDecimalNumber(value: $0) } | |
} | |
func releaseDecimals() { decimals = nil } | |
#else | |
func decimals(_ n: Int) {} | |
func releaseDecimals() {} | |
#endif | |
class Box_2 { | |
var v: Int | |
init(_ v: Int) { self.v = v } | |
} | |
var boxedNumbers : [Box_2]! | |
func boxedNumbers(_ n: Int) { boxedNumbers = (0..<n).map { Box_2($0) } } | |
func releaseboxedNumbers() { boxedNumbers = nil } | |
@inline(never) | |
public func run_MapReduce(_ N: Int) { | |
var numbers = [Int](0..<1000) | |
var c = 0 | |
for _ in 1...N*100 { | |
numbers = numbers.map { $0 &+ 5 } | |
c += numbers.reduce(0, &+) | |
} | |
CheckResults(c != 0) | |
} | |
@inline(never) | |
public func run_MapReduceAnyCollection(_ N: Int) { | |
let numbers = AnyCollection([Int](0..<1000)) | |
var c = 0 | |
for _ in 1...N*100 { | |
let mapped = numbers.map { $0 &+ 5 } | |
c += mapped.reduce(0, &+) | |
} | |
CheckResults(c != 0) | |
} | |
@inline(never) | |
public func run_MapReduceAnyCollectionShort(_ N: Int) { | |
let numbers = AnyCollection([Int](0..<10)) | |
var c = 0 | |
for _ in 1...N*10000 { | |
let mapped = numbers.map { $0 &+ 5 } | |
c += mapped.reduce(0, &+) | |
} | |
CheckResults(c != 0) | |
} | |
@inline(never) | |
public func run_MapReduceShort(_ N: Int) { | |
var numbers = [Int](0..<10) | |
var c = 0 | |
for _ in 1...N*10000 { | |
numbers = numbers.map { $0 &+ 5 } | |
c += numbers.reduce(0, &+) | |
} | |
CheckResults(c != 0) | |
} | |
@inline(never) | |
public func run_MapReduceSequence(_ N: Int) { | |
let numbers = sequence(first: 0) { $0 < 1000 ? $0 &+ 1 : nil } | |
var c = 0 | |
for _ in 1...N*100 { | |
let mapped = numbers.map { $0 &+ 5 } | |
c += mapped.reduce(0, &+) | |
} | |
CheckResults(c != 0) | |
} | |
@inline(never) | |
public func run_MapReduceLazySequence(_ N: Int) { | |
let numbers = sequence(first: 0) { $0 < 1000 ? $0 &+ 1 : nil } | |
var c = 0 | |
for _ in 1...N*100 { | |
let mapped = numbers.lazy.map { $0 &+ 5 } | |
c += mapped.reduce(0, &+) | |
} | |
CheckResults(c != 0) | |
} | |
@inline(never) | |
public func run_MapReduceLazyCollection(_ N: Int) { | |
let numbers = [Int](0..<1000) | |
var c = 0 | |
for _ in 1...N*100 { | |
let mapped = numbers.lazy.map { $0 &+ 5 } | |
c += mapped.reduce(0, &+) | |
} | |
CheckResults(c != 0) | |
} | |
@inline(never) | |
public func run_MapReduceLazyCollectionShort(_ N: Int) { | |
let numbers = [Int](0..<10) | |
var c = 0 | |
for _ in 1...N*10000 { | |
let mapped = numbers.lazy.map { $0 &+ 5 } | |
c += mapped.reduce(0, &+) | |
} | |
CheckResults(c != 0) | |
} | |
@inline(never) | |
public func run_MapReduceString(_ N: Int) { | |
let s = "thequickbrownfoxjumpsoverthelazydogusingasmanycharacteraspossible123456789" | |
var c: UInt64 = 0 | |
for _ in 1...N*100 { | |
c += s.utf8.map { UInt64($0 &+ 5) }.reduce(0, &+) | |
} | |
CheckResults(c != 0) | |
} | |
@inline(never) | |
public func run_MapReduceShortString(_ N: Int) { | |
let s = "12345" | |
var c: UInt64 = 0 | |
for _ in 1...N*100 { | |
c += s.utf8.map { UInt64($0 &+ 5) }.reduce(0, &+) | |
} | |
CheckResults(c != 0) | |
} | |
@inline(never) | |
public func run_MapReduceNSDecimalNumber(_ N: Int) { | |
#if _runtime(_ObjC) | |
let numbers: [NSDecimalNumber] = decimals | |
var c = 0 | |
for _ in 1...N*10 { | |
let mapped = numbers.map { $0.intValue &+ 5 } | |
c += mapped.reduce(0, &+) | |
} | |
CheckResults(c != 0) | |
#endif | |
} | |
@inline(never) | |
public func run_MapReduceNSDecimalNumberShort(_ N: Int) { | |
#if _runtime(_ObjC) | |
let numbers: [NSDecimalNumber] = decimals | |
var c = 0 | |
for _ in 1...N*1_000 { | |
let mapped = numbers.map { $0.intValue &+ 5 } | |
c += mapped.reduce(0, &+) | |
} | |
CheckResults(c != 0) | |
#endif | |
} | |
@inline(never) | |
public func run_Dictionary2(_ N: Int) { | |
let size = 500 | |
let ref_result = 199 | |
var res = 0 | |
for _ in 1...5*N { | |
var x: [String: Int] = [:] | |
for i in 1...size { | |
x[String(i, radix:16)] = i | |
} | |
res = 0 | |
for i in 0..<size { | |
let i2 = size-i | |
if x[String(i2)] != nil { | |
res += 1 | |
} | |
} | |
if res != ref_result { | |
break | |
} | |
} | |
CheckResults(res == ref_result) | |
} | |
@inline(never) | |
public func run_Dictionary2OfObjects(_ N: Int) { | |
let size = 500 | |
let ref_result = 199 | |
var res = 0 | |
for _ in 1...5*N { | |
var x: [Box<String>:Box<Int>] = [:] | |
for i in 1...size { | |
x[Box(String(i, radix:16))] = Box(i) | |
} | |
res = 0 | |
for i in 0..<size { | |
let i2 = size-i | |
if x[Box(String(i2))] != nil { | |
res += 1 | |
} | |
} | |
if res != ref_result { | |
break | |
} | |
} | |
CheckResults(res == ref_result) | |
} | |
@inline(never) | |
public func run_MapReduceClass(_ N: Int) { | |
let numbers: [Box_2] = boxedNumbers | |
var c = 0 | |
for _ in 1...N*10 { | |
let mapped = numbers.map { $0.v &+ 5 } | |
c += mapped.reduce(0, &+) | |
} | |
CheckResults(c != 0) | |
} | |
@inline(never) | |
public func run_MapReduceClassShort(_ N: Int) { | |
let numbers: [Box_2] = boxedNumbers | |
var c = 0 | |
for _ in 1...N*1_000 { | |
let mapped = numbers.map { $0.v &+ 5 } | |
c += mapped.reduce(0, &+) | |
} | |
CheckResults(c != 0) | |
} | |
@inline(never) | |
public func run_Calculator(_ N: Int) { | |
var c = 0 | |
for _ in 1...N*800 { | |
c += my_atoi_impl(identity("1")) | |
c += my_atoi_impl(identity("2")) | |
c += my_atoi_impl(identity("3")) | |
c += my_atoi_impl(identity("4")) | |
c += my_atoi_impl(identity("5")) | |
c += my_atoi_impl(identity("6")) | |
c += my_atoi_impl(identity("7")) | |
c += my_atoi_impl(identity("8")) | |
c += my_atoi_impl(identity("9")) | |
c += my_atoi_impl(identity("10")) | |
c -= 45 | |
} | |
CheckResults(c == 0) | |
} | |
let text = [ | |
// Text from http://en.wikipedia.org/wiki/Hash_table | |
"hash", "table", | |
"in", "computing", "a", "hash", "table", "also", "hash", "map", "is", | |
"a", "data", "structure", "used", "to", "implement", "an", "associative", | |
"array", "a", "structure", "that", "can", "map", "keys", "to", "values", | |
"a", "hash", "table", "uses", "a", "hash", "function", "to", "compute", | |
"an", "index", "into", "an", "array", "of", "buckets", "or", "slots", | |
"from", "which", "the", "correct", "value", "can", "be", "found", | |
"ideally", "the", "hash", "function", "will", "assign", "each", "key", | |
"to", "a", "unique", "bucket", "but", "this", "situation", "is", | |
"rarely", "achievable", "in", "practice", "usually", "some", "keys", | |
"will", "hash", "to", "the", "same", "bucket", "instead", "most", "hash", | |
"table", "designs", "assume", "that", "hash", "collisions", "different", | |
"keys", "that", "are", "assigned", "by", "the", "hash", "function", "to", | |
"the", "same", "bucket", "will", "occur", "and", "must", "be", | |
"accommodated", "in", "some", "way", "in", "a", "well", "dimensioned", | |
"hash", "table", "the", "average", "cost", "number", "of", | |
"instructions", "for", "each", "lookup", "is", "independent", "of", | |
"the", "number", "of", "elements", "stored", "in", "the", "table", | |
"many", "hash", "table", "designs", "also", "allow", "arbitrary", | |
"insertions", "and", "deletions", "of", "key", "value", "pairs", "at", | |
"amortized", "constant", "average", "cost", "per", "operation", "in", | |
"many", "situations", "hash", "tables", "turn", "out", "to", "be", | |
"more", "efficient", "than", "search", "trees", "or", "any", "other", | |
"table", "lookup", "structure", "for", "this", "reason", "they", "are", | |
"widely", "used", "in", "many", "kinds", "of", "computer", "software", | |
"particularly", "for", "associative", "arrays", "database", "indexing", | |
"caches", "and", "sets", | |
"hashing", | |
"the", "idea", "of", "hashing", "is", "to", "distribute", "the", | |
"entries", "key", "value", "pairs", "across", "an", "array", "of", | |
"buckets", "given", "a", "key", "the", "algorithm", "computes", "an", | |
"index", "that", "suggests", "where", "the", "entry", "can", "be", | |
"found", "index", "f", "key", "array", "size", "often", "this", "is", | |
"done", "in", "two", "steps", "hash", "hashfunc", "key", "index", "hash", | |
"array", "size", "in", "this", "method", "the", "hash", "is", | |
"independent", "of", "the", "array", "size", "and", "it", "is", "then", | |
"reduced", "to", "an", "index", "a", "number", "between", "and", "array", | |
"size", "using", "the", "modulus", "operator", "in", "the", "case", | |
"that", "the", "array", "size", "is", "a", "power", "of", "two", "the", | |
"remainder", "operation", "is", "reduced", "to", "masking", "which", | |
"improves", "speed", "but", "can", "increase", "problems", "with", "a", | |
"poor", "hash", "function", | |
"choosing", "a", "good", "hash", "function", | |
"a", "good", "hash", "function", "and", "implementation", "algorithm", | |
"are", "essential", "for", "good", "hash", "table", "performance", "but", | |
"may", "be", "difficult", "to", "achieve", "a", "basic", "requirement", | |
"is", "that", "the", "function", "should", "provide", "a", "uniform", | |
"distribution", "of", "hash", "values", "a", "non", "uniform", | |
"distribution", "increases", "the", "number", "of", "collisions", "and", | |
"the", "cost", "of", "resolving", "them", "uniformity", "is", | |
"sometimes", "difficult", "to", "ensure", "by", "design", "but", "may", | |
"be", "evaluated", "empirically", "using", "statistical", "tests", "e", | |
"g", "a", "pearson", "s", "chi", "squared", "test", "for", "discrete", | |
"uniform", "distributions", "the", "distribution", "needs", "to", "be", | |
"uniform", "only", "for", "table", "sizes", "that", "occur", "in", "the", | |
"application", "in", "particular", "if", "one", "uses", "dynamic", | |
"resizing", "with", "exact", "doubling", "and", "halving", "of", "the", | |
"table", "size", "s", "then", "the", "hash", "function", "needs", "to", | |
"be", "uniform", "only", "when", "s", "is", "a", "power", "of", "two", | |
"on", "the", "other", "hand", "some", "hashing", "algorithms", "provide", | |
"uniform", "hashes", "only", "when", "s", "is", "a", "prime", "number", | |
"for", "open", "addressing", "schemes", "the", "hash", "function", | |
"should", "also", "avoid", "clustering", "the", "mapping", "of", "two", | |
"or", "more", "keys", "to", "consecutive", "slots", "such", "clustering", | |
"may", "cause", "the", "lookup", "cost", "to", "skyrocket", "even", "if", | |
"the", "load", "factor", "is", "low", "and", "collisions", "are", | |
"infrequent", "the", "popular", "multiplicative", "hash", "3", "is", | |
"claimed", "to", "have", "particularly", "poor", "clustering", | |
"behavior", "cryptographic", "hash", "functions", "are", "believed", | |
"to", "provide", "good", "hash", "functions", "for", "any", "table", | |
"size", "s", "either", "by", "modulo", "reduction", "or", "by", "bit", | |
"masking", "they", "may", "also", "be", "appropriate", "if", "there", | |
"is", "a", "risk", "of", "malicious", "users", "trying", "to", | |
"sabotage", "a", "network", "service", "by", "submitting", "requests", | |
"designed", "to", "generate", "a", "large", "number", "of", "collisions", | |
"in", "the", "server", "s", "hash", "tables", "however", "the", "risk", | |
"of", "sabotage", "can", "also", "be", "avoided", "by", "cheaper", | |
"methods", "such", "as", "applying", "a", "secret", "salt", "to", "the", | |
"data", "or", "using", "a", "universal", "hash", "function", | |
"perfect", "hash", "function", | |
"if", "all", "keys", "are", "known", "ahead", "of", "time", "a", | |
"perfect", "hash", "function", "can", "be", "used", "to", "create", "a", | |
"perfect", "hash", "table", "that", "has", "no", "collisions", "if", | |
"minimal", "perfect", "hashing", "is", "used", "every", "location", "in", | |
"the", "hash", "table", "can", "be", "used", "as", "well", "perfect", | |
"hashing", "allows", "for", "constant", "time", "lookups", "in", "the", | |
"worst", "case", "this", "is", "in", "contrast", "to", "most", | |
"chaining", "and", "open", "addressing", "methods", "where", "the", | |
"time", "for", "lookup", "is", "low", "on", "average", "but", "may", | |
"be", "very", "large", "proportional", "to", "the", "number", "of", | |
"entries", "for", "some", "sets", "of", "keys" | |
] | |
// Fill the dictionary with words from the first half of the text | |
let half: Dictionary<String, Bool> = { | |
var dict: Dictionary<String, Bool> = [:] | |
for i in 0 ..< text.count/2 { | |
let word = text[i] | |
dict[word] = true | |
} | |
return dict | |
}() | |
@inline(never) | |
public func run_Dictionary(_ scale: Int) { | |
var dict: Dictionary<String, Bool> = [:] | |
let N = 5*scale | |
// Check performance of filling the dictionary: | |
for _ in 1...N { | |
dict = [:] | |
for word in text { | |
dict[word] = true | |
} | |
} | |
CheckResults(dict.count == 270) | |
// Check performance of searching in the dictionary: | |
dict = half | |
// Count number of words from the first half in the entire text | |
var count = 0 | |
for _ in 1...N { | |
for word in text { | |
if dict[word] != nil { | |
count += 1 | |
} | |
} | |
} | |
CheckResults(count == N*541) | |
} | |
// Fill the dictionary with words from the first half of the text | |
let halfObjects: Dictionary<Box<String>, Box<Bool>> = { | |
var dict: Dictionary<Box<String>, Box<Bool>> = [:] | |
for i in 0 ..< text.count/2 { | |
let word = text[i] | |
dict[Box(word)] = Box(true) | |
} | |
return dict | |
}() | |
@inline(never) | |
public func run_DictionaryOfObjects(scale: Int) { | |
var dict: Dictionary<Box<String>, Box<Bool>> = [:] | |
let N = 5*scale | |
// Check performance of filling the dictionary: | |
for _ in 1...N { | |
dict = [:] | |
for word in text { | |
dict[Box(word)] = Box(true) | |
} | |
} | |
CheckResults(dict.count == 270) | |
// Check performance of searching in the dictionary: | |
dict = halfObjects | |
// Count number of words from the first half in the entire text | |
var count = 0 | |
for _ in 1...N { | |
for word in text { | |
if dict[Box(word)] != nil { | |
count += 1 | |
} | |
} | |
} | |
CheckResults(count == N*541) | |
} | |
@inline(never) | |
public func run_Join(_ N: Int) { | |
var array: [String] = [] | |
for x in 0..<1000 * N { | |
array.append(String(x)) | |
} | |
_ = array.joined(separator: "") | |
_ = array.joined(separator: " ") | |
} | |
@inline(never) | |
public func run_SubstringEqualString(_ N: Int) { | |
var string = "pen,pineapple,apple,pen" | |
string += ",✒️,🍍,🍏,✒️" | |
let substrings = string.split(separator: ",") | |
let pineapple = "pineapple" | |
let apple = "🍏" | |
var count = 0 | |
for _ in 1...N*500 { | |
for s in substrings { | |
if s == pineapple || s == apple { count = count &+ 1 } | |
} | |
} | |
CheckResults(count == 2*N*500) | |
} | |
let _substrings = "pen,pineapple,apple,pen,✒️,🍍,🍏,✒️".split(separator: ",") | |
let _comparison = _substrings + ["PPAP"] | |
@inline(never) | |
public func run_SubstringComparable(_ N: Int) { | |
let substrings = _substrings // without this alias, there was 25% slowdown | |
let comparison = _comparison // due to increased retain/release traffic 🤷 | |
var count = 0 | |
for _ in 1...N*500 { | |
if substrings.lexicographicallyPrecedes(comparison) { | |
count = count &+ 1 | |
} | |
} | |
CheckResults(count == N*500) | |
} | |
import Dispatch | |
func time<T>(_ _caller : String = #function, _ block: () -> T) -> T { | |
let start = DispatchTime.now() | |
let res = block() | |
let end = DispatchTime.now() | |
let milliseconds = (end.uptimeNanoseconds - start.uptimeNanoseconds) / 1_000_000 | |
print("\(_caller)\t\(milliseconds)") | |
// print("result: \(res)") | |
return res | |
} | |
let N = 1000 | |
print("Running...") | |
time("StringComparison_abnormal") { | |
run_StringComparison_abnormal(N * 2) | |
} | |
time("Chars2") { | |
run_Chars(N * 3 / 2) | |
} | |
time("StringFromLongWholeSubstringGeneric") { | |
run_StringFromLongWholeSubstringGeneric(N * 60) | |
} | |
time("SubstringComparable") { | |
run_SubstringComparable(N * 100) | |
} | |
time("StringFromLongWholeSubstring") { | |
run_StringFromLongWholeSubstring(N * 60) | |
} | |
time("Calculator") { | |
run_Calculator(N * 9) | |
} | |
time("StringComparison_fastPrenormal") { | |
run_StringComparison_fastPrenormal(N * 2) | |
} | |
time("StrComplexWalk") { | |
run_StrComplexWalk(N) | |
} | |
time("OpenClose") { | |
run_OpenClose(N * 28) | |
} | |
time("SortStringsUnicode") { | |
run_SortStringsUnicode(N * 6 / 10) | |
} | |
time("StringComparison_latin1") { | |
run_StringComparison_latin1(N * 9 / 4) | |
} | |
time("StringWalk") { | |
run_StringWalk(N) | |
} | |
time("StringHasSuffixUnicode") { | |
run_StringHasSuffixUnicode(N / 100) | |
} | |
time("StringEqualPointerComparison") { | |
run_StringEqualPointerComparison(N * 4) | |
} | |
time("Dictionary3") { | |
run_Dictionary3(N * 5) | |
} | |
time("StringWordBuilderReservingCapacity") { | |
run_StringWordBuilderReservingCapacity(N / 5) | |
} | |
time("StringHasPrefixUnicode") { | |
run_StringHasPrefixUnicode(N / 100) | |
} | |
time("Dictionary") { | |
run_Dictionary(N * 9 / 4) | |
} | |
time("RemoveWhereFilterString") { | |
run_RemoveWhereFilterString(N * 2) | |
} | |
time("CSVParsing2") { | |
run_CSVParsing(N) | |
} | |
time("CharacterLiteralsSmall") { | |
run_CharacterLiteralsSmall(N * 10) | |
} | |
time("MapReduceString") { | |
run_MapReduceString(N * 30) | |
} | |
time("WordCountUniqueASCII") { | |
run_WordCountUniqueASCII(N * 7 / 10) | |
} | |
time("Dictionary2") { | |
run_Dictionary2(N * 2) | |
} | |
time("StringHashing_abnormal") { | |
run_StringHashing_abnormal(N * 12 / 10) | |
} | |
time("RemoveWhereQuadraticString") { | |
run_RemoveWhereQuadraticString(N * 4) | |
} | |
time("StringInterpolationManySmallSegments") { | |
run_StringInterpolationManySmallSegments(N / 11) | |
} | |
time("StringWordBuilder") { | |
run_StringWordBuilder(N / 2) | |
} | |
time("StringHashing_zalgo") { | |
run_StringHashing_zalgo(N / 2) | |
} | |
time("StringMatch") { | |
run_StringMatch(N / 9) | |
} | |
time("Join") { | |
run_Join(N * 3) | |
} | |
time("StringBuilderLong") { | |
run_StringBuilderLong(N * 8 / 10) | |
} | |
time("StringHashing_ascii") { | |
run_StringHashing_ascii(N * 33) | |
} | |
time("CharacterPropertiesStashedMemo") { | |
run_CharacterPropertiesStashedMemo(N * 9 / 10) | |
} | |
time("RomanNumbers") { | |
run_RomanNumbers(N / 60) | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment