javascript

git

java

python

git-remote

c++

github

django

c#

reactjs

css

content-type

variables

var

loops

iteration

std

c++-faq

git-checkout

generator

html5-Angular JS缩放和性能

我们正在使用为银行构建的Angular应用程序来应对性能问题。

不幸的是,显示代码片段违反了合同。 无论如何,我可以描述正在进行的一些主要问题,我希望可以推荐最佳实践。

应用结构:

  • 本质上,是一个巨大的多表单页面。
  • 每种形式都是其自己的部分,带有嵌套的控制器和大约3层深的部分。
  • 在json对象的集合上重复ng相同的形式。
  • 每个表单都绑定到重复的对象/模型。
  • 我们应该支持该页面上1-200个表格中的任何一个。

如果您看一下时间线。 我们在jQuery parse html方法,jQuery重新计算stye方法,GC事件(垃圾收集)上花费了大量时间。 我想将这些最小化应该可以加快速度。 它们都是Angular生命周期的一部分,但是可能有更好的方法来避免它们。 这是探查器的一些屏幕截图:

Recalculate Style GC Event

最终,随着重复表单的数量超过5,该应用程序变得迟钝。每种表单相对于其他表单都没有关系。 我们试图不监视表单之间的任何共享属性。

trans by 2020-08-12T10:38:40Z

Haskell Thrift库在性能方面比C ++慢300倍

我正在构建一个包含两个组件的应用程序-用Haskell编写的服务器和用Qt(C ++)编写的客户端。 我正在节俭地与他们交流,我想知道为什么它这么慢。

我进行了性能测试,这是我的机器上的结果

结果

C++ server and C++ client:

Sending 100 pings                    -    13.37 ms
Transfering 1000000 size vector      -   433.58 ms
Recieved: 3906.25 kB
Transfering 100000 items from server -  1090.19 ms
Transfering 100000 items to server   -   631.98 ms

Haskell server and C++ client:

Sending 100 pings                       3959.97 ms
Transfering 1000000 size vector      - 12481.40 ms
Recieved: 3906.25 kB
Transfering 100000 items from server - 26066.80 ms
Transfering 100000 items to server   -  1805.44 ms

为什么Haskell在测试中这么慢? 如何提高性能?

这些是文件:

档案

性能节俭

namespace hs test
namespace cpp test

struct Item {
    1: optional string    name
    2: optional list<i32> coordinates
}

struct ItemPack {
    1: optional list<Item>     items
    2: optional map<i32, Item> mappers
}


service ItemStore {
    void ping()
    ItemPack getItems(1:string name, 2: i32 count) 
    bool     setItems(1: ItemPack items)

    list<i32> getVector(1: i32 count)
}

主站

{-# LANGUAGE ScopedTypeVariables #-}   
module Main where

import           Data.Int  
import           Data.Maybe (fromJust) 
import qualified Data.Vector as Vector
import qualified Data.HashMap.Strict  as HashMap
import           Network

-- Thrift libraries
import           Thrift.Server

-- Generated Thrift modules
import Performance_Types
import ItemStore_Iface
import ItemStore


i32toi :: Int32 -> Int
i32toi = fromIntegral

itoi32 :: Int -> Int32
itoi32 = fromIntegral

port :: PortNumber
port = 9090

data ItemHandler = ItemHandler

instance ItemStore_Iface ItemHandler where
    ping _                   = return () --putStrLn "ping"
    getItems _ mtname mtsize = do 
        let size = i32toi $ fromJust mtsize
            item i = Item mtname (Just $ Vector.fromList $ map itoi32 [i..100])
            items = map item [0..(size-1)]
            itemsv = Vector.fromList items 
            mappers = zip (map itoi32 [0..(size-1)]) items 
            mappersh = HashMap.fromList mappers
            itemPack = ItemPack (Just itemsv) (Just mappersh)
        putStrLn "getItems"
        return itemPack

    setItems _ _             = do putStrLn "setItems"
                                  return True

    getVector _ mtsize       = do putStrLn "getVector"
                                  let size = i32toi $ fromJust mtsize
                                  return $ Vector.generate size itoi32

main :: IO ()
main = do
    _ <- runBasicServer ItemHandler process port 
    putStrLn "Server stopped"

ItemStore_client.cpp

#include <iostream>
#include <chrono>
#include "gen-cpp/ItemStore.h"

#include <transport/TSocket.h>
#include <transport/TBufferTransports.h>
#include <protocol/TBinaryProtocol.h>

using namespace apache::thrift;
using namespace apache::thrift::protocol;
using namespace apache::thrift::transport;

using namespace test;
using namespace std;

#define TIME_INIT  std::chrono::_V2::steady_clock::time_point start, stop; \
                   std::chrono::duration<long long int, std::ratio<1ll, 1000000000ll> > duration;
#define TIME_START start = std::chrono::steady_clock::now(); 
#define TIME_END   duration = std::chrono::steady_clock::now() - start; \
                   std::cout << chrono::duration <double, std::milli> (duration).count() << " ms" << std::endl;

int main(int argc, char **argv) {

    boost::shared_ptr<TSocket> socket(new TSocket("localhost", 9090));
    boost::shared_ptr<TTransport> transport(new TBufferedTransport(socket));
    boost::shared_ptr<TProtocol> protocol(new TBinaryProtocol(transport));

    ItemStoreClient server(protocol);
    transport->open();

    TIME_INIT

    long pings = 100;
    cout << "Sending " << pings << " pings" << endl;
    TIME_START
    for(auto i = 0 ; i< pings ; ++i)
        server.ping();
    TIME_END


    long vectorSize = 1000000;

    cout << "Transfering " << vectorSize << " size vector" << endl;
    std::vector<int> v;
    TIME_START
    server.getVector(v, vectorSize);
    TIME_END
    cout << "Recieved: " << v.size()*sizeof(int) / 1024.0 << " kB" << endl;


    long itemsSize = 100000;

    cout << "Transfering " << itemsSize << " items from server" << endl;
    ItemPack items;
    TIME_START
    server.getItems(items, "test", itemsSize);
    TIME_END


    cout << "Transfering " << itemsSize << " items to server" << endl;
    TIME_START
    server.setItems(items);
    TIME_END

    transport->close();

    return 0;
}

ItemStore_server.cpp

#include "gen-cpp/ItemStore.h"
#include <thrift/protocol/TBinaryProtocol.h>
#include <thrift/server/TSimpleServer.h>
#include <thrift/transport/TServerSocket.h>
#include <thrift/transport/TBufferTransports.h>

#include <map>
#include <vector>

using namespace ::apache::thrift;
using namespace ::apache::thrift::protocol;
using namespace ::apache::thrift::transport;
using namespace ::apache::thrift::server;


using namespace test;
using boost::shared_ptr;

class ItemStoreHandler : virtual public ItemStoreIf {
  public:
    ItemStoreHandler() {
    }

    void ping() {
        // printf("ping\n");
    }

    void getItems(ItemPack& _return, const std::string& name, const int32_t count) {

        std::vector <Item> items;
        std::map<int, Item> mappers;

        for(auto i = 0 ; i < count ; ++i){
            std::vector<int> coordinates;
            for(auto c = i ; c< 100 ; ++c)
                coordinates.push_back(c);

            Item item;
            item.__set_name(name);
            item.__set_coordinates(coordinates);

            items.push_back(item);
            mappers[i] = item;
        }

        _return.__set_items(items);
        _return.__set_mappers(mappers);
        printf("getItems\n");
    }

    bool setItems(const ItemPack& items) {
        printf("setItems\n");
        return true;
    }

    void getVector(std::vector<int32_t> & _return, const int32_t count) {
        for(auto i = 0 ; i < count ; ++i)
            _return.push_back(i);
        printf("getVector\n");
    }
};

int main(int argc, char **argv) {
    int port = 9090;
    shared_ptr<ItemStoreHandler> handler(new ItemStoreHandler());
    shared_ptr<TProcessor> processor(new ItemStoreProcessor(handler));
    shared_ptr<TServerTransport> serverTransport(new TServerSocket(port));
    shared_ptr<TTransportFactory> transportFactory(new TBufferedTransportFactory());
    shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory());

    TSimpleServer server(processor, serverTransport, transportFactory, protocolFactory);
    server.serve();
    return 0;
}

