2

Java で C# クラスを複製しています。(私は Java の初心者です。)

私のクラスは、double に関連付けられた int 値を追跡する必要があります。次に、値が double を下回ったり上回ったりするたびに、Alerter(int) を作成する必要があります。

Alerter.LatencySensitiveAction() は、すぐに呼び出す必要があります。これは、遅延の影響を受けやすく、タイム クリティカルなコードです。DoubleMap クラスの目的は、LatencySensitiveAction() をできるだけ速く呼び出すことです。

DoubleMap.OnData() は、クラスの遅延に影響されやすいメソッドです (以下)。

TreeMap は理にかなっていますか? C# で SortedList を使用しています。キーと値のペアを高速トラバーサルでソートされた順序で格納する連想コレクションを探しています。

私はこのJavaコードと言われました

for (Map.Entry<Double,Alerter> entry : mAscend.entrySet() )

新しいオブジェクトを作成するため、効率的ではありません。代わりに何を使用すればよいですか?

したがって、基本的に、double と int を関連付けることができ、ソートされた順序で格納され、コレクションを順番にトラバースする最速の方法を使用するコレクションを尋ねています。

私の C# コード (以下) でうまくいくと思いますが、Java への変換には助けが必要です。私の C# コードも改善できると思われる場合は、教えてください.. ty.

Java コード:

public class DoubleMap {

    TreeMap<Double,Alerter> mAscend, mDecend, mHoldAscend, mHoldDecend;

    public DoubleMap()
    {
        mAscend = new TreeMap<Double, Alerter>();
        mDecend = new TreeMap<Double, Alerter>(new ReverseComparator());
    }

    public void Add(boolean rAscend, double value, int size)
    {
        TreeMap<Double,TradeOrder> list = rAscend ? mAscend : mDecend;

        Alerter to = list.get(value);
        if ( to != null )
        {
            Alerter.size += size;
        }
        else 
        {
            to = new Alerter (size);           
            list.put(value, to);
        }
    }

    public void Remove(boolean rAscend, double value, int size)
    {
        TreeMap<Double,TradeOrder> list = rAscend ? mAscend : mDecend;

        Alerter to = list.get(value);
        if ( to != null )
        {
            long nsize = to.size - size;
            if ( nsize <= 0 )
                list.remove(value);
            else
                to.size = nsize;
        }
    }

    public void Ondata(double rValue)
    {
        for (Map.Entry<Double,Alerter> entry : mAscend.entrySet() )
        {
            if ( entry.getKey() > rValue )
                break;

            entry.getValue().LatencySensitiveAction();

            if ( mHoldAscend == null )
                mHoldAscend = new TreeMap<Double,Alerter>(mHoldAscend);
            mAscend.remove(entry.getKey());
        }

        for (Map.Entry<Double,TradeOrder> entry : mDecend.entrySet() )
        {
            if ( entry.getKey() < rValue )
                break;

            entry.getValue().LatencySensitiveAction();

            if ( mHoldDecend == null )
                mHoldDecend = new TreeMap<Double,TradeOrder>(mHoldDecend);
            mHoldDecend.remove(entry.getKey());
        }

        if ( mHoldAscend != null )
        {
            mAscend = mHoldAscend;
            mHoldAscend = null;
        }

        if ( mHoldDecend != null )
        {
            mDecend = mHoldDecend;
            mHoldDecend = null;
        }

    }
}

C# コード:

public class DoubleMap
{
    private SortedList<double, Alerter> mAscend, mDecend, mHoldAscend, mHoldDecend;

    public DoubleMap()
    {
        mAscend = new SortedList<double, Alerter>();
        mDecend = new SortedList<double, Alerter>(new DescendingComparer<double>());
    }

    public void Add(bool rAscend, double rValue, long rSize)
    {
        var list = rAscend ? mAscend : mDecend;
        Alerter to;
        if (list.TryGetValue(rValue, out to))
        {
            to.Size += rSize;
        }
        else
        {
            to = new Alerter(rSize);
            list.Add(rValue, to);
        }
    }

    public void Remove(bool rAscend, double rValue, long rSize)
    {
        var list = rAscend ? mAscend : mDecend;
        Alerter to;
        if (list.TryGetValue(rValue, out to))
        {
            long nqty = to.Size - rSize;
            if (nqty <= 0)
            {
                list.Remove(rValue);
            }
            else
                to.Size = nqty;
        }
    }

    public void OnData(double rValue)
    {
        foreach (var pair in mAscend)
        {
            if (pair.Key > rValue)
                break;

            pair.Value.LatencySensitiveAction();

            if (mHoldAscend == null)
                mHoldAscend = new SortedList<double, Alerter>(mAscend);
            mHoldAscend.Remove(pair.Key);
        }

        foreach (var pair in mDecend)
        {
            if (pair.Key < rValue)
                break;

            pair.Value.LatencySensitiveAction();

            if (mHoldDecend == null)
                mHoldDecend = new SortedList<double, Alerter>(mDecend, new DescendingComparer<double>());
            mHoldDecend.Remove(pair.Key);
        }

        if (mHoldAscend != null)
        {
            mAscend = mHoldAscend;
            mHoldAscend = null;
        }

        if (mHoldDecend != null)
        {
            mDecend = mHoldDecend;
            mHoldDecend = null;
        }
    }
}

