home.social

#unpaper — Public Fediverse posts

Live and recent posts from across the Fediverse tagged #unpaper, aggregated by home.social.

  1. Okay a little bit of #unpaper ghosts for tonight.

    I'm nearly at the end of completing the work @federicomena started: moving all the options into an Options structure instead of using a bunch of separate globals (which I already turned into locals to main() at least.)

    This would unblock, among others, the option of processing each input file in parallel instead of doing them one by one.

    I was hoping to hide some of those locals by defining them in a block within the parser… but tests fail.

  2. one last note for the day from my #unpaper refactoring work: what is even the point of doing bitwise operations in C to try to contain up to four edges (left, top, right, bottom) into an `int` variable?

    `struct Edges { bool left; bool top; bool right; bool bottom; }` is literally the same size, the difference being instead of keeping the data in the lower four bits, it puts it one byte per edge!

  3. Yesterday's maintenance work on #unpaper is something that to me clearly shows the point I was making about the opportunities arising in treating *specific* #LLMs as Computer-Aided Software Engineering (CASE) tools, so I thought I would post a quick thread here, since I don't think I'll manage to post it on the blog any time soon.

    Full disclosure before I start: I work for Meta, which clearly has been betting a lot on AI — but this is my personal point of view, and I don't work on AI projects.

  4. Only a minor #unpaper task today because I'm still recovering from a very annoying flu, but I decided to re-do the parsing of physical dimensions so that it stops being quite random depending on the order of passing -dpi (which is the wrong name anyway) and the sizes themselves.

  5. Okay I guess by this point I need to put numbers together and make a blog post — on a different system (native rather than WSL), a clang -O2 build running the same #unpaper pipeline takes 6.1s.

    The same revision but built "ricer" (-O3 -march=native -ftree-vectorize) takes 3.5s! But the text size of the binary is quite increased: 75KB vs 91KB.

    Unfortunately codiff (at least the OpenSUSE version) doesn't like those DWARVES :(

  6. Okay either there is something wrong in the code, or wow does GCC not keep up.

    (Editing for clarity)

    Of the two #unpaper binaries, one built with clang, the other with gcc, both with -O2 and LTO, the first take 16s to run, the latter 33s!

    Maybe it's the LTO that makes a difference? If that is the case it's well possible that I could see a significant performance regression with the refactoring, with GCC — the code is now split across multiple units rather than in a single one.

  7. Talk about the non-obviousness of optimizations! I thought that, since most of the time in #unpaper was spent on the set/get pixel, and these both had huge switch/case blocks, getting rid of those in favour of using function pointers could have helped.

    Nope! Regressed by over two seconds on a six seconds run. That's *quite worse.* I guess I'll keep optimizing for readability and trust the compiler.

  8. Okay #unpaper poll time: I'm going to definitely change the way it configures masks: there's both auto-masking and user-inserted masks. Right now it allocates 100 items for each of those, with a running count. The order *shouldn't* matter, they are only added to during option parsing and iterated over a few times.

    I'm going to change these with a structure that holds a count as well as the actual masks, either with a flexible array or with a linked list.

    Which one do you think make more sense?

  9. Okay more minor analysis of where #unpaper 7.1 is heading: the size of the ELF file shows that there is more *code* (>25KiB) but there's a *lot less* bss (108 bytes vs 10992 before)

    That's because all of the global variables are now on the stack, I bet. The stack for `main()` is probably annoyingly high because there's still the whole set of (multiple) 100-rectangles array.

    One rectangle is supposedly 16 bytes, so that's probably accounting for most of those 10KiB less bss.

  10. Annoying I'm still not feeling great, so I'm now going to sleep it off a bit more. #unpaper 7.1 is getting closer, all of the global variables are gone, but now I'm paring down the number of arguments passed around by keeping the image-related state together.

    What am I looking for next? Well, it would be nice if I could just point people at a COPR repository or a PPA to get the binary. Is anyone willing to help with that?

    (I also keep getting requests for Windows builds, I have no clue on that

  11. Me: "I'm sure that the refactored #unpaper that has more semantically meaningful APIs rather than doing raw calculations is slower, I want to see how much."

    hyperfine: "Your CLANG / -O2 / LTO version is 2 seconds faster after the refactor than before."

    \meme{shocked_pikachu}

  12. Okay, I'm honestly not feeling well, but #unpaper 7.1 is around the corner if I get to finish this.

    My current problem is that before and after refactoring there's a 5 pixel difference in the calculated border. Unfortunately, I have rewritten a chunk of logic for the new interface, but I couldn't see an obvious reason why it differs? Time to gdb around a bit more.

  13. So the current stretch of #unpaper refactoring is actually quite annoying, because the whole masks/border detection (which is probably the most important part of the tool!) is all connected to each other.

    But it's also the last processing bit that relies on global state variables. After I'm done with that, I should be able to remove all of the remaining globals, and that means I can modularise the options handling too.

  14. More #unpaper refactoring gems.

    One piece of the code used xRatio and yRatio for the proportions to scale an image. Another piece not even 100 lines later used wRat and hRat.

    Of course hRat is not the *horizontal* ratio, it's the *height* ratio. I'm just using horizontal_ratio and vertical_ratio in the refactored code.

  15. #unpaper refactoring work

    previously:

    flood_fill(image, (Point){p.x, p.y - 1}, color, mask_min, mask_max, intensity, abs_black_threshold);

    now:

    flood_fill(image, shift_point(p, DELTA_UPWARD), color, mask_min, mask_max, intensity, abs_black_threshold);

    (it happens enough that the constants are a significant improvement.)

  16. My very much not scientific or reasonably repeatable benchmark of running the testsuites in series shows that #unpaper built with clang -O2+LTO is ~10% faster than the equivalent gcc -O2+LTO.

    gcc -O0: 351.37s
    gcc -O2+LTO: 267.46s
    clang -O2+LTO: 232.23s

    I have not looked at optimizations at all yet, for now I'm still refactoring for maintainability.

  17. I swear making stacks of commits like this and getting them all ready is *so* much easier with #Sapling.

    Edit: forgot the link github.com/unpaper/unpaper/com

    #unpaper

  18. Okay for my #unpaper refactoring I need to definitely come up with a reproducible benchmark.

    Just running this on my laptop, it seems like the full testsuite is regressing for over two minutes (running the tests with -O0 though, because I'm tracking a logic mistake and I needed a full debugger, but still.)

  19. Okay more #unpaper refactoring concerns. The functions are all over the place both in terms of maintaining state and accessing global parameters. Plus structure sizes are fixed with arrays, because of course this is basic C.

  20. Okay this is turning… absurd.

    I'm trying to get some of the #unpaper code in a state where I can refactor it more effectively, one of the thing I just tried doing was adding `const` specifiers to arrays that are not meant to be modified.

    The size of one of the functions increases by 34 bytes which felt… wrong.

  21. @artfulsodger @[email protected]
    Don't know how it compares with this, but I have been using Open Note Scanner (github.com/allgood/OpenNoteSca). It is so good I don't need to clean my scans anymore.