1

object-c クラスのデフォルト セッターを入れ替えて、プロパティにオブザーバーを実際に追加することなく、ある種の KVO を許可しました。これはうまくいきます。しかし、場合によっては、このシステムに何十万ものプロパティを割り当てる必要があります。

したがって、パフォーマンス上の理由から、ivar を直接設定できるカスタム プロパティ記述子があります。パフォーマンスを調整するために、プロパティに関する情報を保存します。

残りの 1 つの場所は、object_setIvar() の使用です。これは、Instruments によると、割り当て中に CPU 時間の 60% を占めます。原因は、object_setIvar が _class_getVariable を呼び出していることです。これには、実際の割り当て (objc_storeStrong()) よりも 3 倍の時間がかかります。

簡単に言えば、プロパティ記述子の一部として事前にすべての情報をクラスのプロパティにキャッシュできるため、ivar をより速く設定するにはどうすればよいですか (object_setIvar() を回避する)。

これは、私のプロパティ記述子クラスの実際のオブジェクト セッター関数です (数値を設定するための同等のものもあります)。

- (id)setObjectValueNoKVOForOwner:(id)instance newObject:(id)newObject
{
    Class cls = object_getClass(instance);
    BOOL retainNewValue, copyNewValue, releaseOldValue;
    switch (self.setterSemantics)
    {
        case MemberDescriptionSetterSemanticsAssign:
            retainNewValue  = NO;
            copyNewValue    = NO;
            releaseOldValue = NO;
            break;

        case MemberDescriptionSetterSemanticsRetain:
            retainNewValue  = YES;
            copyNewValue    = NO;
            releaseOldValue = YES;
            break;

        case MemberDescriptionSetterSemanticsCopy:
            retainNewValue  = NO;
            copyNewValue    = YES;
            releaseOldValue = YES;
            break;
    }

    if (!_ivar)
    {
        _ivar = class_getInstanceVariable(cls, self.attributes.ivarName);
    }

    if (_ivar)
    {
        id oldObject = object_getIvar(instance, _ivar);
        if (newObject != oldObject)
        {
            if (retainNewValue)
            {
                newObject = [newObject retain];
            }
            else if (copyNewValue)
            {
                newObject = [newObject copy];
            }

            object_setIvar(instance, _ivar, newObject); // Improve this: avoid _class_getVariable

            if (releaseOldValue)
            {
                [oldObject release];
            }
        }
    }

    return [newObject autorelease];
}

アップデート:

object_setIvar() に関連するソースを見つけました: https://github.com/opensource-apple/objc4/blob/master/runtime/objc-class.mm http://www.opensource.apple.com/source/ objc4/objc4-532.2/runtime/objc-private.h http://www.opensource.apple.com/source/objc4/objc4-532.2/runtime/objc-runtime-new.mm

既知のクラスを引数として追加するだけで、object_setIvar() の独自のバージョンを実装することは「その」悪とは思えません。残念ながら、プライベート ヘッダー ファイルが必要です。私は iOS をターゲットにしているので、現時点では希望を捨てるべきだと思われます。

更新 2:

このコメントは、アップルのソースで時間を無駄にしている場所で見つけました。

"// FIXME: これは最適化できます。"

そのため、この時点でおそらくあきらめて、将来改善されることを期待する必要があります。プロパティに値を設定するのと同じくらい基本的なことの中にそのようなボトルネックがあることを私は実際には本当に理解していません。一方で、Apple のプログラマーも単なる人間であることを嬉しく思います :)。

4

1 に答える 1

0

このシステムの周りの数十万のプロパティ

私はこのトピックの専門家ではありませんが、プロセッサ メモリ バスの内部動作に関する私の理解では、互いに離れた値 (L1-3 キャッシュ ヒット) よりも近くの値(L1-3 キャッシュ ヒット)を変更する方がはるかに優れていることが示唆されていますキャッシュミス)。

したがって、高速ストレージのために値の単純な連続C 配列を使用したほうがよいのではないでしょうか?

于 2013-11-01T13:20:22.223 に答える