class DescendingComparer<T> : IComparer<T> where T : IComparable<T>
{
    public int Compare(T x, T y)
    {
        return y.CompareTo(x);
    }
}
4

3 に答える 3

3

待ち時間が非常に重要な場合は、カスタム クラスを実装してオーダー ブックを処理することをお勧めします (これはオーダー ブックですよね? :-) )

次のようなものをお勧めします。

  • 価格を表す double の配列 (ps なぜ double を使用しているのですか?浮動小数点の不正確さを避けるために、これは BigDecimal または固定小数点整数のいずれかであるべきではありませんか?)
  • 注文サイズに対応する long の配列
  • 対応するアラートの配列
  • 価格に従ってすべての配列を並べ替える
  • 次に、価格配列でバイナリ検索を直接使用して、特定の範囲の価格を探すことができます

このアプローチにより、レイテンシが非常に低くなります。

欠点は、注文を追加/削除するのが O(n) であることです。しかし、これはわずか 3 つの s で非常に安価な O(n) でarraycopyあるため、オーダー ブックが非常に大きくない限り、オーバーヘッドは非常に低く、気付かないでしょう。

また、Java 用の非常に低遅延のライブラリのセットを含むJavolutionにも興味があるかもしれません。そのうちのいくつかは、アプリケーションの取引用に特別に設計されていると思います。

于 2012-03-05T02:34:30.723 に答える
0

最新の OS で「低遅延」のアプリケーションを扱うときは常に、それがプリエンプティブであることを念頭に置いておく必要があります。リアルタイム オペレーティング システムではないため、任意のスレッドをいつでも中断できます。また、応答時間については保証されません。正直なところ低レイテンシ/一貫したレイテンシを実現しようとしている場合は、少なくともタスク スケジューラでアプリケーションをリアルタイムにプッシュする必要があります。これも真のリアルタイムではありませんが、スレッドがより多くのプロセッサ時間を取得するのに役立ちます。また、GC がスレッドを停止してクリーンアップできることも考慮してください。

最小のレイテンシー、または少なくともより保証されたレイテンシーを実現することに本当に関心がある場合は、少なくとも C++ または C に切り替えます。少なくとも、メモリ割り当てを制御でき、GC の実行を心配する必要はありません。予期しない遅延を引き起こします。

于 2012-03-05T04:45:30.317 に答える
0

トラバーサルしかしていないのに、なぜマップを使用するのでしょうか? O(n) 未満でトラバーサルを実行することはできません。

注文をカプセル化するオブジェクトを作成し、コレクションの PriorityQueue を確認することをお勧めします。

範囲検索を行う必要がある場合は、TreeSet (値が一意の場合) または TreeMap を調べることもできます。(ただし、これらのクラスからソートされた出力を取得するには、特定の方法で反復を行う必要があることに注意してください。)

編集

レビュアーfor (Map.Entry<Double,Alerter> entry : mAscend.entrySet())が for ループ内のコードではなく、 が非効率的であることを意味していたのは確かですか? ペアを一致させるたびに、新しいコレクションの作成を実行しています(それ自体は安価な作業ではなく、時間に敏感なコード内で行うのは確かに良いことではありません)。C# コード内で同じことを行っています。

これを試して:

Code Deleted; See history

編集2

並べ替えと検索の両方を実行するために TreeMap のみに依存しているため、実装が実際には必要以上に遅いことに気付きました。はるかに高速な実装を次に示します。

public class DoubleMap {
    HashMap<Double, Alerter> mAscend, mDescend;
    PriorityQueue<Double> pricesAscending, pricesDescending;

    public DoubleMap()
    {
        pricesAscending = new PriorityQueue<Double>(100);
        pricesDescending = new PriorityQueue<Double>(100, new ReverseComparator());
    }

    public void Add(boolean rAscend, double value, int size)
    {
        Map<Double, Alerter> map = rAscend ? mAscend : mDescend;

        Alerter to = map.get(value);
        if ( to != null )
        {
            Alerter.size += size;
        }
        else 
        {
            to = new Alerter (size);           
            map.put(value, to);
            pricesAscending.offer(value);
            pricesDescending.offer(value);
        }
    }

    public void Remove(boolean rAscend, double value, int size)
    {
        Map<Double, Alerter> map = rAscend ? mAscend : mDecend;

        Alerter to = map.get(value);
        if ( to != null )
        {
            long nsize = to.size - size;
            if ( nsize <= 0 )
                map.remove(value);
                pricesAscending.remove(value);
                pricesDescending.remove(value);
            else
                to.size = nsize;
        }
    }

    public void Ondata(double rValue)
    {
        while (pricesAscending.peek() < rValue) {
            mAscend.getValue(pricesAscending.peek()).LatencySensitiveAction();

            mAscend.remove(pricesAscending.poll());
        }

        while (pricesDescending.peek() > rValue) {
            mDescend.getValue(pricesDescending.peek()).LatencySensitiveAction();

            mDescend.remove(pricesDescending.poll());
        }
    }
}

違い: HashMap には定数時間get()remove()操作があり、TreeMap にはO(log(n))それらの操作のパフォーマンスがあります。

PriorityQueue は一定の時間peek()poll()パフォーマンスを備えています。

于 2012-03-05T02:33:06.917 に答える