生成文件

GEN_SRC := gen-cpp/ItemStore.cpp gen-cpp/performance_constants.cpp gen-cpp/performance_types.cpp
GEN_OBJ := $(patsubst %.cpp,%.o, $(GEN_SRC))

THRIFT_DIR := /usr/local/include/thrift
BOOST_DIR := /usr/local/include

INC := -I$(THRIFT_DIR) -I$(BOOST_DIR)

.PHONY: all clean

all:   ItemStore_server ItemStore_client

%.o: %.cpp
    $(CXX) --std=c++11 -Wall -DHAVE_INTTYPES_H -DHAVE_NETINET_IN_H $(INC) -c $< -o $@

ItemStore_server: ItemStore_server.o $(GEN_OBJ) 
    $(CXX) $^ -o $@ -L/usr/local/lib -lthrift -DHAVE_INTTYPES_H -DHAVE_NETINET_IN_H

ItemStore_client: ItemStore_client.o $(GEN_OBJ)
    $(CXX) $^ -o $@ -L/usr/local/lib -lthrift -DHAVE_INTTYPES_H -DHAVE_NETINET_IN_H

clean:
    $(RM) *.o ItemStore_server ItemStore_client

编译并运行

我生成文件(使用此处的thrift 0.9):

$ thrift --gen cpp performance.thrift
$ thrift --gen hs performance.thrift

编译

$ make
$ ghc Main.hs gen-hs/ItemStore_Client.hs gen-hs/ItemStore.hs gen-hs/ItemStore_Iface.hs gen-hs/Performance_Consts.hs gen-hs/Performance_Types.hs -Wall -O2

运行Haskell测试:

$ ./Main& 
$ ./ItemStore_client

运行C ++测试:

$ ./ItemStore_server&
$ ./ItemStore_client

记住在每次测试后都要杀死服务器

更新资料

编辑了getVector方法以使用getItems代替Vector.fromList,但仍然无效

更新2

由于@MdxBhmt的建议,我测试了getItems函数,如下所示:

getItems _ mtname mtsize = do let size = i32toi $! fromJust mtsize
                                  item i = Item mtname (Just $!  Vector.enumFromN (i::Int32) (100- (fromIntegral i)))
                                  itemsv = Vector.map item  $ Vector.enumFromN 0  (size-1)
                                  itemPack = ItemPack (Just itemsv) Nothing 
                              putStrLn "getItems"
                              return itemPack

在我的原始实现的基础上,这是严格的,并且改进了Vector的生成,相对于其替代方法:

getItems _ mtname mtsize = do let size = i32toi $ fromJust mtsize
                                  item i = Item mtname (Just $ Vector.fromList $ map itoi32 [i..100])
                                  items = map item [0..(size-1)]
                                  itemsv = Vector.fromList items 
                                  itemPack = ItemPack (Just itemsv) Nothing
                              putStrLn "getItems"
                              return itemPack

