8000
We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
There was an error while loading. Please reload this page.
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
We render alot of invoices and we want to add a QRCode so that users can scan the invoice with their phone. Since we render several thousand invoices performance is important. I noticed it took 25ms to render the image when warm. I used the code from readme
QRCodeGenerator qrGenerator = new QRCodeGenerator(); QRCodeData qrCodeData = qrGenerator.CreateQrCode("The text which should be encoded.", QRCodeGenerator.ECCLevel.Q); QRCode qrCode = new QRCode(qrCodeData); Bitmap qrCodeImage = qrCode.GetGraphic(20);
Included in the 25 Ms is saving the bitmap to a memory stream and convert it to a byte array.
We are using full framework 4.7 and the computer i tested on is a AMD 5950x. Latest nuget version
The text was updated successfully, but these errors were encountered:
In general it's hard to say what low or high performance is. Do you have any comparison? (Other libs that are faster? Or what is your code/second expectation?)
Two things which may improve performance:
Sorry, something went wrong.
I clocked only the QRCode part now. It takes 21ms. I lowered pixelres from 20 per module to 10. Down to 19-20ms. I think its slow. A modern computer game takes 5-8ms to render a single scene frame which is way more complex. It should be possible to get better performance. I think the problem is the old GDI+ framework. Its very slow
It looks like the PngByteQRCode doesnt use GDI+ will try. I need it without quiet zone because I render it in a report with its own borders.
PngByteQRCode
I tried the byte version. It takes 13ms to render. So better. But it seems there is no way to disable quiet zone on it.
I missed point 1) (Cache QRCodeGenerator) That shaved of some time. Down to 15ms warm on GDI+ Its still alot of time for a singel image render. But way better
Another idea is using ParallelForeach: https://www.c-sharpcorner.com/UploadFile/efa3cf/parallel-foreach-vs-foreach-loop-in-C-Sharp/ By using it, you could make better use of your multicore processor. If it works with your application at the end, depends on your use case. If you want to generate codes on request, than you can't multithread with the loop, because there's nothing to loop. But if you create multiple QR codes in batches/at the same time, using a ParallelForeach could increase the overall throughput. (And at least for your benchmark, it should show an increased performance.)
That said - feel free to fork QRCoder and send in your performance optimizations via Pull Request, if you see any points that should/could be optimized.
We are already running the report generation task in parallel. It takes longer to generate the QR Code then it takes for the database to request and fetch the data for each invoice :D
Hi @AndersMalmgren ,
If I read your comments correctly, you had the best performance when using the PngByteQRCode, but couldn't use this renderer because you didn't want the whitespace (=quiet zone). Correct?
In the latest CI build (and soon officially when I push version 1.4.2 to NuGet) there is now a new/additional parameter "drawQuietZones" available for the PngByteQRCode. If you set this to "false", the codes will be rendered without quiet zones. With this you could take advantage of the performance benefits of the PngByteQR code.
I'm facing another performance issue but not a time complexity it's a Memory Leak as follow:
I'm using this code to convert a base64 string to a QR in the form of byte[] so I can display it in a Microsoft LocalReport.
string
byte[]
LocalReport
/// <summary> /// Converts the given invoice information into a (tag/type length value) TLV representation then convert it into a <see cref="Bitmap"/> QR code in the form of <see cref="byte"/>[]. /// </summary> /// <param name="sellerName">The name of the seller.</param> /// <param name="vatRegNum">The VAT registration number.</param> /// <param name="timestamp">The timestamp in which the transaction was created.</param> /// <param name="totalWithVAT">The transaction total value with VAT.</param> /// <param name="vatTotal">The total VAT value of the transaction.</param> /// <returns>A <see cref="byte"/>[] for the <see cref="Bitmap"/> QR code.</returns> public static byte[] ToBitmapBytesQRCode(string sellerName, string vatRegNum, string timestamp, string totalWithVAT, string vatTotal) { var tlv = ToTLV(sellerName, vatRegNum, timestamp, totalWithVAT, vatTotal); byte[] qrCodeAsBitmapByteArr; using (var qrGenerator = new QRCodeGenerator()) { // 2mb added to memory and never got released here. using (var qrCodeData = qrGenerator.CreateQrCode(tlv, QRCodeGenerator.ECCLevel.Q)) { using (var qrCode = new BitmapByteQRCode(qrCodeData)) { // 19mb added to memory and never got released here. qrCodeAsBitmapByteArr = qrCode.GetGraphic(20); } } } return qrCodeAsBitmapByteArr; }
Each call to this methods puts about 21mb to the memory and never got released even with the using that should dispose any resources related by the created QR instances.
using
Am I abusing something in the library or it is an issue with it?
@FawzyMokhtar
You are sure its the QRCode? LocalReport will leak memory if you dont call
lr.ReleaseSandboxAppDomain();
I remember we had to work alot to get LocalReport to play nice,
Actually I managed to reduce the amount of memory used by forcing the application to run on x64 bit platform instead of 32 bit, things started to work correctly and some memory (not all of course) are released.
I went through the code - while debugging - line by line and monitoring the Resource Monitor, after that it is obvious it's caused by QRCode.
QRCode
BTW, the LocalReport.render() in my case is getting called after the QR is successfully generated and not before that.
LocalReport.render()
It's good to say that using the PngByteQRCode instead of the BitmapByteQRCode reduced the amount of memory used - in that step - from 19mb to actually NOTHING which is WooW.
BitmapByteQRCode
I think the problem maybe with the BitmapByteQRCode itself.
No branches or pull requests