Delphi:高速(er)widestring連結
-
26-09-2019 - |
質問
い機能を持っていたの仕事に変換するという事になりますのADO Recordset
へのhtml:
class function RecordsetToHtml(const rs: _Recordset): WideString;
の腸の機能については、これまでの広い文字列の連結:
while not rs.EOF do
begin
Result := Result+CRLF+
'<TR>';
for i := 0 to rs.Fields.Count-1 do
Result := Result+'<TD>'+VarAsWideString(rs.Fields[i].Value)+'</TD>';
Result := Result+'</TR>';
rs.MoveNext;
end;
により、数千の結果、機能か、どのユーザーというものを感じ、長すぎます。の デサンプリングプロファイラ ることを示 99.3% の時間を過ごしwidestring連結(@WStrCatN
や @WstrCat
).
誰でもできるので方法を考えなければなり改善widestring連結?とは思わないDelphi5はどのような文字列ビルダを構築します。や Format
をサポートしていないUnicodeで扱います。
というウィーゼル:ふりだ実装のインターフェース:
IRecordsetToHtml = interface(IUnknown)
function RecordsetToHtml(const rs: _Recordset): WideString;
end;
更新一
と思ったのを IXMLDOMDocument
, 構築をHTML形式をサポートしています。その後はその最終的なHTMLう xhtml
ない html
-微妙なが重要。
更新二
Microsoft knowledge baseの記事: 方向文字列の連結業績
解決 4
こ置しています。にオープンソース HtmlParser for Delphiは、ヘルパー TStringBuilder
クラスです。内部で使用されていた DomString
s、実際にエイリアスの WideString
:
TDomString = WideString;
ちょこっとガマン、ちょこっfiddlingのクラス:
TStringBuilder = class
public
constructor Create(ACapacity: Integer);
function EndWithWhiteSpace: Boolean;
function TailMatch(const Tail: WideString): Boolean;
function ToString: WideString;
procedure AppendText(const TextStr: WideString);
procedure Append(const value: WideString);
procedure AppendLine(const value: WideString);
property Length: Integer read FLength;
end;
のガッツの日常につなが
while not rs.EOF do
begin
sb.Append('<TR>');
for i := 0 to rs.Fields.Count-1 do
sb.Append('<TD>'+VarAsWideString(rs.Fields[i].Value));
sb.AppendLine('</TR>');
rs.MoveNext;
end;
このコードを 感じ 走限afaster.プロファイリングを示して 多く 改善;の WideString
操作や長さからなる。そのたFastMM独自の社内業務です。
注記
- 何かの間違いで強制力のすべての文字列であるがために、通常のコードページ
VarAsString
よVarAsWideString
) - 一部のHTML閉じタグはあくまでもオプションであり、省略するものを論理的にない。
他のヒント
WideStringには本質的に遅いです。あなたは、コードを見れば、それは文字列を再割り当てに保つとのOleaut32.dllからAPIですSysAllocStringLen()&Cを呼び出します。これは、Delphiのメモリマネージャを使用しませんが、私の知る限りでは、それはCOMのメモリマネージャを使用しています。 ほとんどのHTMLページがUTF-16を使用していないので、あなたはUTFから変換し、実際のコードページに注意する必要がありますが、ネイティブDelphiの文字列型と文字列のリストを使用して、より良い結果を得ることができ、そして変換がパフォーマンスを同様にダウングレードされます。 また、あなたはおそらくがをAnsiStringのの後、WideStringのに変換にバリアントを変換しVarAsString()関数を使用しています。デルファイのバージョンは、あなたが必ずあなたのバリアントがNULLになることはありませんすることができれば、それを避けるため、またはデルファイ自動変換に頼るVarAsWideString()または同様の何かの機能を持っているかどうかをチェックします。
うん、あなたのアルゴリズムは、(N ^ 2)Oで明らかにされています。
代わりにstring
を返す、TStringList
を返してみてください、と
while not rs.EOF do
begin
Result.Add('<TR>');
for i := 0 to rs.Fields.Count-1 do
Result.Add( '<TD>'+VarAsString(rs.Fields[i].Value)+'</TD>' );
Result := Result.Add('</TR>');
rs.MoveNext;
end;
あなたはその後、Result
TStringList.SaveToFile
を保存することができます 私はできない時間をお過ごしするだけ正確にコードです。
私の最速のものでなければならないことで:
することによって、すべての文字列は、合計の長さのものを加えるためのテーブルタグだけます。
利用にSetStringを一つの文字列の適切な長さです。
することによって、すべての文字列の再利用 の"移す"の手順 コピーする文字列の適切な位置は、最終文字列になります。
キーものが多くconcatenations文字列でなく、長めの定数配分は、パフォーマンスを改善。単一の配分はお客様の最大のtimesaver.
Widestringは参考カウントし、変更というのは文字列の操作が可能です。 場合にカンター-ジャパンは、前身企業なunicode符号化された, できる社内利用、ネイティブの文字列です(参考算)連結文字列に変換しまWidestring.内容は、以下のようになります:
var
NativeString: string;
begin
// ...
NativeString := '';
while not rs.EOF do
begin
NativeString := NativeString + CRLF + '<TR>';
for i := 0 to rs.Fields.Count-1 do
NativeString := NativeString + '<TD>'+VarAsString(rs.Fields[i].Value) + '</TD>';
NativeString := NativeString + '</TR>';
rs.MoveNext;
end;
Result := WideString(NativeString);
私は別のアプローチ:エンコードをUnicode UTF8String(参考として算入連結した変換UTF8StringにWidestring.でも私には分かりませんが、まUTF8String連結できます。のエンコーディングするのも一つの方法です。
とにかく、がWidestring連結するよりもずっと遅いですがネイティブの文字列。では、IMOが可能です。ぎるとチューニングなどのようなことがいえるでしょうすることは避けてください。 真剣に考えたの性能、そしてアップグレードデ少なくとも2009年.コスト買い取り工具の長期安いのでやって重hacks古いをご利用いただけます:standardとexpress。