我正在构建一个包含两个组件的应用程序-用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"
#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;
}
#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
,但仍然无效
由于@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毫秒,没有加速:(
我向Thrift Jira报告了一个问题
这是完全不科学的,但是使用带有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
该网站暗示清除媒介可能会改变容量:
[HTTP://恩.CPP reference.com/我/CPP/container/vector/clear]
许多实现不会在调用后释放分配的内存 清除(),有效地保留向量的容量() 不变。
但是根据@JamesKanze所说,这是错误的,明确的标准要求不会改变容量。
标准怎么说?
考虑以下代码,这是我的实际问题的SSCCE:
#include <iostream>
int roundtrip(int x)
{
return int(float(x));
}
int main()
{
int a = 2147483583;
int b = 2147483584;
std::cout << a << " -> " << roundtrip(a) << '\n';
std::cout << b << " -> " << roundtrip(b) << '\n';
}
我的计算机(Xubuntu 12.04.3 LTS)上的输出是:
2147483583 -> 2147483520
2147483584 -> -2147483648
请注意,正数b
在往返之后如何以负数结束。 这种行为是否有明确规定? 我本来希望从int到float的往返至少能够正确保留符号...
嗯,在ideone上,输出是不同的:
2147483583 -> 2147483520
2147483584 -> 2147483647
g ++小组是在同时修复了一个错误,还是两个输出都完全有效?
考虑:
template <typename T>
class Base
{
public:
static const bool ZEROFILL = true;
static const bool NO_ZEROFILL = false;
}
template <typename T>
class Derived : public Base<T>
{
public:
Derived( bool initZero = NO_ZEROFILL ); // NO_ZEROFILL is not visible
~Derived();
}
我无法使用GCC g ++ 3.4.4(cygwin)进行编译。
在将它们转换为类模板之前,它们是非泛型的,派生类能够查看基类的静态成员。 C ++规范的要求中是否存在这种可见性损失,还是我需要采用语法更改?
我了解到Base<T>
的每个实例都将具有其自己的静态成员“ ZEROFILL
”和“ NO_ZEROFILL
”,即Base<float>::ZEROFILL
和Base<double>::ZEROFILL
是不同的变量,但我并不在乎; 该常量用于代码的可读性。 我想使用静态常量,因为就名称冲突而言,这比使用宏或全局方法更安全。
我正在尝试使用模板类链接到共享库,但这给了我“未定义符号”错误。 我将问题压缩为大约20行代码。
共享的
template <class Type> class myclass {
Type x;
public:
myclass() { x=0; }
void setx(Type y);
Type getx();
};
共享的
#include "shared.h"
template <class Type> void myclass<Type>::setx(Type y) { x = y; }
template <class Type> Type myclass<Type>::getx() { return x; }
main.cpp
#include <iostream>
#include "shared.h"
using namespace std;
int main(int argc, char *argv[]) {
myclass<int> m;
cout << m.getx() << endl;
m.setx(10);
cout << m.getx() << endl;
return 0;
}
这是我编译库的方式:
g++ -fPIC -c shared.cpp -o shared.o
g++ -dynamiclib -Wl,-dylib_install_name -Wl,libshared.dylib -o libshared.dylib shared.o
和主程序:
g++ -c main.cpp
g++ -o main main.o -L. -lshared
仅得到以下错误:
Undefined symbols:
"myclass<int>::getx()", referenced from:
_main in main.o
_main in main.o
"myclass<int>::setx(int)", referenced from:
_main in main.o
如果我删除shared.h/cpp
中的“模板”内容,并仅用“整数”替换它们,那么一切正常。 另外,如果我只将模板类代码复制并粘贴到main.cpp
中,并且不链接到共享库,那么一切也将正常运行。
如何获得这样的模板类以通过共享库工作?
我将MacOS 10.5和GCC 4.0.1一起使用。
我已经阅读了很多有关C ++类的教程,但是他们错过了其他教程包括的内容。
有人可以告诉我如何编写和使用一个非常简单的C ++类,该类使用可见性,方法以及简单的构造函数和析构函数吗?
我最近完成了一堆Java编码,并且已经习惯了非常特定的软件包命名系统,例如深度嵌套。 com.company.project.db
。在Java,AS3 / Flex和C#中运行正常。 我也曾经在C ++中看到过相同的范例,但是我也听说将C ++名称空间视为Java包的直接对应对象是很不好的。
是真的,为什么? 名称空间/程序包有何相似之处和不同之处? 如果您使用深层嵌套的名称空间,可能会出现什么问题?
据我了解,Visual Studio 2015附带有clang。 首先,我虽然这仅适用于Android和iOS应用程序,但是根据本文的介绍,对于Windows程序,也应该可以使用clang ++前端。 但是,我找不到相应的选项。
所以,请您向我解释一下,如何在c ++项目中(在VS2015 RC Community Edition中)将使用的编译器更改为clang。
对于一组异常类,什么是好的设计?
我看到了关于哪些异常类应该和不应该做什么的各种内容,但是没有一个简单的设计可以轻松地使用和扩展这些功能。
使1和4一起工作是我面临的最大问题,因为任何格式和文件输出方法都可能会失败。
编辑:因此,在几个类别中查看了异常类以及与Neil关联的问题之后,似乎完全不考虑项目1(因此忽略了提升建议)似乎是一种惯例,这对我来说似乎是个坏主意。
无论如何,我以为我也会发布我正在考虑使用的异常类。
class Exception : public std::exception
{
public:
// Enum for each exception type, which can also be used
// to determine the exception class, useful for logging
// or other localisation methods for generating a
// message of some sort.
enum ExceptionType
{
// Shouldn't ever be thrown
UNKNOWN_EXCEPTION = 0,
// The same as above, but it has a string that
// may provide some information
UNKNOWN_EXCEPTION_STR,
// For example, file not found
FILE_OPEN_ERROR,
// Lexical cast type error
TYPE_PARSE_ERROR,
// NOTE: in many cases functions only check and
// throw this in debug
INVALID_ARG,
// An error occured while trying to parse
// data from a file
FILE_PARSE_ERROR,
}
virtual ExceptionType getExceptionType()const throw()
{
return UNKNOWN_EXCEPTION;
}
virtual const char* what()throw(){return "UNKNOWN_EXCEPTION";}
};
class FileOpenError : public Exception
{
public:
enum Reason
{
FILE_NOT_FOUND,
LOCKED,
DOES_NOT_EXIST,
ACCESS_DENIED
};
FileOpenError(Reason reason, const char *file, const char *dir)throw();
Reason getReason()const throw();
const char* getFile()const throw();
const char* getDir ()const throw();
private:
Reason reason;
static const unsigned FILE_LEN = 256;
static const unsigned DIR_LEN = 256;
char file[FILE_LEN], dir[DIR_LEN];
};
由于所有字符串都通过复制到内部固定大小的缓冲区中进行处理(如果需要则截断,但始终以null终止)来处理点1。
尽管这没有解决第3点,但是我认为无论如何在现实世界中该点的使用都很有限,如果有必要,可以通过抛出新的异常来解决。
我已将“ cin”重定向为从文件流中读取cin.rdbug(inF.rdbug())
当我使用提取运算符时,它会一直读取直到到达空白字符。
是否可以使用其他定界符? 我通过cplusplus.com中的api,但没有找到任何东西。
该代码可使用Visual C ++ 11进行编译,并可以在Windows 7上按预期运行,但是无法使用Windows 7上的MinGW 4.7.0或Linux上的gcc 4.8.0进行编译。 编译为-std=c++11
标志
#include <codecvt>
#include <string>
// convert UTF-8 string to wstring
std::wstring utf8_to_wstring (const std::string& str)
{
std::wstring_convert<std::codecvt_utf8<wchar_t>> myconv;
return myconv.from_bytes(str);
}
// convert wstring to UTF-8 string
std::string wstring_to_utf8 (const std::wstring& str)
{
std::wstring_convert<std::codecvt_utf8<wchar_t>> myconv;
return myconv.to_bytes(str);
}
错误:
codecvt:没有这样的文件或目录。
我有一个共享库,希望将其链接为使用GCC的可执行文件。 共享库具有非标准名称,其格式不是libNAME.so,因此我不能使用通常的-l选项。 (它碰巧也是Python扩展,因此没有“ lib”前缀。)
我能够将库文件的路径直接传递给链接命令行,但这会导致库路径被硬编码到可执行文件中。
例如:
g++ -o build/bin/myapp build/bin/_mylib.so
有没有一种方法可以链接到该库而不会导致路径被硬编码到可执行文件中?
首先,我知道这个问题遍及整个网站,但我已经查看了几乎所有问题,似乎无法找出问题所在。 这是VS2012。谢谢。
//Socket.h
#pragma once
#include <iostream>
#include <WinSock2.h>
using namespace std;
const int STRLEN = 256;
class Socket
{
protected:
WSADATA wsaData;
SOCKET mySocket;
SOCKET myBackup;
SOCKET acceptSocket;
sockaddr_in myAddress;
public:
Socket();
~Socket();
bool SendData( char* );
bool RecvData( char*, int );
void CloseConnection();
void GetAndSendMessage();
};
class ServerSocket : public Socket
{
public:
void Listen();
void Bind( int port );
void StartHosting( int port );
};
class ClientSocket : public Socket
{
public:
void ConnectToServer( const char *ipAddress, int port );
};
这是Socket.cpp
//Socket.cpp
#include "stdafx.h"
#include "Socket.h"
Socket::Socket()
{
if( WSAStartup( MAKEWORD(2, 2), &wsaData ) != NO_ERROR )
{
cerr<<"Socket Initialization: Error with WSAStartup\n";
system("pause");
WSACleanup();
exit(10);
}
//Create a socket
mySocket = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
if ( mySocket == INVALID_SOCKET )
{
cerr<<"Socket Initialization: Error creating socket"<<endl;
system("pause");
WSACleanup();
exit(11);
}
myBackup = mySocket;
}
Socket::~Socket()
{
WSACleanup();
}
bool Socket::SendData( char *buffer )
{
send( mySocket, buffer, strlen( buffer ), 0 );
return true;
}
bool Socket::RecvData( char *buffer, int size )
{
int i = recv( mySocket, buffer, size, 0 );
buffer[i] = '\0';
return true;
}
void Socket::CloseConnection()
{
//cout<<"CLOSE CONNECTION"<<endl;
closesocket( mySocket );
mySocket = myBackup;
}
void Socket::GetAndSendMessage()
{
char message[STRLEN];
cin.ignore();//without this, it gets the return char from the last cin and ignores the following one!
cout<<"Send > ";
cin.get( message, STRLEN );
SendData( message );
}
void ServerSocket::StartHosting( int port )
{
Bind( port );
Listen();
}
void ServerSocket::Listen()
{
//cout<<"LISTEN FOR CLIENT..."<<endl;
if ( listen ( mySocket, 1 ) == SOCKET_ERROR )
{
cerr<<"ServerSocket: Error listening on socket\n";
system("pause");
WSACleanup();
exit(15);
}
//cout<<"ACCEPT CONNECTION..."<<endl;
acceptSocket = accept( myBackup, NULL, NULL );
while ( acceptSocket == SOCKET_ERROR )
{
acceptSocket = accept( myBackup, NULL, NULL );
}
mySocket = acceptSocket;
}
void ServerSocket::Bind( int port )
{
myAddress.sin_family = AF_INET;
myAddress.sin_addr.s_addr = inet_addr( "0.0.0.0" );
myAddress.sin_port = htons( port );
//cout<<"BIND TO PORT "<<port<<endl;
if ( bind ( mySocket, (SOCKADDR*) &myAddress, sizeof( myAddress) ) == SOCKET_ERROR )
{
cerr<<"ServerSocket: Failed to connect\n";
system("pause");
WSACleanup();
exit(14);
}
}
void ClientSocket::ConnectToServer( const char *ipAddress, int port )
{
myAddress.sin_family = AF_INET;
myAddress.sin_addr.s_addr = inet_addr( ipAddress );
myAddress.sin_port = htons( port );
//cout<<"CONNECTED"<<endl;
if ( connect( mySocket, (SOCKADDR*) &myAddress, sizeof( myAddress ) ) == SOCKET_ERROR )
{
cerr<<"ClientSocket: Failed to connect\n";
system("pause");
WSACleanup();
exit(13);
}
}
这是stdafx.h
#pragma once
#include "targetver.h"
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
// Windows Header Files:
#include <windows.h>
// C RunTime Header Files
#include <stdlib.h>
#include <malloc.h>
#include <memory.h>
#include <tchar.h>
// TODO: reference additional headers your program requires here
#include "Socket.h"
这是我的错误消息:
1>------ Build started: Project: Client, Configuration: Debug Win32 ------
1> stdafx.cpp
1> Socket.cpp
1> Client.cpp
1> Generating Code...
1>Socket.obj : error LNK2019: unresolved external symbol __imp__accept@12 referenced in function "public: void __thiscall ServerSocket::Listen(void)" (?Listen@ServerSocket@@QAEXXZ)
1>Socket.obj : error LNK2019: unresolved external symbol __imp__bind@12 referenced in function "public: void __thiscall ServerSocket::Bind(int)" (?Bind@ServerSocket@@QAEXH@Z)
1>Socket.obj : error LNK2019: unresolved external symbol __imp__closesocket@4 referenced in function "public: void __thiscall Socket::CloseConnection(void)" (?CloseConnection@Socket@@QAEXXZ)
1>Socket.obj : error LNK2019: unresolved external symbol __imp__connect@12 referenced in function "public: void __thiscall ClientSocket::ConnectToServer(char const *,int)" (?ConnectToServer@ClientSocket@@QAEXPBDH@Z)
1>Socket.obj : error LNK2019: unresolved external symbol __imp__htons@4 referenced in function "public: void __thiscall ServerSocket::Bind(int)" (?Bind@ServerSocket@@QAEXH@Z)
1>Socket.obj : error LNK2019: unresolved external symbol __imp__inet_addr@4 referenced in function "public: void __thiscall ServerSocket::Bind(int)" (?Bind@ServerSocket@@QAEXH@Z)
1>Socket.obj : error LNK2019: unresolved external symbol __imp__listen@8 referenced in function "public: void __thiscall ServerSocket::Listen(void)" (?Listen@ServerSocket@@QAEXXZ)
1>Socket.obj : error LNK2019: unresolved external symbol __imp__recv@16 referenced in function "public: bool __thiscall Socket::RecvData(char *,int)" (?RecvData@Socket@@QAE_NPADH@Z)
1>Socket.obj : error LNK2019: unresolved external symbol __imp__send@16 referenced in function "public: bool __thiscall Socket::SendData(char *)" (?SendData@Socket@@QAE_NPAD@Z)
1>Socket.obj : error LNK2019: unresolved external symbol __imp__socket@12 referenced in function "public: __thiscall Socket::Socket(void)" (??0Socket@@QAE@XZ)
1>Socket.obj : error LNK2019: unresolved external symbol __imp__WSAStartup@8 referenced in function "public: __thiscall Socket::Socket(void)" (??0Socket@@QAE@XZ)
1>Socket.obj : error LNK2019: unresolved external symbol __imp__WSACleanup@0 referenced in function "public: __thiscall Socket::Socket(void)" (??0Socket@@QAE@XZ)
1>C:\Users\ajayp_000\documents\visual studio 2012\Projects\Client\Debug\Client.exe : fatal error LNK1120: 12 unresolved externals
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
到目前为止,我在项目中使用的是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;
}
我正在尝试学习C ++,并试图了解返回的对象。 我似乎看到了这样做的两种方法,并且需要了解什么是最佳实践。
选项1:
QList<Weight *> ret;
Weight *weight = new Weight(cname, "Weight");
ret.append(weight);
ret.append(c);
return &ret;
选项2:
QList<Weight *> *ret = new QList();
Weight *weight = new Weight(cname, "Weight");
ret->append(weight);
ret->append(c);
return ret;
(当然,我也可能不理解这一点)。
哪种方法被认为是最佳实践,应该遵循什么方法?
我的项目中有2个文件夹“ inc”和“ lib”,分别具有标题和静态库。 我如何告诉cmake将这两个目录分别用于include和link?
可能重复:
未命名/匿名名称空间与静态函数
我碰到了这段代码
namespace ABC {
namespace DEF {
namespace
{
我希望名称空间后面应加上一些名称,但此代码并非如此。
C ++允许吗? 这个未命名的命名空间有什么优势?
下面是访问实例的受保护字段x的一个细微示例。B是A的子类,因此任何类型B的变量也都是类型A。为什么B :: foo()可以访问b的x字段,而不能访问a的x字段?
class A {
protected:
int x;
};
class B : public A {
protected:
A *a;
B *b;
public:
void foo() {
int u = x; // OK : accessing inherited protected field x
int v = b->x; // OK : accessing b's protected field x
int w = a->x; // ERROR : accessing a's protected field x
}
};
这是我用g ++遇到的错误
$ g++ -c A.cpp
A.cpp: In member function ‘void B::foo()’:
A.cpp:3: error: ‘int A::x’ is protected
A.cpp:14: error: within this context
我不知道为什么我的一个项目的VDSERR.h列在“外部依赖项”下,而另一个却没有,并给我一个关于其中定义的符号的“未定义符号”编译器错误。 如何将这个文件也包含在其他项目中? (可能是通过拖放操作,但是我想在这里知道确切的设置。)
可能重复:
C ++中的指针变量和引用变量之间有什么区别?
这使我感到困惑:
class CDummy
{
public:
int isitme (CDummy& param);
};
int CDummy::isitme (CDummy& param)
{
if (¶m == this)
{
return true; //ampersand sign on left side??
}
else
{
return false;
}
}
int main ()
{
CDummy a;
CDummy* b = &a;
if ( b->isitme(a) )
{
cout << "yes, &a is b";
}
return 0;
}
在C中,通常表示var的地址。 这是什么意思? 这是一种精美的指针表示方式吗?
我之所以假设它是一个指针符号,是因为毕竟这是一个指针,我们正在检查两个指针是否相等。
我正在cplusplus.com上学习,他们有这个示例。