Reputation: 11645
I have a lot of string operations like concatenating, replacing, finding indexes of large texts (10000 characters) ...
The operations are too slow. Exactly the same doing in Java/Android is faster.
I am asking if the same in Objective-C is faster.
I am a iOS newby and only know Swift so far (so I can't try simply), thats why I asking if Objective-C with swift-bridging could be faster?
Update I have a lot of substring operations in a loop (also replace), which concatenates a new String. NewText & sText are of Type String, sText has about 10000 characters, the loop will have about 100 iterations:
NewText=NewText + sText.substring(istart,endIndex: iend);
func substring(startIndex: Int, endIndex: Int) -> String
{
//println("substring" + self);
var start = advance(self.startIndex, startIndex)
var end = advance(self.startIndex, endIndex)
return self.substringWithRange(Range<String.Index>(start: start, end: end))
}
UPDATE 2 Performance Test (replace string) with String, NSString, CFString
From the information you all provided, it seems not to be a difference between Objective-C and Swift. It is more which Stringtype to use. I made a performance test with the Types: String, NSString and CFString
func performance_test_with_strings(){
var sTextNSString:NSString="<1000 character> searchstring end";
var sTextString=String(sTextNSString);
//var sTextCFString:CFMuString=sTextNSString as CFString;
var stoReplace="searchstring";
var sTextCFString:CFMutableStringRef=CFStringCreateMutable(nil, 0);
CFStringAppend(sTextCFString, sTextString as! CFMutableStringRef);
var stoReplaceCFString="searchstring" as CFString;
var stoReplaceCFString2="mynewstring" as CFString;
var chrono1:Chronometer=Chronometer();
chrono1.start();
for var i=0;i<10000;i++ {
var newText=sTextNSString.stringByReplacingOccurrencesOfString(stoReplace, withString: "mynewstring");
}
chrono1.zwischenstand("after replacing with a NSString");
for var i=0;i<10000;i++ {
var newText=sTextString.stringByReplacingOccurrencesOfString(stoReplace, withString: "mynewstring");
}
chrono1.zwischenstand("after replacing with a String");
//CFShow(cfmutablestring);
for var i=0;i<5000;i++ {
// To compare this correct I'll have to do 2 replacments in a loop of only 5000 iterations
specialreplace(&sTextCFString,sWhat: "searchstring",sTo: "mynewstring");
specialreplace(&sTextCFString,sWhat: "mynewstring",sTo: "searchstring");
}
chrono1.zwischenstand("after replacing with a CFString");
chrono1.showMeasures();
exit(0);
}
func specialreplace(inout sText:CFMutableStringRef,sWhat:String, sTo:String){
var cfRange = CFStringFind(sText, sWhat as CFString, nil);
CFStringReplace(sText, cfRange, sTo as CFString);
}
class Chronometer: NSObject {
var mearures:[(String,Double)]=[(String,Double)]();
var starttime = NSDate(); // <<<<<<<<<< end time
var lasttime:Double=0;
func start(){
starttime = NSDate(); // <<<<<<<<<< end time
}
func zwischenstand(mytext:String){
var zwischenzeit = NSDate();
let timeInterval: Double = zwischenzeit.timeIntervalSinceDate(starttime);
let actualtimeconsumed=timeInterval-lasttime;
mearures.append((mytext,actualtimeconsumed));
var textshow=mytext + " actual : " + String(stringInterpolationSegment: actualtimeconsumed);
textshow=textshow + " total :" + String(stringInterpolationSegment: timeInterval);
println(textshow);
lasttime=timeInterval;
}
func showMeasures(){
var total:Double=0;
for var i=0 ; i < mearures.count ; i++ {
let text=mearures[i].0;
let measure=mearures[i].1;
println(text + " : " + String(stringInterpolationSegment: measure));
total = total + measure;
}
println("total : " + String(stringInterpolationSegment: total));
}
}
after replacing with a NSString actual : 1.15460801124573 total :1.15460801124573
after replacing with a String actual : 1.15148597955704 total :2.30609399080276
after replacing with a CFString actual : 0.323610007762909 total :2.62970399856567
after replacing with a NSString : 1.15460801124573
after replacing with a String : 1.15148597955704
after replacing with a CFString : 0.323610007762909
total : 2.62970399856567
So my conclusion for my case its the best to use CFString.
Is this test correct?
Upvotes: 2
Views: 1823
Reputation: 86651
One thing to note about Swift is that it attempts to do Unicode handling properly. Java and Cocoa's NSString
do not do this. They both assume that the string is encoded in UTF-16 and each character only takes one 16 bit integer. Therefore string handling only works properly for what is called the Basic Multilingual Plane
With NSString
and in Java, finding the nth "character" is easy, you just index to the nth item in the array, but that could easily be the second part of a surrogate pair. You also can't tell if that really is the nth character except by scanning all the previous characters to make sure none of them are two word characters.
Swift does this properly, but at the expense of a lot of linear (aka slow) scanning through strings.
Upvotes: 3
Reputation: 2052
I would use Core Foundation's CFMutableString operations. I generally tend to find them much faster than their Cocoa variants.
Upvotes: 1