-
Notifications
You must be signed in to change notification settings - Fork 618
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
Fieldmap length and checksum optimization #42
Fieldmap length and checksum optimization #42
Conversation
A cache for strings of frequently used integers
Avoided some temporary IntField creation to compute length. In fact, the "isStringEquivalent" branch that I added is useless with previous commit on Message class, which directly compute length & checksum if possible. Change some 'for each' list iteration by old loop over index to avoid iterator allocations, as the jvm will not always do it for us.
NumbersCache is a bit of a memory/performance trade-off right? This is to do what - convert What's the performance of the cache vs the performance of Integer.toString()? 1000000 also seems arbitrary and high. The common numbers we see are going to be the fields themselves. Every order of magnitude dropped saves you over 90% of memory size (1 character less in the String and 90% less objects total). |
Hi Philip,
Yes it was a memory trade off.
Getting a number from this cache is simply faster than Integer.toString() but main interest was to avoid String allocations.
It is not only used by the field number themselves, but for all the integer figures that are sent in a fix message (they end up by being converted into string, in the quick fix api). (I used this cache on others PR).
At Natixis they were a lot of garbage to save this way (hence reducing number of stop the world young gen gc), because we were sending thousands of messages each seconds.
I choose an arbitrary size of 1000000 because this value was a good trade off regarding the figures used in a trading environment, and memory size. 25mb of string allocated in old gen is peanuts on modern hardware, but indeed 250mb would be too much only for that...
That's why there is two caches, on for number until 1000000, and a second one for some number above, every 1000, ex : 1001000, 1002000, 5000000, etc… A number not in this cache is allocated the same way as before...
Regards,
Charles
Le 7 nov. 2017 à 01:16, Philip a écrit :
… NumbersCache is a bit of a memory/performance trade-off right? This is to do what - convert 9 into "9"?
What's the performance of the cache vs the performance of Integer.toString()?
What's the size of the cache. For the small one it's 2 bytes and 48 bytes for the string. Gauss's trick tells us there's ~500K of those so that's 25MB of data.
1000000 also seems arbitrary and high. The common numbers we see are going to be the fields themselves. Every order of magnitude dropped saves you over 90% of memory size (1 character less in the String and 90% less objects total).
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub, or mute the thread.
|
Hi @charlesbr1 , @philipwhiuk , do you think the big numbers cache makes sense? Reducing the cached numbers to 99999 would probably be sufficient, too. Thanks, |
Hi,
Yes you’re right. You can reduce it. The big numbers made sens on the Natixis FX engine, it was tuned for this context.
From what I remember, one should take care that group tag is using it...
From what I remember too, one simple thing you can take too, is the message checksum and lenght calculator. I may be wrong I think it was doing something like constructing the message two time to perform calculation. It was easy to rewrite it in a more efficient way...
Regards,
Charles.
… Le 15 mars 2018 à 14:49, Christoph John ***@***.***> a écrit :
Hi @charlesbr1 , @philipwhiuk ,
do you think the big numbers cache makes sense?
Having all numbers from 0 to 999999 may make sense since the cache then contains every tag number, seqnum (unless you send really large numbers of messages), checksum and length that is going to be used. However, the values on the FIX messages (e.g. price, qty) are often floating point values so I am not really convinced to use it. Or maybe I am missing something?
Reducing the cached numbers to 99999 would probably be sufficient, too.
Thanks,
Chris.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub, or mute the thread.
|
Hi @charlesbr1 , would it be possible to grant me permission to push to the PR branches of your PRs?
Thanks, |
Hi Chris,
I just checked box ' Allow edits from maintainers.’ on PRs.
Let me know if it is not what you requested.
Regards,
Charles
Learn more
… Le 29 mars 2018 à 23:53, Christoph John ***@***.***> a écrit :
Hi @charlesbr1 <https://github.com/charlesbr1> , would it be possible to grant me permission to push to the PR branches of your PRs?
E.g. on #35 <#35> I needed to make changes to the unit test but had to merge the PR on the command line eventually.
From #40 <#40> I created a new PR from your fork so I could build via Travis CI.
But in both cases the commit looks like I authored the changes. :-/
Thanks,
Chris.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub <#42 (comment)>, or mute the thread <https://github.com/notifications/unsubscribe-auth/AM62PEILPM1UUyMj2KqyJFZS3vTP7avCks5tjVfOgaJpZM4Fj6gn>.
|
Hi @charlesbr1 |
…rlesbr1/quickfixj into charlesbr1-fieldmap-length-and-checksum
- changed NumbersCache to only hold numbers up to 99999 since it should be sufficient for normal use cases - removed NumbersCache.get(double) method since its usage is questionable as it will truncate a double to a long value
Added small wiki page https://github.com/quickfix-j/quickfixj/wiki/JMH-benchmark-for-%2339-and-%2342 |
Avoided some temporary IntField creation to compute length.
In fact, the "isStringEquivalent" branch that I added is useless with previous pull request on Message class, which directly compute length & checksum if possible.
Change some 'for each' list iteration by old loop over index to avoid iterator allocations, as the jvm will not always do it for us.