Nicer way to convert number (ascii code) into character?

1,074 views
Skip to first unread message

James Wendel

unread,
Dec 26, 2012, 10:11:55 PM12/26/12
to mi...@dartlang.org
I decided to use dart to generate some simple values that I wanted to paste into excel, and I started to wonder about the ease (and speed) of converting numbers into letters.  I used to benchmark_harness and did a little test.

First, here is the original code I wrote:

List<String> letters = [ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o' ];
for (num i=1; i < 214; i++) {
 
for (num letter=0; letter < 15; letter++) {
   
print("=${letters[letter]}$i");
 
}
}


I've modified it to remove the useless string concatenation and printing (as it hides the speeds of doing character convert).  The 2 test I came down to:

TEST1:
    var a;
   
for (num i=1; i < 10000; i++) {
     
for (num letter='a'.charCodeAt(0); letter < 'o'.charCodeAt(0); letter++) {
        a
= new String.fromCharCodes([letter]);
     
}
   
}

VS

TEST2:
    List<String> letters = [ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o' ];
   
var a;
   
for (num i=1; i < 10000; i++) {
     
for (num letter=0; letter < 15; letter++) {
        a
= letters[letter];
     
}
   
}



Runtimes for TEST1 (5 runs):
273750 us.
269000 us.
275375 us.
269750 us.
283875 us.


Runtimes for TEST2 (5 runs):
2389 us.
2446 us.
2382 us.
2518 us.
2430 us.


The point I'm trying to make is that conversion of a number into a character is slow with the method currently available to us.  Unless I'm missing another way to convert, I think it would be nice to have an easier way to convert a num into a character (String).

The other issue I have is using String.fromCharCodes() is a bit annoying as it requires creating a list of codes to convert.  I'd imagine if I could do a single character at a time, it would be faster.

Lasse R.H. Nielsen

unread,
Dec 27, 2012, 8:40:10 AM12/27/12
to mi...@dartlang.org
You may want to change test1 to:
    var a;
    // Don't do these calls on every iteration.
    num start = 'a'.charCodeAt(0);
    num end = 'o'.charCodeAt(0);
    
for (num i=1; i < 10000; i++) {
      
for (num letter=start; letter < end;letter++) {

        a 
= new String.fromCharCodes([letter]);
      
}
    
}


It should be possible to optimize the charCodeAt calls away, but I don't think it's done yet.
I agree that it's still too slow.

The preferable way should be:

    var a;
    num start = 'a'.charCodeAt(0);
    num end = 'o'.charCodeAt(0);
    for (num i 1; i < 10000; i++) {
      StringBuffer buf = new StringBuffer();
      for (num letter=start; letter < end;letter++) {
        buf.addCharCode(letter);

      
}
      a = buf.toString();
    
}

but StringBuffer isn't optimized in any way yet, so it also just uses String.fromCharCodes (which is a slow and roundabout way to make a string).
We'll get a String.fromCharCode, so you can at least omit the extra List wrapper. If that gets optimized, I think you should be able to get down to the time of Test2.
/L


--
Consider asking HOWTO questions at Stack Overflow: http://stackoverflow.com/tags/dart
 
 



--
Lasse R.H. Nielsen - l...@google.com  
'Faith without judgement merely degrades the spirit divine'
Google Denmark ApS - Frederiksborggade 20B, 1 sal - 1360 København K - Denmark - CVR nr. 28 86 69 84

James Wendel

unread,
Dec 27, 2012, 8:56:40 AM12/27/12
to mi...@dartlang.org
Thanks for the reply. I believe I did try an alternate of hard coding the ASCII codes for 'a' and 'o' but it had minimal impact on the results.

Good to know that optimizations are coming for Strings still. I just wanted to check and see if it was on your radar.

Thanks again for creating an awesome language.

-James

Justin Fagnani

unread,
Dec 27, 2012, 4:21:42 PM12/27/12
to General Dart Discussion
James,

I think you're mostly seeing the cost of object creation. With test1 you're creating a new List and a new String every iteration, while test2 creates no new objects in the loop.

I tried moving the list passed to fromCharCodes() in test1 outside the loop and reusing it and halved the time. Moving the charCodeAt(0) calls outside the loop got about 10% improvement. Then I tried to put test2 on even footing by creating a new String in each loop. Since fromCharCode() is the only String constructor, to create new Strings from the letters I used interpolation. That increased the time to the original test1, which is twice as slow as the slightly optimized test1. So fromCharCodes() compares well against interpolation here. Either way, creating a new String is going to be a lot more expensive that just retrieving a reference to an existing one.

btw, I also tried an empty loop, which was only a bit faster than the original test2, which makes sense given how little that line is doing. (though if the VM knew that [] was side-effect-free it could optimize away the whole loop)

Cheers,
  Justin



--
Reply all
Reply to author
Forward
0 new messages