请注意,没有发送HashMap。 第一个版本的时间为12338.2毫秒,第二个版本为11698.7毫秒,没有加速:(

更新3

我向Thrift Jira报告了一个问题

abhinav的Update 4

这是完全不科学的,但是使用带有Thrift 0.9.2的GHC 7.8.3和@MdxBhmt的版本getItems,可以大大减少差异。

C++ server and C++ client:

Sending 100 pings:                     8.56 ms
Transferring 1000000 size vector:      137.97 ms
Recieved:                              3906.25 kB
Transferring 100000 items from server: 467.78 ms
Transferring 100000 items to server:   207.59 ms

Haskell server and C++ client:

Sending 100 pings:                     24.95 ms
Recieved:                              3906.25 kB
Transferring 1000000 size vector:      378.60 ms
Transferring 100000 items from server: 233.74 ms
Transferring 100000 items to server:   913.07 ms

执行了多次执行,每次都重新启动服务器。 结果是可重现的。

请注意,原始问题的源代码(使用@MdxBhmt的getItems实现)将无法原样编译。 必须进行以下更改:

getItems _ mtname mtsize = do let size = i32toi $! fromJust mtsize
                                  item i = Item mtname (Just $!  Vector.enumFromN (i::Int32) (100- (fromIntegral i)))
                                  itemsv = Vector.map item  $ Vector.enumFromN 0  (size-1)
                                  itemPack = ItemPack (Just itemsv) Nothing 
                              putStrLn "getItems"
                              return itemPack

getVector _ mtsize       = do putStrLn "getVector"
                              let size = i32toi $ fromJust mtsize
                              return $ Vector.generate size itoi32
trans by 2020-08-12T08:06:03Z

衡量代码执行所需时间的最佳方法是什么?

我正在尝试确定哪种方法删除字符串最快。

我只是获得开始时间和结束时间并显示差异。

但是结果是如此多样,例如 如下所示,相同的方法可能需要60毫秒至231毫秒。

什么是获得更准确结果的更好方法?

替代文字[http://www.deviantsart.com/upload/1q4t3rl.png]

using System;
using System.Collections;
using System.Collections.Generic;

namespace TestRemoveFast
{
    class Program
    {
        static void Main(string[] args)
        {
            for (int j = 0; j < 10; j++)
            {
                string newone = "";
                List<string> tests = new List<string>();
                for (int i = 0; i < 100000; i++)
                {
                    tests.Add("{http://company.com/Services/Types}ModifiedAt");
                }

                DateTime start = DateTime.Now;
                foreach (var test in tests)
                {
                    //newone = ((System.Xml.Linq.XName)"{http://company.com/Services/Types}ModifiedAt").LocalName;
                    newone = Clean(test);
                }

                Console.WriteLine(newone);
                DateTime end = DateTime.Now;
                TimeSpan duration = end - start;
                Console.WriteLine(duration.ToString());
            }

            Console.ReadLine();
        }

        static string Clean(string line)
        {
            int pos = line.LastIndexOf('}');
            if (pos > 0)
                return line.Substring(pos + 1, line.Length - pos - 1);
                //return line.Substring(pos + 1);
            else
                return line;
        }
    }
}
trans by 2020-08-12T05:40:40Z

性能-上传到正在运行的Android emu的速度较慢

我已经搜索过,但没有找到针对我的具体情况的任何疑问或答案。 我有一台运行速度很快的新机器,它具有运行Windows 7的大量内存。我正在使用最新的Eclipse和Android SDK。

从运行启动到运行我的应用程序,模拟器运行大约需要45秒钟(对于模拟器而言,这真是太快了!)。

如果然后我更改应用程序并在仍在运行的模拟器上重新运行它,则时间将增加到70多秒! 与人们的所有其他投诉相反,就我而言,重新启动模拟器比使用现有实例要快。 我不喜欢

这是时间:

2011-09-29 13:07:13 - hello Uploading hello.apk onto device 'emulator-5554'
2011-09-29 13:07:18 - hello Installing hello.apk...
2011-09-29 13:07:37 - hello Success!

在更改应用程序以使其重新加载后运行:

2011-09-29 13:08:18 - hello Uploading hello.apk onto device 'emulator-5554'
2011-09-29 13:09:16 - hello Installing hello.apk...
2011-09-29 13:09:24 - hello Success!

如您所见,重新启动仿真器后,上传到仿真器仅需5秒钟。 正在运行的模拟器需要将近一分钟! 这是延长重新运行时间的原因。 即使我在重新运行它之前在模拟器上卸载该应用程序,这也不会改变。

关于我可以尝试解决的任何想法? 它似乎是某种通信问题,可能与adb有关。

trans by 2020-08-11T21:46:11Z

使用Boost.Lockfree队列比使用互斥体慢

到目前为止,我在项目中使用的是boost::lockfree::queue。 我测量了此队列上特定操作所需的平均时间。

时间是在两台机器上测量的:我的本地Ubuntu VM和一台远程服务器。使用boost::lockfree::queue,两台计算机上的平均值几乎相同:〜750微秒。

然后,我将boost::lockfree::queue“升级”到bool is_lock_free(void) const;,这样我就可以摆脱保护队列的互斥锁了。 在我的本地VM上,我可以看到巨大的性能提升,现在平均为200微秒。 但是,在远程计算机上,平均时间达到800微秒,比以前慢。

首先,我认为这可能是因为远程计算机可能不支持无锁实现:

在Boost.Lockfree页面上:

并非所有硬件都支持同一组原子指令。 如果它在硬件中不可用,则可以使用防护在软件中对其进行仿真。 然而,这具有丢失无锁属性的明显缺点。

要了解是否支持这些说明,boost::lockfree::queue具有称为bool is_lock_free(void) const;的方法。但是,boost::lockfree::spsc_queue没有这样的功能,对我而言,这意味着它不依赖硬件,并且在任何计算机上始终是无锁的。

性能下降的原因可能是什么?


示例代码(生产者/消费者)

// c++11 compiler and boost library required

#include <iostream>
#include <cstdlib>
#include <chrono>
#include <async>
#include <thread>
/* Using blocking queue:
 * #include <mutex>
 * #include <queue>
 */
#include <boost/lockfree/spsc_queue.hpp>


boost::lockfree::spsc_queue<int, boost::lockfree::capacity<1024>> queue;

/* Using blocking queue:
 * std::queue<int> queue;
 * std::mutex mutex;
 */

int main()
{
    auto producer = std::async(std::launch::async, [queue /*,mutex*/]() 
    {
        // Producing data in a random interval
        while(true)
        {
            /* Using the blocking queue, the mutex must be locked here.
             * mutex.lock();
             */

            // Push random int (0-9999)
            queue.push(std::rand() % 10000);

            /* Using the blocking queue, the mutex must be unlocked here.
             * mutex.unlock();
             */

            // Sleep for random duration (0-999 microseconds)
            std::this_thread::sleep_for(std::chrono::microseconds(rand() % 1000));
        }
    }

    auto consumer = std::async(std::launch::async, [queue /*,mutex*/]() 
    {
        // Example operation on the queue.
        // Checks if 1234 was generated by the producer, returns if found.

        while(true)
        {
            /* Using the blocking queue, the mutex must be locked here.
             * mutex.lock();
             */

            int value;
            while(queue.pop(value)
            {
                if(value == 1234)
                    return;
            }

            /* Using the blocking queue, the mutex must be unlocked here.
             * mutex.unlock();
             */

            // Sleep for 100 microseconds
            std::this_thread::sleep_for(std::chrono::microseconds(100));
        }
    }

    consumer.get();
    std::cout << "1234 was generated!" << std::endl;
    return 0;
}
trans by 2020-08-11T20:00:49Z

性能-我们何时应该使用Radix排序?

似乎Radix sort具有非常好的平均用例性能,即O(kN):[http://en.wikipedia.org/wiki/Radix_sort]

但是似乎大多数人仍在使用快速排序,不是吗?

trans by 2020-08-11T19:08:49Z

性能-Android:requestLayout()调用不正确

当我尝试给ListView中的布局充气时,会发生以下错误:

requestLayout() improperly called by android.widget.TextView{...} during layout: running second layout pass

我正尝试在ListView中扩大布局,如下所示:

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    if(convertView == null){
        LayoutInflater inflater = (LayoutInflater) musicActivity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        convertView = inflater.inflate(R.layout.list_item, parent, false);
        ...
    }else{...}
}

被夸大的布局看起来像下面这样简单,仍然会产生错误

<TextView
    android:id="@+id/txt"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:textSize="@dimen/txt_size"/>

我调查了类似的问题,但没有找到解决方案,似乎可以解决问题1,问题2,问题3。

有谁知道是什么原因导致这种类型的错误? 有任何故障排除建议吗? 有关更多上下文,请在ViewPager中的Fragment中显示此ListView

更新

这是完整的XML布局(减去一堆属性),仍然会导致问题

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="match_parent"
 android:layout_height="match_parent">

 <TextView
    android:id="@+id/txt1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" />

 <TextView
    android:id="@+id/txt2"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" />

 <TextView
    android:id="@+id/txt3"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" />

<TextView
    android:id="@+id/txt4"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"/>

</RelativeLayout>

基于此,我认为XML本身不是问题,除非它与我正在使用ViewPager和Fragments有关

trans by 2020-08-11T01:28:20Z

c#-一次连接执行多个sql命令或每次重新连接是否更好?

这是我的测试代码,似乎暗示多次连接比一次连接更好。

难道我做错了什么?

int numIts = 100;
Stopwatch sw = new Stopwatch();
sw.Start();
using (SqlConnection connection = new SqlConnection(connectionParameters))
{   
            connection.Open();
    for(int i = 0; i < numIts; i++)
    {
        SqlCommand command = new SqlCommand(sqlCommandName, connection);
                command.CommandType = CommandType.StoredProcedure;
                command.Parameters.AddWithValue(par1Name, par1Val);
                command.Parameters.AddWithValue(par2Name, par2Val);
        using(SqlDataReader reader = command.ExecuteReader())
        {
        }
    }
}
sw.Stop();
TimeSpan durationOfOneConnectionManyCommands = sw.Elapsed;
Console.WriteLine(durationOfOneConnectionManyCommands);

sw.Reset();

sw.Start();
for(int i = 0; i < numIts; i++)
{
    using (SqlConnection connection = new SqlConnection(connectionParameters))
    {   
                connection.Open();
        SqlCommand command = new SqlCommand(sqlCommandName, connection);
                command.CommandType = CommandType.StoredProcedure;
                command.Parameters.AddWithValue(par1Name, par1Val);
                command.Parameters.AddWithValue(par2Name, par2Val);
        using(SqlDataReader reader = command.ExecuteReader())
        {
        }
    }                               
}
sw.Stop();
TimeSpan durationOfManyConnections = sw.Elapsed;
Console.WriteLine(durationOfManyConnections);

输出:

//output:
//00:00:24.3898218   // only one connection established
//00:00:23.4585797   // many connections established.
//
//output after varying parameters (expected much shorter):
//00:00:03.8995448
//00:00:03.4539567

更新:

好的,所以那些说使用一个连接会更快的人有了它。 (尽管相差不大,如果有的话。)这是修改后的代码和输出:

public void TimingTest()
{
    numIts = 1000;
    commandTxt = "select " + colNames + " from " + tableName;

    OneConnection();
    ManyConnections();
    OneConnection();
}
private void ManyConnections()
{
    Stopwatch sw = new Stopwatch();
    sw.Start();
    for (int i = 0; i < numIts; i++)
    {
        using (SqlConnection connection = new SqlConnection(connectionParameters))
        {
            connection.Open();
            using (SqlCommand command = connection.CreateCommand())
            {
                command.CommandText = commandTxt;

                using (SqlDataReader reader = command.ExecuteReader())
                {
                }
            }
        }
    }
    sw.Stop();
    TimeSpan durationOfManyConnections = sw.Elapsed;
    Console.WriteLine("many connections: " + durationOfManyConnections);
}
private void OneConnection()
{
    Stopwatch sw = new Stopwatch();
    sw.Start();
    using (SqlConnection connection = new SqlConnection(connectionParameters))
    {
        connection.Open();
        for (int i = 0; i < numIts; i++)
        {
            using (SqlCommand command = connection.CreateCommand())
            {
                command.CommandText = commandTxt;
                using (SqlDataReader reader = command.ExecuteReader())
                {
                }
            }
        }
    }
    sw.Stop();
    TimeSpan durationOfOneConnectionManyCommands = sw.Elapsed;
    Console.WriteLine("one connection: " + durationOfOneConnectionManyCommands);
}

输出:

one connection: 00:00:08.0410024
many connections: 00:00:08.7278090
one connection: 00:00:08.6368853

one connection: 00:00:10.7965324
many connections: 00:00:10.8674326
one connection: 00:00:08.6346272

更新:

如果我在每个函数之后都使用SQLConnection.ClearAllPools(),则区别更加明显:

输出:

one connection: 00:00:09.8544728
many connections: 00:00:11.4967753
one connection: 00:00:09.7775865
trans by 2020-08-10T22:23:36Z

C ++ map <std :: string> vs map <char *>性能(我知道,还是“?”)

我使用的地图带有char *键,并且在一切正常的情况下,我没有获得预期的性能。 我只搜索了一些地方来优化和改进某些东西,那时同事说:“字符串键会变慢。”

我读了几十个问题,他们总是说:

“不要使用char *作为密钥”
std::string钥匙永远不是您的瓶颈”
char *std::string是一个神话。”

我很不情愿地尝试了char *键,但有很大的不同。

我将问题归结为一个简单的例子:

#include <stdio.h>
#include <stdlib.h>
#include <map>

#ifdef USE_STRING

#include <string>
typedef std::map<std::string, int> Map;

#else

#include <string.h>
struct char_cmp { 
    bool operator () (const char *a,const char *b) const 
    {
        return strcmp(a,b)<0;
    } 
};
typedef std::map<const char *, int, char_cmp> Map;

#endif

Map m;

bool test(const char *s)
{
    Map::iterator it = m.find(s);
    return it != m.end();
}

int main(int argc, char *argv[])
{
    m.insert( Map::value_type("hello", 42) );

    const int lcount = atoi(argv[1]);
    for (int i=0 ; i<lcount ; i++) test("hello");
}

首先是std :: string版本:

$ g++ -O3 -o test test.cpp -DUSE_STRING
$ time ./test 20000000
real    0m1.893s

接下来的'char *'版本:

g++ -O3 -o test test.cpp             
$ time ./test 20000000
real    0m0.465s

这是一个很大的性能差异,与我在较大的程序中看到的相同。

使用char *钥匙很难释放钥匙,只是感觉不对。 C ++专家我缺少什么? 有什么想法或建议吗?

trans by 2020-08-10T19:33:11Z

asp.net-ConfigurationManager.AppSettings缓存

我们知道IIS会缓存ConfigurationManager.AppSettings,因此它仅读取磁盘一次,直到web.config更改为止。 这样做是出于性能目的。

有人在:

[HTTP://forums.asp.net/怕/1080926/1598469.aspx#1598469]

指出.NET Framework对app.config的作用不同,但它会针对每个请求从磁盘读取。 但是我很难相信,因为它会慢一些。 请告诉我他错了,否则我必须修复我编写的每个控制台/ Windows窗体/ Windows服务。

更新我很遗憾我误解了人们在上面链接的论坛中所说的内容。

trans by 2020-08-10T05:13:50Z

在C ++中使用接口会降低性能吗?

在C ++中使用接口(抽象基类)时,运行时性能会受到损失吗?

trans by 2020-08-10T03:59:33Z

不区分大小写的字符串从Python开始

这是我检查mystring是否以某些字符串开头的方式:

>>> mystring.lower().startswith("he")
True

问题是mystring很长(成千上万个字符),因此lower()操作要花费很多时间。

问题:有没有更有效的方法?

我失败的尝试:

>>> import re;
>>> mystring.startswith("he", re.I)
False
trans by 2020-08-09T21:17:20Z

高性能javascript中的对象池?

我正在编写一些JavaScript代码,这些代码需要快速运行,并使用许多短期对象。 我最好使用对象池,还是只是根据需要创建对象?

我写了一个JSPerf测试,该测试表明使用对象池没有任何好处,但是我不确定jsperf基准测试运行的时间是否足够长,足以启动浏览器的垃圾收集器。

该代码是游戏的一部分,因此我不关心旧版浏览器的支持。 我的图形引擎无论如何都无法在旧的浏览器上运行。

trans by 2020-08-09T18:13:23Z

为什么numpy.any在大型数组上这么慢?

我正在寻找确定是否大型阵列的最有效方法包含至少一个非零值。 乍看之下np.any看起来像显然是完成这项工作的工具,但在大型阵列上似乎出乎意料地缓慢。

考虑以下极端情况:

first = np.zeros(1E3,dtype=np.bool)
last = np.zeros(1E3,dtype=np.bool)

first[0] = True
last[-1] = True

# test 1
%timeit np.any(first)
>>> 100000 loops, best of 3: 6.36 us per loop

# test 2
%timeit np.any(last)
>>> 100000 loops, best of 3: 6.95 us per loop

至少np.all在这里似乎在做些明智的事情-如果非零值是数组中的第一个,应该没有必要考虑返回np.bool之前的其他任何项目,所以我希望测试1会稍微比测试更快2。

但是,当我们使数组更大时会发生什么呢?

first = np.zeros(1E9,dtype=np.bool)
last = np.zeros(1E9,dtype=np.bool)

first[0] = True
last[-1] = True

# test 3
%timeit np.any(first)
>>> 10 loops, best of 3: 21.6 ms per loop

# test 4
%timeit np.any(last)
>>> 1 loops, best of 3: 739 ms per loop

不出所料,测试4比测试3慢很多。但是,在测试3中np.all仍应只需要检查中的单个元素的值np.bool,以便知道它包含至少一个非零值。 为什么,那么,测试3是否比测试1慢得多?

编辑1:

我正在使用Numpy的开发版本(1.8.0.dev-e11cd9b),但是使用Numpy 1.7.1可以获得完全相同的计时结果。 我正在运行64位Linux,Python 2.7.4。 我的系统基本上处于闲置状态(我正在运行IPython会话,浏览器和文本编辑器),并且绝对不会出现问题。 我还将结果复制到另一台运行Numpy 1.7.1的计算机上。

编辑2:

使用Numpy 1.6.2时,测试1和3的时间均为〜1.85us,因此jorgeca表示在这方面,Numpy 1.6.2和1.7.1 1.7.0之间似乎存在一些性能下降。

编辑3:

遵循J.F. Sebastian和jorgeca的领导,我在零数组上使用np.all做了一些基准测试,这应该等效于在第一个元素为1的数组上调用np.bool

测试脚本:

import timeit
import numpy as np
print 'Numpy v%s' %np.version.full_version
stmt = "np.all(x)"
for ii in xrange(10):
    setup = "import numpy as np; x = np.zeros(%d,dtype=np.bool)" %(10**ii)
    timer = timeit.Timer(stmt,setup)
    n,r = 1,3
    t = np.min(timer.repeat(r,n))
    while t < 0.2:
        n *= 10
        t = np.min(timer.repeat(r,n))
    t /= n
    if t < 1E-3:
        timestr = "%1.3f us" %(t*1E6)
    elif t < 1:
        timestr = "%1.3f ms" %(t*1E3)
    else:
        timestr = "%1.3f s" %t
    print "Array size: 1E%i, %i loops, best of %i: %s/loop" %(ii,n,r,timestr)

结果:

Numpy v1.6.2
Array size: 1E0, 1000000 loops, best of 3: 1.738 us/loop
Array size: 1E1, 1000000 loops, best of 3: 1.845 us/loop
Array size: 1E2, 1000000 loops, best of 3: 1.862 us/loop
Array size: 1E3, 1000000 loops, best of 3: 1.858 us/loop
Array size: 1E4, 1000000 loops, best of 3: 1.864 us/loop
Array size: 1E5, 1000000 loops, best of 3: 1.882 us/loop
Array size: 1E6, 1000000 loops, best of 3: 1.866 us/loop
Array size: 1E7, 1000000 loops, best of 3: 1.853 us/loop
Array size: 1E8, 1000000 loops, best of 3: 1.860 us/loop
Array size: 1E9, 1000000 loops, best of 3: 1.854 us/loop

Numpy v1.7.0
Array size: 1E0, 100000 loops, best of 3: 5.881 us/loop
Array size: 1E1, 100000 loops, best of 3: 5.831 us/loop
Array size: 1E2, 100000 loops, best of 3: 5.924 us/loop
Array size: 1E3, 100000 loops, best of 3: 5.864 us/loop
Array size: 1E4, 100000 loops, best of 3: 5.997 us/loop
Array size: 1E5, 100000 loops, best of 3: 6.979 us/loop
Array size: 1E6, 100000 loops, best of 3: 17.196 us/loop
Array size: 1E7, 10000 loops, best of 3: 116.162 us/loop
Array size: 1E8, 1000 loops, best of 3: 1.112 ms/loop
Array size: 1E9, 100 loops, best of 3: 11.061 ms/loop

Numpy v1.7.1
Array size: 1E0, 100000 loops, best of 3: 6.216 us/loop
Array size: 1E1, 100000 loops, best of 3: 6.257 us/loop
Array size: 1E2, 100000 loops, best of 3: 6.318 us/loop
Array size: 1E3, 100000 loops, best of 3: 6.247 us/loop
Array size: 1E4, 100000 loops, best of 3: 6.492 us/loop
Array size: 1E5, 100000 loops, best of 3: 7.406 us/loop
Array size: 1E6, 100000 loops, best of 3: 17.426 us/loop
Array size: 1E7, 10000 loops, best of 3: 115.946 us/loop
Array size: 1E8, 1000 loops, best of 3: 1.102 ms/loop
Array size: 1E9, 100 loops, best of 3: 10.987 ms/loop

Numpy v1.8.0.dev-e11cd9b
Array size: 1E0, 100000 loops, best of 3: 6.357 us/loop
Array size: 1E1, 100000 loops, best of 3: 6.399 us/loop
Array size: 1E2, 100000 loops, best of 3: 6.425 us/loop
Array size: 1E3, 100000 loops, best of 3: 6.397 us/loop
Array size: 1E4, 100000 loops, best of 3: 6.596 us/loop
Array size: 1E5, 100000 loops, best of 3: 7.569 us/loop
Array size: 1E6, 100000 loops, best of 3: 17.445 us/loop
Array size: 1E7, 10000 loops, best of 3: 115.109 us/loop
Array size: 1E8, 1000 loops, best of 3: 1.094 ms/loop
Array size: 1E9, 100 loops, best of 3: 10.840 ms/loop

编辑4:

按照seberg的评论,我尝试使用np.all阵列而不是np.bool进行相同的测试。在这种情况下,随着数组大小的增加,Numpy 1.6.2也显示出速度下降:

Numpy v1.6.2
Array size: 1E0, 100000 loops, best of 3: 3.503 us/loop
Array size: 1E1, 100000 loops, best of 3: 3.597 us/loop
Array size: 1E2, 100000 loops, best of 3: 3.742 us/loop
Array size: 1E3, 100000 loops, best of 3: 4.745 us/loop
Array size: 1E4, 100000 loops, best of 3: 14.533 us/loop
Array size: 1E5, 10000 loops, best of 3: 112.463 us/loop
Array size: 1E6, 1000 loops, best of 3: 1.101 ms/loop
Array size: 1E7, 100 loops, best of 3: 11.724 ms/loop
Array size: 1E8, 10 loops, best of 3: 116.924 ms/loop
Array size: 1E9, 1 loops, best of 3: 1.168 s/loop

Numpy v1.7.1
Array size: 1E0, 100000 loops, best of 3: 6.548 us/loop
Array size: 1E1, 100000 loops, best of 3: 6.546 us/loop
Array size: 1E2, 100000 loops, best of 3: 6.804 us/loop
Array size: 1E3, 100000 loops, best of 3: 7.784 us/loop
Array size: 1E4, 100000 loops, best of 3: 17.946 us/loop
Array size: 1E5, 10000 loops, best of 3: 117.235 us/loop
Array size: 1E6, 1000 loops, best of 3: 1.096 ms/loop
Array size: 1E7, 100 loops, best of 3: 12.328 ms/loop
Array size: 1E8, 10 loops, best of 3: 118.431 ms/loop
Array size: 1E9, 1 loops, best of 3: 1.172 s/loop

为什么会发生这种情况? 与布尔型情况一样,np.all仍应只需要在返回前检查第一个元素,因此时间应保持不变。 数组大小。

trans by 2020-08-09T14:47:33Z

为什么添加局部变量使.NET代码

为什么注释掉for循环的前两行并取消注释第三行会导致42%的加速?

int count = 0;
for (uint i = 0; i < 1000000000; ++i) {
    var isMultipleOf16 = i % 16 == 0;
    count += isMultipleOf16 ? 1 : 0;
    //count += i % 16 == 0 ? 1 : 0;
}

时间的背后是截然不同的汇编代码:循环中的13条指令和7条指令。 该平台是运行.NET 4.0 x64的Windows 7。 启用代码优化,并且测试应用程序在VS2010外部运行。 [更新:Repro项目,对验证项目设置很有用。]

消除中间布尔值是一项基本的优化,这是我1980年代《龙书》中最简单的优化之一。 生成CIL或JIT x64机器代码时,如何不应用优化?

是否有“真正的编译器,请您优化此代码”开关? 我同情过早的优化类似于对金钱的热爱,但在尝试描述一个复杂的算法时却遇到了挫败感,这种算法的问题遍布整个例程。 您将在热点中工作,但是没有迹象表明可以通过手动调整编译器通常认为的正常工作范围来极大改善温暖的区域。 我当然希望我在这里想念一些东西。

更新:x86也会发生速度差异,但取决于实时编译方法的顺序。 请参阅为什么JIT订单会影响性能?

汇编代码(按要求):

    var isMultipleOf16 = i % 16 == 0;
00000037  mov         eax,edx 
00000039  and         eax,0Fh 
0000003c  xor         ecx,ecx 
0000003e  test        eax,eax 
00000040  sete        cl 
    count += isMultipleOf16 ? 1 : 0;
00000043  movzx       eax,cl 
00000046  test        eax,eax 
00000048  jne         0000000000000050 
0000004a  xor         eax,eax 
0000004c  jmp         0000000000000055 
0000004e  xchg        ax,ax 
00000050  mov         eax,1 
00000055  lea         r8d,[rbx+rax] 
    count += i % 16 == 0 ? 1 : 0;
00000037  mov         eax,ecx 
00000039  and         eax,0Fh 
0000003c  je          0000000000000042 
0000003e  xor         eax,eax 
00000040  jmp         0000000000000047 
00000042  mov         eax,1 
00000047  lea         edx,[rbx+rax] 
trans by 2020-08-09T05:42:13Z

javascript-为什么多维数据集比squ快

我这样写:

  var max = 0xffffff * 4;
  var step = 1 / max;
  function cube() {
    var result = 0.;
    for (var x = 0.; x < 1; x += step) {
      result += x * x * x;
    }
    return result;
  }
  function mul() {
    var result = 0.;
    for (var x = 0.; x < 1; x += step) {
      result += x * x;
    }
    return result;
  }
  function go() {
    var r = '';
    r += cube() + ' \n';
    r += mul() + ' \n';
    alert(r);
  }

并在Chrome分析器中查看结果:

mul: 106ms 
cube: 87ms

那怎么可能?

trans by 2020-08-07T07:05:58Z

NET中如何提高JSON反序列化速度? (JSON.net还是其他?)

我们正在考虑用JSON(WCF或其他)调用替换(一些或许多)“经典” SOAP XML WCF调用,因为其开销较低且易于直接在Javascript中使用。 现在,我们刚刚在Web服务中添加了一个额外的Json端点,并在某些操作中添加了WebInvoke属性并对其进行了测试。 使用C#.Net客户端或Javascript客户端,一切正常。 到目前为止,一切都很好。

但是,似乎将大JSON字符串反序列化为C#.Net中的对象比反序列化SOAP XML慢得多。 两者都使用DataContract和DataMember属性(完全相同的DTO)。 我的问题是:这是预期的吗? 我们可以做些什么来优化此性能? 还是我们应该仅针对较小的请求考虑JSON,而我们确实注意到性能有所提高。

到目前为止,我们已经选择了JSON.net进行此测试,即使在此测试用例中未显示它,也应该比.Net JSON序列化要快。 不知何故,ServiceStack反序列化根本不起作用(无错误,为IList返回null)。

为了进行测试,我们进行了服务呼叫以收集房间列表。 它返回一个GetRoomListResponse,并且在返回5个虚拟房间的情况下,JSON如下所示:

{"Acknowledge":1,"Code":0,"Message":null,"ValidateErrors":null,"Exception":null,"RoomList":[{"Description":"DummyRoom","Id":"205305e6-9f7b-4a6a-a1de-c5933a45cac0","Location":{"Code":"123","Description":"Location 123","Id":"4268dd65-100d-47c8-a7fe-ea8bf26a7282","Number":5}},{"Description":"DummyRoom","Id":"aad737f7-0caa-4574-9ca5-f39964d50f41","Location":{"Code":"123","Description":"Location 123","Id":"b0325ff4-c169-4b56-bc89-166d4c6d9eeb","Number":5}},{"Description":"DummyRoom","Id":"c8caef4b-e708-48b3-948f-7a5cdb6979ef","Location":{"Code":"123","Description":"Location 123","Id":"11b3f513-d17a-4a00-aebb-4d92ce3f9ae8","Number":5}},{"Description":"DummyRoom","Id":"71376c49-ec41-4b12-b5b9-afff7da882c8","Location":{"Code":"123","Description":"Location 123","Id":"1a188f13-3be6-4bde-96a0-ef5e0ae4e437","Number":5}},{"Description":"DummyRoom","Id":"b947a594-209e-4195-a2c8-86f20eb883c4","Location":{"Code":"123","Description":"Location 123","Id":"053e9969-d0ed-4623-8a84-d32499b5a8a8","Number":5}}]}

响应和DTO如下所示:

[DataContract(Namespace = "bla")]
public class GetRoomListResponse
{
    [DataMember]
    public IList<Room> RoomList;

    [DataMember]
    public string Exception;

    [DataMember]
    public AcknowledgeType Acknowledge = AcknowledgeType.Success;

    [DataMember]
    public string Message;

    [DataMember]
    public int Code;

    [DataMember]
    public IList<string> ValidateErrors;
}

[DataContract(Name = "Location", Namespace = "bla")]
public class Location
{
    [DataMember]
    public Guid Id { get; set; }

    [DataMember]
    public int Number { get; set; }

    [DataMember]
    public string Code { get; set; }

    [DataMember]
    public string Description { get; set; }
}

[DataContract(Name = "Room", Namespace = "bla")]
public class Room
{
    [DataMember]
    public Guid Id { get; set; }

    [DataMember]
    public string Description { get; set; }

    [DataMember]
    public Location Location { get; set; }
}

然后我们的测试代码如下:

    static void Main(string[] args)
    {
        SoapLogin();

        Console.WriteLine();

        SoapGetRoomList();
        SoapGetRoomList();
        SoapGetRoomList();
        SoapGetRoomList();
        SoapGetRoomList();
        SoapGetRoomList();
        SoapGetRoomList();

        Console.WriteLine();

        JsonDotNetGetRoomList();
        JsonDotNetGetRoomList();
        JsonDotNetGetRoomList();
        JsonDotNetGetRoomList();
        JsonDotNetGetRoomList();
        JsonDotNetGetRoomList();
        JsonDotNetGetRoomList();

        Console.ReadLine();
    }

    private static void SoapGetRoomList()
    {
        var request = new TestServiceReference.GetRoomListRequest()
        {
            Token = Token,
        };

        Stopwatch sw = Stopwatch.StartNew();

        using (var client = new TestServiceReference.WARPServiceClient())
        {
            TestServiceReference.GetRoomListResponse response = client.GetRoomList(request);
        }

        sw.Stop();
        Console.WriteLine("SOAP GetRoomList: " + sw.ElapsedMilliseconds);
    }

    private static void JsonDotNetGetRoomList()
    {
        var request = new GetRoomListRequest()
        {
            Token = Token,
        };

        Stopwatch sw = Stopwatch.StartNew();
        long deserializationMillis;

        using (WebClient client = new WebClient())
        {
            client.Headers["Content-type"] = "application/json";
            client.Encoding = Encoding.UTF8;

            string requestData = JsonConvert.SerializeObject(request, JsonSerializerSettings);

            var responseData = client.UploadString(GetRoomListAddress, requestData);

            Stopwatch sw2 = Stopwatch.StartNew();
            var response = JsonConvert.DeserializeObject<GetRoomListResponse>(responseData, JsonSerializerSettings);
            sw2.Stop();
            deserializationMillis = sw2.ElapsedMilliseconds;
        }

        sw.Stop();
        Console.WriteLine("JSON.Net GetRoomList: " + sw.ElapsedMilliseconds + " (deserialization time: " + deserializationMillis + ")");
    }

    private static JsonSerializerSettings JsonSerializerSettings
    {
        get
        {
            var serializerSettings = new JsonSerializerSettings();

            serializerSettings.CheckAdditionalContent = false;
            serializerSettings.ConstructorHandling = ConstructorHandling.Default;
            serializerSettings.DateFormatHandling = DateFormatHandling.MicrosoftDateFormat;
            serializerSettings.DefaultValueHandling = DefaultValueHandling.Ignore;
            serializerSettings.NullValueHandling = NullValueHandling.Ignore;
            serializerSettings.ObjectCreationHandling = ObjectCreationHandling.Replace;
            serializerSettings.PreserveReferencesHandling = PreserveReferencesHandling.None;
            serializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Error;

            return serializerSettings;
        }
    }

现在,我们以返回50、500和5000个房间的方式运行了该应用程序。 对象不是很复杂。

这些是结果; 时间以毫秒为单位:

50间客房:

SOAP GetRoomList: 37
SOAP GetRoomList: 5
SOAP GetRoomList: 4
SOAP GetRoomList: 4
SOAP GetRoomList: 9
SOAP GetRoomList: 5
SOAP GetRoomList: 5

JSON.Net GetRoomList: 289 (deserialization time: 91)
JSON.Net GetRoomList: 3 (deserialization time: 0)
JSON.Net GetRoomList: 2 (deserialization time: 0)
JSON.Net GetRoomList: 2 (deserialization time: 0)
JSON.Net GetRoomList: 2 (deserialization time: 0)
JSON.Net GetRoomList: 2 (deserialization time: 0)
JSON.Net GetRoomList: 2 (deserialization time: 0)

500间客房:

SOAP GetRoomList: 47
SOAP GetRoomList: 9
SOAP GetRoomList: 8
SOAP GetRoomList: 8
SOAP GetRoomList: 8
SOAP GetRoomList: 8
SOAP GetRoomList: 8

JSON.Net GetRoomList: 301 (deserialization time: 100)
JSON.Net GetRoomList: 12 (deserialization time: 8)
JSON.Net GetRoomList: 12 (deserialization time: 8)
JSON.Net GetRoomList: 12 (deserialization time: 8)
JSON.Net GetRoomList: 11 (deserialization time: 8)
JSON.Net GetRoomList: 11 (deserialization time: 8)
JSON.Net GetRoomList: 15 (deserialization time: 12)

5000间客房:

SOAP GetRoomList: 93
SOAP GetRoomList: 51
SOAP GetRoomList: 58
SOAP GetRoomList: 60
SOAP GetRoomList: 53
SOAP GetRoomList: 53
SOAP GetRoomList: 51

JSON.Net GetRoomList: 405 (deserialization time: 175)
JSON.Net GetRoomList: 107 (deserialization time: 79)
JSON.Net GetRoomList: 108 (deserialization time: 82)
JSON.Net GetRoomList: 112 (deserialization time: 85)
JSON.Net GetRoomList: 105 (deserialization time: 79)
JSON.Net GetRoomList: 111 (deserialization time: 81)
JSON.Net GetRoomList: 110 (deserialization time: 82)

我正在发布模式下运行该应用程序。 客户端和服务器都在同一台计算机上。 如您所见,与WCF SOAP使用的XML到对象的映射相比,使用JSON对许多(相同类型的)对象进行反序列化要花费更多的时间。 糟糕的是,反序列化比使用SOAP进行整个Web服务花费的时间更多。

对此有解释吗? XML(或WCF SOAP实现)在这方面是否提供了很大的优势,或者我可以在客户端进行任何更改(我宁愿不更改服务,但可以更改客户端DTO可以接受)以尝试 提高绩效? 感觉好像我已经在JSON.net端选择了一些设置,这些设置应该使其比默认设置更快,不是吗? 这里的瓶颈似乎是什么?

trans by 2020-08-06T09:16:37Z

优化-加速Python

这确实是两个问题,但它们是如此相似,为简单起见,我想将它们放在一起:

  • 首先:给定一个已建立的python项目,除了普通的代码内优化之外,还有哪些不错的方法来加速它?

  • 其次:用python从头开始编写程序时,有什么好的方法可以大大提高性能?

对于第一个问题,想像一下您已经交付了一个体面的项目,并且需要提高性能,但是您似乎无法通过重构/优化获得太多收益。 在这种情况下,如果不使用C之类的方式重写它,您将如何加速?

trans by 2020-08-06T08:37:04Z

性能-除了减少内存使用量之外,C#静态函数是否比非静态函数性能更好?

我假设staticpublic private目标必须减少内存使用量,原因是内存中只有一个静态目标副本。

似乎是因为方法是静态的,这可能使该方法成为CLR编译器进一步优化的潜在要点,这超出了使用非静态函数的可能性。 虽然只是一个脆弱的理论,所以我来问大家。

static publicprivate方法是否提供了减少内存使用量之外的任何其他性能优势?

(请注意:我对讨论过早优化问题的响应不感兴趣。当然,我每天都会遵循这样的合理建议,但这并不意味着有时不需要进行优化。(双重否定!)。让我沉迷于我 至少有好奇心)

trans by 2020-08-06T04:10:52Z

性能-低延迟,大规模消息排队

在Facebook应用程序和云计算时代,我对大型多人游戏进行了重新思考。

假设我要在现有开放协议的基础上构建一些东西,并且我想为1,000,000个同时播放器服务,以解决问题。

假设每个玩家都有一个传入消息队列(用于聊天和其他操作),并且平均而言,还有一个传入消息队列(行会,区域,实例,拍卖等),因此我们有2,000,000个队列。 玩家将一次收听1-10个队列。 每个队列平均每秒可能有1条消息,但是某些队列将具有更高的速率和更多的侦听器(例如,级别实例的“实体位置”队列)。 假设系统排队等待时间不超过100毫秒,对于轻度面向动作的游戏(但Quake或Unreal Tournament等游戏则不行)是可以的。

从其他系统来看,我知道在单个1U或刀片服务器上为10,000个用户提供服务是一个合理的期望(假设没有其他昂贵的活动在进行,例如物理模拟或其他)。

因此,在纵横制集群系统中,客户端连接到连接网关,而连接网关又连接到消息队列服务器,我们将获得100个网关计算机的每个网关10,000个用户,以及100个队列计算机的每个队列服务器20,000个消息队列。 再次,仅用于一般作用域。 每台MQ机器上的连接数将很少:大约100个,可以与每个网关进行通信。 网关上的连接数会更高:客户端为10,100 +与所有队列服务器的连接。 (最重要的是,添加一些用于游戏世界模拟服务器的连接或其他连接,但我现在暂时将其分开)

如果我不想从头开始构建它,则必须使用一些现有的消息传递和/或排队基础结构。 我可以找到的两个开放协议是AMQP和XMPP。 XMPP的预期用途有点类似于此游戏系统所需的用途,但是开销非常明显(XML,加上详细的状态数据,以及必须建立在其上的各种其他通道)。 AMQP的实际数据模型与我上面描述的更为接近,但是所有用户似乎都是大型企业型公司,并且工作负载似乎与工作流相关,而不与实时游戏更新相关。

是否有任何人可以分享这些技术或其实现的白天经验?

trans by 2020-08-06T02:54:15Z

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 下一页 共41页