Skip to content
This repository has been archived by the owner on Apr 9, 2024. It is now read-only.

SevenZipCompressor Compressing callback returning significantly wrong progress #67

Open
Mgamerz opened this issue Oct 13, 2019 · 8 comments · May be fixed by #78
Open

SevenZipCompressor Compressing callback returning significantly wrong progress #67

Mgamerz opened this issue Oct 13, 2019 · 8 comments · May be fixed by #78
Labels
bug Something isn't working

Comments

@Mgamerz
Copy link

Mgamerz commented Oct 13, 2019

I am not sure if this is an issue with sevenzipsharp or the 7z.dll (I am using one from 7z 19.00), but when I subscribe to the Compressing event, when I inspect the argument's PercentDone value, it seems to be wildly off. It will go from 0-100 very quickly (for a 2GB source directory I am compressing), in which I believe it is filling buffers. After this reaches 100%, I get no more progress notifications until the archive job is complete - which can take several minutes.

When I use 7zip gui to compress this archive, I see correct progress, so I am wondering if maybe the compression callback is binded to the wrong interface to the dll? It shows bytes written going all the way up to the 2GB of data, but it seems more like that's what's read and not what's actually been processed, as my process sits at 14GB of memory for almost 3 minutes until the archive is done being generated.

My code to generate an archive:

var compressor = new SevenZip.SevenZipCompressor();
compressor.CompressionLevel = CompressionLevel.Ultra;
//compressor.CustomParameters.Add("s", "on"); //can't figure out how to make it do solid archives
compressor.Compressing += (a, b) =>
{
    Debug.WriteLine(b.PercentDone);
    mainWindow.UpdateBusyProgressBarCallback(new ProgressBarUpdate(ProgressBarUpdate.UpdateTypes.SET_VALUE, (int)b.PercentDone));
};
compressor.FileCompressionStarted += (a, b) => { Debug.WriteLine(b.FileName); };
compressor.CompressFileDictionary(archiveMapping, archivePath);
compressor.CompressionMode = CompressionMode.Append;
compressor.CompressionLevel = CompressionLevel.None;
compressor.CompressFiles(archivePath, new string[]
{
    Path.Combine(ModBeingDeployed.ModPath, "moddesc.ini")
});
Utilities.HighlightInExplorer(archivePath);

After doing some investigation, it seems the process for archive compression works like this;

  1. Read source files into memory (this is what the Compressing % callbacks show)
  2. 7z.dll does it's thing with the file for significant amount of time
  3. 7z.dll/SevenzipWrapper write the new memory-archive to disk. I can see bytesWritten being raised but it is not being passed back to the sevenzipcompressor it seems (or maybe I missed something).

It is step 2 that would be most useful. I am looking into seeing how it is done in 7z UI, maybe it is exposed via some sort of interface.

@squid-box squid-box added the bug Something isn't working label Oct 13, 2019
@Mgamerz
Copy link
Author

Mgamerz commented Oct 13, 2019

After investigating the source code, it looks like we might want to look at SetCompleted from IArchiveUpdateCallback. I have it printing out and I am getting constant byte updates from here - I imagine this is amount of archive generated at that point.

I am also getting some progress when it's outputting to disk too from that call - perhaps this is the overall archive percentage. I'm not sure what the values mean (they seem to not be specifically bytes).

image

This is in COM.cs. I will continue to investigate.

Edit: It seems SetCompleted is called during all 3 steps I listed above, but it is different values than the BytesWritten (which is what the compressing callback is looking at). I'm not sure what it is, but I am going to test seeing what the SetTotal() and SetCompleted() methods combined show me. Maybe 7z is precalculating the amount of operations or something it has to do (like reading source files in chunks, compression passes, and disk writes in chunks) and that is how it shows the progressbar.

@Mgamerz
Copy link
Author

Mgamerz commented Oct 13, 2019

Sorry for the barrage of comments and emails. It is indeed SetTotal and SetCompleted. I have extended my implementation of SevenZipSharp to have a OnProgressing() callback, which uses the SetTotal (sets a _total variable in the ArchiveUpdateCallback object). When SetCompleted is called, it raises this event. I can submit some code - I am not fully sure of the proxy styling + disabling fast compression without events. I added a DetailedProgressEventArgs that returns the Total and the Amount Completed (both ulong). Having progress as a byte between 0 and 100 is not as useful as having a large value I can work with, especially when it can take several seconds between a full jump in percentage.

I will prepare some code for a PR - I expect it will take a fair amount of work to massage it into the code style for this repository. I made it a new event instead of Compressing() as I did not want to break backwards compatibility, but I am sure there is a better way to do it.

@Mgamerz
Copy link
Author

Mgamerz commented Oct 23, 2019

Haven't forgotten about this. I am still building my app and want to test it there first before I put in a PR.

@VisualUser
Copy link

Hi, do you think this could be related to this:
#77

@Mgamerz
Copy link
Author

Mgamerz commented Nov 30, 2019

Could be. I'm still planning on making PR to this repo with this code. Essentially, if you want accurate progress, you need to setup a OnProgressing() handler, as it's the actual progress values. the progress events are already part of the library but they don't seem to be used. (SetCompleted() and SetTotal() in the archiveupdatecallback and... archivecompressingcallback? files)

Not sure what this library is hooked up to, it's like... running at full capacity of buffers or something (like when 7z is using max memory it will use during an operation). I'll see if I can make PR this weekend to this repo for this feature.

If you look at how 7z behaves when you compress a large archive, you can see it goes through a lot of files quickly and then just says "compressing X" for a long time. This library seems to be hooked up to that logic rather than what powers the progress bar.

@VisualUser
Copy link

Ok, thanks for the information. I will try using the OnProgressing handler.

@Mgamerz
Copy link
Author

Mgamerz commented Nov 30, 2019 via email

@Mgamerz Mgamerz linked a pull request Nov 30, 2019 that will close this issue
@Lukiluc29
Copy link

@Mgamerz @VisualUser Hello, do you have any news on this problem?

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants