I'm a CS student and in order to practice my coding skills I'm trying to implement an e-book reader and I want some advice from more experienced programmers. I'm using C++\QML but I'll try to keep my problem non-specific to any technology.

Small preface

Once the book opened I keep it in memory. I also generate an array of pages. Initially I keep in memory:

  • the current page;
  • 3 pages to left;
  • 3 pages to right.

The last two options are needed in order to allow fast scrolling. When the user scrolls one page backward\forward my program calculates a few additional pages in that direction.

I also allow the user to change the window size which affects the page size. And here are problems.

The problem

Every time user changes the window size it changes the page size => the program have to recalculate the state of the currently displayed page (its size and content) and also nearby pages. It takes some time.

So every time user just playing around with the app window my program has hard time in calculations. Those calclulations take some time and slow down the whole app.

What I did in order to solve it

  1. I thought about forbidding user to manually change the window size (and give him a few allowed page sizes) but I'm not sure how user-friendly it is :) In this case I could calculate pages of predefined sizes at the begining so it won't slow down the app as much as it is now.
  2. I thought multi-threading would save me. As a true newbie at first I did everything in one thread. As long as my app started to actually work (slow of course, because my GUI froze sometimes due to calculations), I introduced multi-threading and now my GUI and working thread are separate. It's faster a little bit now but still sometimes I can see how slow it is especially on a small laptop when you scroll pages faster than a turtle.

So, my question is: how appropriate is my approach? Is it sane at all and what are the ways to improve the perfomance?

  • 1
    Often times it is more about hiding/masking rather than increasing task speed. If you were to wait for 10 minutes task to finish there is marginal difference between waiting by frozen UI and one showing the progress. I would suggest delay actual calculation after the window size finished changing (drag-drop, scale/interpolate between preset sizes for intermediate result) and blurring the page along with showing progress when re-calculating. – wondra Feb 7 '18 at 6:57

It's definitely a good idea to separate out the laying out of the pages from the rendering. Putting them on different threads is a good idea as well. I don't think the solution is to do speculative layout at different sizes, though. I think you'll end up doing a lot of unnecessary work. I also don't like the idea of forcing the user into a few set sizes.

What I would do next is profile your application to see what's taking the longest amount of time during page layout. A profiler will tell you which function is taking up the most time in your application. You can then examine that function to determine why it's taking up so much time. Often an operation can be done faster by using a different data layout, a different data structure, or a different algorithm altogether. For example, finding the maximum value in an array requires checking every element once to see if that element is bigger than the current maximum. But if the array is already sorted, it takes only a single read of the last element.

Once you've profiled your code, you can work on making those functions faster, or post more questions here on better ways to approach the problem.

  • Upvote for separating layout and rendering. How the next 3 pages will be arranged shouldn't be determined until the user has established the proper size. However the rendering of the current page should have a dedicated thread. Also I would add that during resize, the rendering thread should be preferring fast algorithms over precise algorithms at least until the user commits to a change. – Neil Feb 7 '18 at 8:31
  • Yes, I don't do any rendering until the size is finally accepted (don't do anything while resizing). Okay, I got the idea! I think my code for rendering is a mess actually (though I tried to keep it as clean as possible). I'll take a look into estimating the load and optimizing my algorithms. Now I think there's a room for improvement that could speed up the things. Thanks for the tips! I'll dig into my code and maybe will ask advice later here or on CodeReview (depending on my future problems). – Neilana Feb 7 '18 at 13:46

I take it that the re-calculation you mention is the text re-flow calculation, as you keep the font size same, but change the page area ?

  1. You need to optimize the page rendering/rasterization logic for speed.
  2. Adjacent pages can be kept in a lower quality/resolution.
  3. Each page can have its own rendering subroutine/task, on a separate worker thread (with a FIFO queue and cancellation support) that can run separate from page switching.
  4. Page switching or resizing simply re-distributes content (start/end) between in memory pages. Actual rendering work is submitted to worker queue (#3).
  5. Pages that go out of scope, cancel any unfinished render task in queue.
  6. Worker thread picks tasks most recently submitted to the FIFO queue. That is: the page just presented to user is rendered first.

Overall effect will be that user can switch or resize as fast he likes to, the content will appear with slight delay, as soon as its render task in worker queue (#3) is done.

  • Thanks for the answer! I'm looking forward optimizing my rendering algorithm. Didn't think about that before but simple example with maximum value in the answer above I realized there might be some problems. I'll follow your advices as well when optimizing my rendering process. – Neilana Feb 7 '18 at 14:07

The content of a page should not change based on the size of the display canvas. You're picking up unnecessary complexity because you're treating book pages as if they were HTML pages. They're not.

Page 47 of "Treasure Island" should be the same content, no matter what the zoom level. Most e-book readers honor the pagination of the original printed book.

Once you eliminate the need to shuffle content, your rendering and page scrolling becomes much simpler. It doesn't matter if you use a percentage zoom option, or a fixed-size option (small, medium, large, etc.), or use the physical size of the window. For each display canvas size, you just need to decide on the appropriate font, fit the text horizontally, and let it extend vertically with a scroll bar.

  • If the solution is simply to display the text "as is" with no re-rendering, then no challenge is offered, which is sort of entirely the point behind doing this project to begin with. While it's important to understand that this may be a feasible "real world" solution to the problem, there is no intrinsic value of this answer outside of the general advice for a student. More would be gained by simply pursuing the challenge in my humble opinion. – Neil Feb 7 '18 at 8:40
  • I see your point, but I tend to take a more pragmatic approach. I don't believe in pedagogy for it's own sake. To practice at making something that is not actually useful is really nothing more than navel-gazing, IMO. – Mark Benningfield Feb 7 '18 at 8:45
  • It's arguable whether or not this is entirely useless. Most e-book readers support both dynamic and static paging. It seems logical to provide both possibilities and let the client decide according to preference, in which case you must implement both. – Neil Feb 7 '18 at 8:51
  • Well, my app is not just in the sake of pedagogy. In the sake of pedagogy I'd been solving puzzles on codingame.com for a while and realized that solving puzzles doesn't get me any close to the real world problems. So I decided to write the program that would be useful for me. That e-book reader I'm asking about is not just reader - I'm simplifying the things. Actually it's the app that would help me to learn foreign languages by building up my vocabulary and allowing me to work with it. Opening, reading and working with books is just one of its main features. – Neilana Feb 7 '18 at 13:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.