サポート掲示板
HOME  □ MANUAL  □ 新着記事  □ 新規投稿
ツリー表示  □ 記事全文表示  □ SEARCH  □ 過去ログ
ツリー表示

MESSAGE 圧縮に必要なグローバルメモリのサイズ(空き)について /tetsuo (14/03/18(Tue) 19:57) [1166]
....MESSAGE Re[1]: 圧縮に必要なグローバルメモリのサイズ(空き)について /Akky (14/03/19(Wed) 19:01) [1168]
........MESSAGE Re[2]: 圧縮に必要なグローバルメモリのサイズ(空き)について /tetsuo (14/03/20(Thu) 09:01) [1170]
............MESSAGE Re[3]: 圧縮に必要なグローバルメモリのサイズ(空き)について /Akky (14/03/20(Thu) 18:46) [1171]
................MESSAGE Re[4]: 圧縮に必要なグローバルメモリのサイズ(空き)について /tetsuo (14/03/21(Fri) 18:47) [1172] 解決済み!
....MESSAGE Re[1]: 圧縮に必要なグローバルメモリのサイズ(空き)について /tetsuo (14/03/19(Wed) 18:12) [1167]
........MESSAGE Re[2]: 圧縮に必要なグローバルメモリのサイズ(空き)について /Akky (14/03/19(Wed) 19:05) [1169]


親記事 / ▼[ 1168 ] ▼[ 1167 ]
NO.1166  圧縮に必要なグローバルメモリのサイズ(空き)について
□投稿者/ tetsuo -(2014/03/18(Tue) 19:57:42)
□U R L/
【ソフト名】
 7-zip32.dll

【バージョン】
 9.20.00.02

【使用OS】
 Windows7 Professional Sp1 32bit

【PC機種】
HP p6740jp

【質問内容】

  お世話になります。
  いつも大変便利に活用させていただいております。

  現在、Visual Basic 2010で開発を行なっておりまして、ファイル(*.sdf)にパスワード付きで圧縮を掛けるようにしています。
  ところが、環境によってSevenZip関数から32798(ERROR_ENOUGH_MEMORY)が返ってくるようになりました。
  その際の、第3引数(Output)の中身は以下のようになっています。

  --- OutPut -------------------------------------------------------

  7-Zip (A) 9.20 Copyright (c) 1999-2010 Igor Pavlov 2010-11-18
  Scanning

  Creating archive 1234.7z



  ERROR: Can't allocate required memory!

  --------------------------------------------------------------------

  調査してみたところ、物理メモリの空きが少ない場合で、かつ圧縮しようとしているファイル(*.sdf)のサイズがある一定以上の大きさの場合にこの
  現象が発生するようです。

  ・ERROR_ENOUGH_MEMORYが発生した段階で、繰り返しSevenZip関数をコールしても、ERROR_ENOUGH_MEMORYが発生する。
  ・ERROR_ENOUGH_MEMORYが発生した段階で、圧縮対象のsdfファイルをサイズの小さな同名のsdfファイルに差し替えた場合、改善する場合がある。
  ・ERROR_ENOUGH_MEMORYが発生した段階で、常駐ソフトを終了する等の方法で物理メモリの空きを増やすことで改善する場合がある。

  上記のような結果から、圧縮対象のファイルサイズに応じて、アーカイバのエンジンが確保するグローバルメモリのサイズが変わるものと勝手に
  解釈しておりますが、例えば圧縮する前にエンジン側で要求されるグローバルメモリのサイズを取得する(もしくは計算する)ことは可能なので
  しょうか?

  もしくは、比較的大きなサイズのファイルを圧縮する場合、できるだけエンジン側で要求されるグローバルメモリのサイズを抑える為の圧縮方法は
  ありませんでしょうか?

  7-zipAPI.txt、7-zipCMD.txt等は拝見させていただきましたが、無知なものでご教示いただければ大変助かります。
  お手数をお掛け致しますが、よろしくお願い致します。


  (※ご参考になるかわかりませんが、ソースコードを掲載致します)

  --- ソースコード ---------------------------------------------------------------------------------------------------------------------

