How to print array of integers into console quickly?
I have an array of integers
a = [1,2,3,4]
When I do
a.join
Ruby internally calls the开发者_开发技巧 to_s
method 4 times, which is too slow for my needs.
What is the fastest method to output an big array of integers to console?
I mean:
a = [1,2,3,4........,1,2,3,9], should be:
1234........1239
If you want to print an integer to stdout, you need to convert it to a string first, since that's all stdout understands. If you want to print two integers to stdout, you need to convert both of them to a string first. If you want to print three integers to stdout, you need to convert all three of them to a string first. If you want to print one billion integers to stdout, you need to convert all one billion of them to a string first.
There's nothing you, we, or Ruby, or really any programming language can do about that.
You could try interleaving the conversion with the I/O by doing a lazy stream implementation. You could try to do the conversion and the I/O in parallel, by doing a lazy stream implementation and separating the conversion and the I/O into two separate threads. (Be sure to use a Ruby implementation which can actually execute parallel threads, not all of them can: MRI, YARV and Rubinius can't, for example.)
You can parallelize the conversion, by converting separate chunks in the array in separate threads in parallel. You can even buy a billion core machine and convert all billion integers at the same time in parallel.
But even then, the fact of the matter remains: every single integer needs to be converted. Whether you do that one after the other first, and then print them or do it one after the other interleaved with the I/O or do it one after the other in parallel with the I/O or even convert all of them at the same time on a billion core CPU: the number of needed conversions does not magically decrease. A large number of integers means a large number of conversions. Even if you do all billion conversions in a billion core CPU in parallel, it's still a billion conversions, i.e. a billion calls to to_s
.
As stated in the comments above if Fixnum.to_s
is not performing quickly enough for you then you really need to consider whether Ruby is the correct tool for this particular task.
However, there are a couple of things you could do that may or may not be applicable for your situation.
If the building of the array happens outside the time critical area then build the array, or a copy of the array with strings instead of integers. With my small test of 10000 integers this is approximately 5 times faster.
If you control both the reading and the writing process then use Array.pack
to write the output and String.unpack
to read the result. This may not be quicker as pack seems to call Fixnum.to_int
even when the elements are already Integers.
I expect these figures would be different with each version of Ruby so it is worth checking for your particular target version.
The slowness in you program does not come from to_s
being called 4 times, but from printing to the console. Console output is slow, and you can't really do anything about it.
For single digits you can do this
[1,2,3,4,5].map{|x|(x+48).chr}.join
If you need to speed up larger numbers you could try memoizing the result of to_s
Unless you really need to see the numbers on the console (and it sound like you do not) then write them to a file in binary - should be much faster.
And you can pipe binary files into other programs if that is what you need to do, not just text.
精彩评论