Swift slow on object creation and setValue:forKey: -


i accessing local mysql database in swift code translated objective c. in objective c performs fast, in swift 10 15 times slower depending on count of records.

i using generics create data transfer objects. sql select method has signature:

func sqlselect<t: nsobject>(select: string) -> [t]? 

first fetched 20.000 records mysql database , returned empty array of ts. time needed 0.3 seconds, not fast acceptable.

then created 20.000 t instances in above function , appended them local swift array, fast: 0.1 sec.

now creating 5 nsnumbers , 9 strings fetched mysql data slow: 1.2 sec. 280.000 object creations (14 * 20.000 = 280.000). additional 1.4 seconds used setting properties of each t instance setvalue:forkey:

the same code in objective c , in xojo (aka realbasic) fast: less 1 second compared more 3 seconds.

what options make swift code faster?

first edit – added source code:

func sqlselect<t: nsobject>(select: string) -> [t]? {   ... // error handling omitted   var statement = select.cstringusingencoding(nsutf8stringencoding)!   var err = mysql_real_query(mysql, statement, strlen(statement))   ... // error handling omitted   var mysql_result: unsafemutablepointer<mysql_res> = mysql_store_result(mysql)   ... // error handling omitted   var mysql_fields: unsafemutablepointer<mysql_field> = mysql_fetch_fields(mysql_result)   ... // error handling omitted   var names = [string]()   var types = [uint32]()   var columncount = mysql_num_fields(mysql_result)   i: int in 0...columncount - 1 {     names.append(string.fromcstring(mysql_fields[i].name)!)     types.append(mysql_fields[i].type.value)   }   var records = [t]()   var recordcount = int(mysql_num_rows(mysql_result))   records.reservecapacity(recordcount - 1)   r in 0...recordcount - 1 {     var row = mysql_fetch_row(mysql_result)     var record = t()     c: int in 0...columncount - 1 {         var value: anyobject?         if row[c] == nil {           value = nil;         } else {           switch types[c] {           case mysql_type_tiny.value, mysql_type_short.value, mysql_type_int24.value, mysql_type_long.value:               value = nsnumber(int: atoi(row[c]))           case mysql_type_float.value:               value = nsnumber(float: strtof(row[c], nil))           ... // other data types omitted           case mysql_type_tiny_blob.value, mysql_type_blob.value, mysql_type_medium_blob.value, mysql_type_long_blob.value, mysql_type_bit.value,                  mysql_type_set.value, mysql_type_enum.value, mysql_type_geometry.value, mysql_type_var_string.value, mysql_type_string.value:               if mysql_fields[c].charsetnr == 63 {                 value = nsdata(bytes: row[c], length: int(strlen(row[c])))               } else {                 value = string.fromcstring(row[c])!               }           case mysql_type_null.value:               value = nil           default:               value = nil           }           record.setvalue(value, forkey: names[c])         }     }     records.append(record)   }   return records } 

second edit: results running code in instruments

it shows approximately 40% of time spent in:

-[nsobject(nskeyvaluecoding) setvalue:forkey:] 

and deeper in function these 3 functions:

@objc swift._nscontiguousstring.getcharacters (swift._nscontiguousstring)(swift.unsafemutablepointer<swift.uint16>, range : c._swiftnsrange) -> () _swift_retain_(swift::heapobject*) _swift_release_(swift::heapobject*) 

the second biggest time use in:

swift.array.append <a>(inout [a])(a) -> () 

so solution keep access database in objective c code.


Comments

Popular posts from this blog

facebook - android ACTION_SEND to share with specific application only -

python - Creating a new virtualenv gives a permissions error -

javascript - cocos2d-js draw circle not instantly -