Delegate Function TSetUnicodeMode(ByVal bUnicode As Boolean) As Boolean
Delegate Function TExecute(ByVal hwnd As IntPtr, ByVal cmdLine As Byte(), ByVal pOutput As IntPtr, ByVal dwsize As Integer) As Integer

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim hModule As IntPtr = LoadLibrary("7-zip32.dll")
Try
Dim hSetUnicodeMode As IntPtr = GetProcAddress(hModule, "SevenZipSetUnicodeMode")
Dim fnSetUnicodeMode As [Delegate] = Marshal.GetDelegateForFunctionPointer(hSetUnicodeMode, GetType(TSetUnicodeMode))
fnSetUnicodeMode.DynamicInvoke(True)

Const FNAME_MAX32 As Integer = 512
Dim pBuffer As IntPtr = Marshal.AllocHGlobal(FNAME_MAX32 + 1)
Try
Dim szCmdLine As String = "a -t7z ""1234.7z"" -pABCDEFG ""5678.sdf"""
Dim hExecute As IntPtr = GetProcAddress(hModule, "SevenZip")
Dim fnExecute As [Delegate] = Marshal.GetDelegateForFunctionPointer(hExecute, GetType(TExecute))

If (0 <> fnExecute.DynamicInvoke(Me.Handle, System.Text.Encoding.UTF8.GetBytes(szCmdLine), pBuffer, FNAME_MAX32 + 1)) Then
MsgBox(Marshal.PtrToStringUni(pBuffer))
End If
Finally
Marshal.FreeHGlobal(pBuffer)
End Try
Finally
FreeLibrary(hModule)
End Try
End Sub

  ------------------------------------------------------------------------------------------------------------------------------------------



▲[ 1166 ] / ▼[ 1170 ]
NO.1168  Re[1]: 圧縮に必要なグローバルメモリのサイズ(空き)について
□投稿者/ Akky -(2014/03/19(Wed) 19:01:30)
□U R L/
私もよく分かりませんが7-zipCMD.txtの「-m : 圧縮方式の設定」に
各圧縮方法での必要メモリの計算方法が書かれていますのでそれを参考に計算して下さい。
一番簡単にメモリが少なくて済む方法は圧縮レベルを-mx1にしとけば良いかと。
この場合辞書サイズが64KBでマッチファインダーがHC4だから
64+7.5*64+4096=4640KBになるかと思います。

但し、これ以外にもメモリは使われるのでこれだけ有れば大丈夫というものではありませんのでご注意を。

# 今気が付きましたがマッチファインダーの表の辞書の所で
# 64MB...48MB ってなってる所は 64KB...48MBの誤りですね。



▲[ 1168 ] / ▼[ 1171 ]
NO.1170  Re[2]: 圧縮に必要なグローバルメモリのサイズ(空き)について
□投稿者/ tetsuo -(2014/03/20(Thu) 09:01:31)
□U R L/
> 私もよく分かりませんが7-zipCMD.txtの「-m : 圧縮方式の設定」に
> 各圧縮方法での必要メモリの計算方法が書かれていますのでそれを参考に計算して下さい。
> 一番簡単にメモリが少なくて済む方法は圧縮レベルを-mx1にしとけば良いかと。
> この場合辞書サイズが64KBでマッチファインダーがHC4だから
> 64+7.5*64+4096=4640KBになるかと思います。
>
> 但し、これ以外にもメモリは使われるのでこれだけ有れば大丈夫というものではありませんのでご注意を。
>
> # 今気が付きましたがマッチファインダーの表の辞書の所で
> # 64MB...48MB ってなってる所は 64KB...48MBの誤りですね。

表の見かたが分からなかったので、大変参考になりました。
ありがとうございます。


> 7z形式のデフォルトはLZMAです。
> Deflateが標準なのはzipです。

テキストをよく拝見させていただいていたつもりでしたが、見かたを間違っておりました。
申し訳ありませんでした。

