Open beru opened 3 years ago
報告されていないCMemoryの不具合と考えられます。
エディタに文字を表示するためのメモリ(上限は2GB、スレッドヒープに存在) 上限2GBは「1行あたり」の制約なので可能。 👇 コピーの前準備としてメモリにコピー(上限は2GB、スレッドヒープに新たに確保) intでは3.81GBを表現できないので1メモリに詰め込もうとすると失敗します。
対策には以下3つが必要と思います。
CNativeW : public CNative : protected CMemory という形の継承階層ですが、特に CNativeW は各所で使われているので影響範囲がとても広くて対処が難しいですね。例えば各行の実データの CDocLine::m_cLine
とかでです。
1行の上限が2GBという制約は問題ないと思います。ただ64bitビルドでは4GBより大きいサイズのデータを各所で扱えるようにはしたいですね。
CMemory
で size_t
型を使うと64bitビルドでインスタンスのサイズが増加してしまうのは嫌だなって思います。ただ大きなサイズのメモリを扱うために別の型を追加するのもちょっとどうなのか判断が付きかねます。。
CNativeW : public CNative : protected CMemory という形の継承階層ですが、特に CNativeW は各所で使われているので影響範囲がとても広くて対処が難しいですね。例えば各行の実データの
CDocLine::m_cLine
とかでです。1行の上限が2GBという制約は問題ないと思います。ただ64bitビルドでは4GBより大きいサイズのデータを各所で扱えるようにはしたいですね。
CMemory
でsize_t
型を使うと64bitビルドでインスタンスのサイズが増加してしまうのは嫌だなって思います。ただ大きなサイズのメモリを扱うために別の型を追加するのもちょっとどうなのか判断が付きかねます。。
issueを解決する方向としては、 一時バッファの確保方法を変更して 2GB超 を確保できるようにするのと GlobalAlloc に 2GB超 のデータを渡せるようにする感じかな、と思っています。
CMemoryのインスタンスサイズを拡張してはならないとすると、 内部データを int から size_t に変えられないので、ややめんどうです。
C Run-Time の _HEAP_MAXREQ は 32bit でも INT_MAX より大きいので、 内部データを unsigned化 する作業はやったほうが良さそうです。
int 32bit版でも64bit版でも31bit利用可能。 uint32_t 32bit版でも64bit版でも32bit利用可能。
その前に CMemory::AllocBuffer
の実装がなんかクサいのをなんとかしたいです。。。
CMemoryのインスタンスサイズを拡張してはならないとすると、 内部データを int から size_t に変えられないので、ややめんどうです。
いや、拡張しても良いと思います。自分がCMemoryのインスタンスサイズを増やしたくない理由は
ですが、仮に CMemory
のメンバー m_nRawLen
, m_nDataBufSize
の型を int から size_t に変更しても sizeof(CMemory)
は 8 しか増加しないので、64bitビルド時に 100万行でやっと 8MB の違いです。そのぐらいなら良いんじゃないかとも思えてきます。
C Run-Time の _HEAP_MAXREQ は 32bit でも INT_MAX より大きいので、 内部データを unsigned化 する作業はやったほうが良さそうです。
int 32bit版でも64bit版でも31bit利用可能。 uint32_t 32bit版でも64bit版でも32bit利用可能。
uint32_t にすれば少し制限が緩和されますね。ただし警告が増えそうです。
その前に
CMemory::AllocBuffer
の実装がなんかクサいのをなんとかしたいです。。。
独自の CMemory
を使わずに std::vector<char>
で良いんじゃないかと昔思ったりしましたが、CMemory
は色々な箇所で使われているので書き換える手間に見合ったメリットが無さそうです。
冷静にコードを眺めると、1行に保持できる「データ量」の上限が2GBでした。
データ量=2GB(2ギガバイト) 文字数(1文字あたり2bytes)=1G文字
そうですね。1行分の最大文字数は 30bit (1024 1024 1024) が正しいですね。訂正が面倒でしていませんでした。 この1行の制限自体は仕様で良いんじゃないかと思いますが、
まぁ言うは易し(Talk Is Cheap)で実現するのは大変そうです。。
この件「64bit版で2GBより大きいサイズのテキストのコピペをする事が出来ない」について、 あるべき結論の認識が変わったので書いておきます。
仕様です。
64bit版でも 2GB より大きいサイズのテキストを扱うことはできません。
扱えるテキストの最大サイズは、UTF16換算で 2G - 1
文字 までです。
32bit版では、UTF16換算のテキストサイズが 2G - 1
文字 に収まる場合でも、2GBを超えるファイルは開けません。
64bit版では、UTF16換算のテキストサイズが 2G - 1
文字 に収まる場合に限り、2GBを超えるファイルを開くことができます。
bits | 文字数上限 | ファイルサイズ上限の目安(UTF16) | ファイルサイズ上限の目安(UTF32) |
---|---|---|---|
32bit版 | 2,147,483,646 | 4,294,967,294 | 4,294,967,294 |
64bit版 | 2,147,483,646 | 4,294,967,294 | 8,589,934,588 |
64bit版で読み込めるファイルサイズの上限が減ってしまうような変更は行わない方が良いと思いますよ。
64bit版で読み込めるファイルサイズの上限が減ってしまうような変更は行わない方が良いと思いますよ。
たぶん誤解だと思いますが、新たな制限を作る話ではなく、仕様的な限界を明示しよう、って話です。
状況まとめ GitHub移行以前 メモリ上限は2GB、扱える文字数の上限は1G文字、32bit版では2GBを超えるファイルは開かない。 CMemory変更後 メモリ上限は4GB、扱える文字数の上限は2G文字、32bit版では2GBを超えるファイルは開かない。
ファイルサイズを制限する意味はないですね。 2GB上限を超えた場合に使う変な名前の関数も撤廃したいっすね(闇
一度に編集できる文字数に上限を定める「べき」の論拠は、 Text Services Frameworkが2G文字を超えるテキストの編集に対応していないからです。 https://docs.microsoft.com/ja-jp/windows/win32/api/textstor/nf-textstor-itextstoreacp-gettext
拡張形式として、2G上限を突破する手段があってもよいとは思います。 上限を超える方法を用意するかどうかは別にして、上限は設けるべきだと思います。
https://github.com/sakura-editor/sakura/issues/1575#issuecomment-835138576 に書かれた「仕様」というのは、このぐらいまでのサイズのデータなら各処理で問題なく扱うことが出来るサイズなのかもしれません。しかし実際には場所毎に扱う事が出来るサイズというのは異なるので、もっと大きいサイズのファイルも構成によっては読み込んで表示する事が出来ると思います。
自分が「仕様」を策定する事に否定的なのは、もともと仕様を細かく文書化して設計や実装が行われたソフトウェアではないのに、現状の実装上の制限から後付けで最大公約数的な「仕様」を謳う事です。適切に実装がされていれば解決出来るはずの問題を、問題の定義をすり替えて無かった事にしようとしているように見えます。
現状の実装の問題点とまっとうな対策案は berryzplusさん自身が書いたコメント https://github.com/sakura-editor/sakura/issues/1575#issuecomment-793831350 にまとめられていると思います。どうしてそこから後退してしまったのか分かりません。問題の解決を急いでいるのでしょうか?
#1575 (comment) に書かれた「仕様」というのは、このぐらいまでのサイズのデータなら各処理で問題なく扱うことが出来るサイズなのかもしれません。しかし実際には場所毎に扱う事が出来るサイズというのは異なるので、もっと大きいサイズのファイルも構成によっては読み込んで表示する事が出来ると思います。
具体的な値を示してあるために、分かりづらかったかも知れません。 記載しているファイルサイズは目安です。
ドキュメント全体の上限文字数を定めたら、 快適に編集できる環境を提供できるんじゃないか? と言う提案のつもりです。
現状は1.38GBを開けると言っても使用に耐えない重さです。 「開ける」なら、快適に編集できたほうがいいと思います。
現状の実装の問題点とまっとうな対策案は berryzplusさん自身が書いたコメント #1575 (comment) にまとめられていると思います。どうしてそこから後退してしまったのか分かりません。問題の解決を急いでいるのでしょうか?
ぼくも当初は、サイズ値を64bit化するのが「まっとう」だと思っていました。
しかし、CNativeWのサイズ値を64bit化する対応では、4GB超のメモリが必要なときに、メモリをスレッドヒープから確保することになってしまうので、パフォーマンスに激しい悪影響が出そうだ、ということに気付きました。
で、ドキュメントデータの確保先がヒープでなくても構わない手法として、以前から導入検討していたtsfのCOMインターフェースのシグニチャを確認したところ、tsfが64bit対応してないことに気付きました。
それはそれとして、元々の事象(=無応答になる)はバグとして対処するのが良いと思います。 編集上限文字に制限をかけたからと言って、無応答をなかったことにはできないですし。
しばらく考えてみました。
content-type
が text/plain
でも2GBを超えたらもうテキストじゃない気がします。
対応は、それを踏まえて行いたいです。
こないだ2chの書き込みでこんなやりとりを見ました。
具体的にはどのくらいのファイルサイズ?
10GBくらい
・・・。
個人的には、500MBを超えたらログファイルじゃないような気がします。 何故かというと「メモ帳(=notepad.exe)」で開ける上限が500MBだからです。 「ログファイルじゃない」というより、「ログファイルとして使い物にならない」ってことですが。
ログファイルは、運用環境のシステムイベントを記録しておき、トラブルの対策に役立てるためのものです。 運用環境にインストールするプログラムは、ほとんどの場合「システムに必要なもの」に限られます。 ログファイルを見るためのプログラムが「システムに必要」と言えるかは微妙だと思います。 運用保守に余計なプログラムを要さないことは、一般的なシステムの非機能要件だと考えるからです。
10GBを超えるようなログファイルは、おそらくデバッグトレースの垂れ流しを記録した場合とかにできると思います。
たぶん、システム屋がやるべきことは、 10GBを超えるような自称「ログファイル」を吐くクソシステムに、 「それはシステムじゃねぇよ」とNOを叩きつけることだと思うんです。
Apacheを何も工夫せずにエラーログやアクセスログを全て保存する設定にして そこそこアクセスされるWebサービスを運営していれば数年放置していれば10GBクラスにはなりそうですが・・・。
たぶん、システム屋がやるべきことは、 10GBを超えるような自称「ログファイル」を吐くクソシステムに、 「それはシステムじゃねぇよ」とNOを叩きつけることだと思うんです。
上記のようなシステムはクソシステムだと思いますが 10GBクラスのファイルを難なく開くことが出来るようになったら、 もの凄いと思いますし、強いテキストエディタだと思います。
Visual studio 2022(次期バージョン)のプレビューが始まっています。 https://visualstudio.microsoft.com/ja/vs/preview/vs2022/
vs2022の最大の「売り」はIDEプロセスの64bit化らしいです。
従来頑なに 32bit 版プロセスで構成していたものを、 次回から突然64bit版プロセスに一本化するらしいです。
失敗が約束されてる雰囲気をビシビシ感じるわけですが、 初版リリースがまともに動かないのはいつものことなので、 ある意味「仕様通り」のリリース計画であるとも考えられます。
一応、このファイルを開こうとしてみました。
見せてもらおうか、マイクロソフトの次期IDEの性能とやらを。
・・・。
予想通りというかなんというか、開くことすらできませんでした。 このテストファイル、1.38GBしかないんですけどね。 ※text services frameworkの上限である「2GB」にすら達していませんが、無理でした。
というか、ダークモードにも対応してませんね・・・。
というか、ダークモードにも対応してませんね・・・。
👆これ誤解。
問題内容
64bit版で2GBより大きいサイズのテキストのコピペをする事が出来ません。
もし処理出来ないならエラーメッセージを出して処理を中断する事が望ましいです。ただし処理できるようにする方がよりベターだと思います。
そもそもそんな大きいサイズのテキストをコピペする事は一般的な用途では無いと思いますが、64bit版なら出来そうな事に対応していない点の調査をしていて気づきました。
再現手順
test.7z.zip
上記のファイルをダウンロードして
test.7z
にリネームした後に展開すると 3.81 GBのテキストファイルが得られます。中身は あいうえお の記述を単にコピペで連続させたものです。行数は8192行ですが1行のサイズが大きいです。64bit版のサクラエディタであれば開くのに時間は掛かりますが開くこと自体は十分にメモリを積んでいれば問題なく行えます。
しかし全選択してコピーする操作(Ctrl + A, Ctrl + C)を行うといつまで経っても処理が完了しません。なのでタスクマネージャーなどで強制終了させざるを得ません。
再現頻度
常に再現します。
確認は 8a22482a42a6f9c94353c4c25af87b2bd45aa81d で行いました。
問題のカテゴリ
環境情報
Windows 10 Pro 64bit バージョン 20H2