This pipeline is faster than the fastest other answer by a significant factor (see results). It uses tr and tac. It does need to utilize 2 ASCII bytes (\x00-\x7F) which don't exist in your data.
\x00 is typically a good choice, as is \x01, but you can use any ASCII byte which is not in the data.
In this example, SPACE and TAB as the delimiters characters. Delimiters can be multi-byte or single. The output delimiter is a single space.
Here is the command. The filename shows the numberof fields _x number of lines
<"$file" tr ' \t\n' '\0\0\1' |tr -s '\0' '\n' |tac |tr '\n' ' ' |tr '\1' '\n'
If you want/need to check for the unused bytes, you can check beforehand with this optional awk script. The overall time, even when running this optional script, is still significantly faster than other metods (so far :).. Here is the pre-processing script.
o=($(<"$file" char-ascii-not-in-stream)); x="${o[0]}"; y="${o[1]}"
<"$file" tr ' \t\n' "$x$x$y" |tr -s "$x" '\n' |tac |tr '\n' ' ' | tr '$y' '\n' >"$file".$user
This is the awk script: char-ascii-not-in-stream
#!/usr/bin/awk -f
{c[$0]} END{for(i=0;i<=127;i++) {if(sprintf("%c", i) in c);else {printf "\\%03o ",i}}}
The second set of times, for this script, include char-ascii-not-in-stream's time.
Peter.O {tr,tac,tr} ==== file_10_x10000
real 0m0.013s 0m0.015s
user 0m0.020s 0m0.020s
sys 0m0.008s 0m0.012s
user11136 {python} ===== file_10_x10000
real 0m0.057s
user 0m0.048s
sys 0m0.008s
jmp {python} =========== file_10_x10000
real 0m0.160s
user 0m0.160s
sys 0m0.000s
rush {awk} ============= file_10_x10000
real 0m0.121s
user 0m0.120s
sys 0m0.000s
##############################################
Peter.O {tr,tac,tr} ==== file_1000_x1000
real 0m0.048s 0m0.059s
user 0m0.040s 0m0.040s
sys 0m0.040s 0m0.048s
user11136 {python} ===== file_1000_x1000
real 0m0.158s
user 0m0.136s
sys 0m0.028s
jmp {python} =========== file_1000_x1000
real 0m0.327s
user 0m0.320s
sys 0m0.008s
rush {awk} ============= file_1000_x1000
real 0m0.832s
user 0m0.820s
sys 0m0s012s
##############################################
Peter.O {tr,tac,tr} ==== file_1000000_x50
real 0m5.221s 0m6.458s
user 0m4.208s 0m5.248s
sys 0m2.624s 0m2.396s
user11136 {python} ===== file_1000000_x50
real 0m16.286s
user 0m10.041s
sys 0m5.148s
jmp {python} =========== file_1000000_x50
real 0m22.845s
user 0m20.705s
sys 0m1.140s
rush {awk} ============= file_1000000_x50
real 0m44.793s
user 0m43.583s
sys 0m0.848s
##############################################