今回のようにパラメータを指定しない場合、ご教示いただいたとおりに表を参考に計算すると、
標準の辞書サイズ16MB(2^24byte)と標準のマッチファインダーがbt4だと思いますので、

16+11.5*16+4=204MB

ということですね。

今回圧縮しようとして失敗するファイルのサイズが180MB程度なのですが、物理メモリの空き容量
が600MB程度あるにも係わらずERROR_ENOUGH_MEMORYで失敗してしまうのは、計算で算出される
領域以外で要求されるメモリが存在するということなのでしょうか?
状況(ファイルサイズが小さい場合はエラーが発生しない場合がある)からファイルサイズに因果
関係があるように思えるのですが、本家7-zip様の問題になるのでしょうか?








▲[ 1170 ] / ▼[ 1172 ]
NO.1171  Re[3]: 圧縮に必要なグローバルメモリのサイズ(空き)について
□投稿者/ Akky -(2014/03/20(Thu) 18:46:11)
□U R L/
ファイルを開くのもメモリ使いますから他にもメモリが必要なのは当然になりますね。
7-zipの仕様がどうなのかは分かりませんが、もしファイル全てを
一気に読み込んでた場合は更にファイルサイズ分のメモリが必要になります。
# 流石にそんな仕様にはなってないとは思いますが。
# その辺り本家7-zipのヘルプに書いてあるかもしれませんが知らないです。



▲[ 1171 ] / 返信無し
NO.1172  Re[4]: 圧縮に必要なグローバルメモリのサイズ(空き)について
□投稿者/ tetsuo -(2014/03/21(Fri) 18:47:06)
□U R L/
解決済み!
> ファイルを開くのもメモリ使いますから他にもメモリが必要なのは当然になりますね。
> 7-zipの仕様がどうなのかは分かりませんが、もしファイル全てを
> 一気に読み込んでた場合は更にファイルサイズ分のメモリが必要になります。
> # 流石にそんな仕様にはなってないとは思いますが。
> # その辺り本家7-zipのヘルプに書いてあるかもしれませんが知らないです。

お返事が遅くなりました。
申し訳ありませんでした。m(_ _)m

私も巨大なサイズのファイルをメモリ上に全て読み込むようなことはされていないと思うのですが・・・
正直、そのあたりが知りたかったのですが、本家の7-zipの仕様の問題なのか判断がつかなかったため、
ご質問させていただきました。

一度、本家のヘルプ等で勉強してみたいと思います。
この度は大変お手数をお掛けしました。

今回のご質問はひとまず解決済みとさせていただきます。
ありがとうございました。



▲[ 1166 ] / ▼[ 1169 ]
NO.1167  Re[1]: 圧縮に必要なグローバルメモリのサイズ(空き)について
□投稿者/ tetsuo -(2014/03/19(Wed) 18:12:28)
□U R L/
追加です。

前回のソースコードで、以下のようにコマンドライン文字列を変更(MethodIDを明示的に"Deflate"に設定)したところ、ERROR_ENOUGH_MEMORYのエラーは発生しなくなりました。

Dim szCmdLine As String = "a -t7z ""1234.7z"" -pABCDEFG -m0=Deflate ""5678.sdf"""

しかしながら、"7-zipCMD.txt"の中で、"MethodID"の標準値は"Deflate"となっております。
MethodIDを明示的に"Deflate"に設定した場合と、MethodIDを何も指定しない場合では、内部動作が異なるのでしょうか?

ちなみにLZMA等のアルゴリズムの場合は、辞書サイズを小さくするとERROR_ENOUGH_MEMORYが出なくなったりするようなのですが・・・



▲[ 1167 ] / 返信無し
NO.1169  Re[2]: 圧縮に必要なグローバルメモリのサイズ(空き)について
□投稿者/ Akky -(2014/03/19(Wed) 19:05:35)
□U R L/
7z形式のデフォルトはLZMAです。
Deflateが標準なのはzipです。



- Child Tree -