Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Output performance for numbers #51

Open
stevebleazard opened this issue Feb 9, 2018 · 3 comments
Open

Output performance for numbers #51

stevebleazard opened this issue Feb 9, 2018 · 3 comments
Labels
backlog Low-priority tasks likely to not get done anytime soon performance Performance optimization

Comments

@stevebleazard
Copy link

When converting numbers to strings string_of_float has a significant performance impact when the number is an INT. Detecting INTs and using string_of_int significantly improves performance. Thus, using

let f2s f = 
  (* Check value is in the JSON integer range, maybe not necessary *)
  if f > 9007199254740991. || f < -9007199254740991. then string_of_float f 
  else
    let i = int_of_float f in
    let f1 = float_of_int i in
    if f1 = f then string_of_int i 
    else string_of_float f 

Has a cost of around 6.5% for floats but results in around 4x performance improvement for INTs. Here are comparisons of straight string_of_float and f2s for 1,000,000 conversions:

string_of_float

1,552,011,783      cycles
2,958,207,469      instructions

f2s

  363,014,703      cycles                   
  945,099,124      instructions

Is it worth integrating this into the encoder?

@mjambon
Copy link
Member

mjambon commented Feb 9, 2018

This is interesting. Why did you close the issue?

I was about to suggest to push for the change in the standard library at https://caml.inria.fr/mantis.

@stevebleazard
Copy link
Author

Confusion on my part, I have re-opened

@stevebleazard stevebleazard reopened this Feb 10, 2018
@mjambon
Copy link
Member

mjambon commented Mar 2, 2018

It's a bit more complicated on 32-bit platforms (31-bit ints) because the conversion from float to int works on a restricted range (float min_int to float max_int). Here are options I can think of:

  • use a fixed range regardless of the platform, defined as the range of 31-bit ints;
  • detect the platform (e.g. using Sys.word_size) and run one function or the other accordingly.

Code for the second option could be like this:

let fast_string_of_float =
  match Sys.word_size with
  | 64 -> fast_string_of_float_64
  | 32 -> fast_string_of_float_32
  | _ -> string_of_float

There's also the question of whether this optimization benefits everyone. In some applications, integers may be extremely rare, in which case this "optimization" would slow them down by 6.5% (based on your report).

Atdgen could support a global (command-line) or type-specific option that turns this on or off.

@mjambon mjambon added performance Performance optimization backlog Low-priority tasks likely to not get done anytime soon labels Jun 2, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backlog Low-priority tasks likely to not get done anytime soon performance Performance optimization
Projects
None yet
Development

No branches or pull requests

2 participants