.net 환경 에서 크로스 프로 세 스,고주파 읽 기와 쓰기 데이터 에 대한 문제
11904 단어 .net프로 세 스읽 기와 쓰기 데이터
1.최근 프로젝트 는 고주파 로 데 이 터 를 읽 고 쓰 도록 요구 하고 데이터 의 양도 크 지 않 으 며 다 중 표 는 모두 백만 개의 상하 에 있 습 니 다.
표 가 가장 큰 것 도 25 만 정도 인 데 역사 데이터 표 는 언급 되 지 않 기 때문에 고려 할 필요 가 없다.
어 려 운 점 은 이 규모 의 핫 이 슈 데이터 로 변화 가 매우 빈번 하 다 는 점 이다.
데 이 터 는 일부 검 측 장치 의 수집 데이터 에서 기원 되 고 일부 큰 표 는 짧 은 시간 안에(예 를 들 어 몇 초)대부분 변화 할 수 있 습 니 다.
또한 메 인 프로그램 도 일부 백 스테이지 서 비 스 는 계속 문의 하고 특정한 유형의 장 치 를 읽 고 써 야 하기 때문에 정보 교환 시간 이 가능 한 한 짧 아야 한다.
2.이전의 해결 방안 은 모든 핫 이 슈 데 이 터 를 공유 메모리 에 통일 적 으로 불 러 오고 지탱 할 수 있 는(밀리초 단위)까지 불 러 오 는 것 이 었 으 나 시스템 구조 업그레이드 로 인해 이전의 프로그램(20 년 전의)은 호 환 되 지 않 았 습 니 다.
하나만 다시 쓸 수 있 습 니 다.가장 먼저 생각 나 는 것 은 redis 입 니 다.그 당시 에 모든 API 를 다시 쓴 후에 테스트 를 통 해 효율 이 안 되 는 것 을 발 견 했 습 니 다.네,잘못 보지 않 았 습 니 다.redis 도 사용 범위 가 있 습 니 다.
3.redis 읽 기와 쓰기 가 매우 빠 르 지만 대량의 읽 기와 쓰기 작업 에 대해 저 는 지원 이 부족 하 다 고 생각 합 니 다.redis 는 대량 읽 기와 쓰 기 를 지원 하지만 효율 이 빠 르 지 않 습 니 다.
문자열(string)형식의 대량 읽 기와 쓰기 에 대해 테스트 한 적 이 있 습 니 다.효율 이 비교적 좋 은 것 은 매번 200~250 개 사이 에 20 만 개의 데 이 터 를 처리 하 는 데 5 초 정도 걸린다.(PC 기기,8G,4 핵)
그리고 질서 있 는 집합(sorted set)유형 에 대해 대량으로 쓰 는 작업 은 매우 어색 하고 API 를 수정 하지 않 았 습 니 다.(다른 방식 이 있 으 면 가르쳐 주 십시오)저 는 테스트 한 적 이 있 습 니 다.효율 은 string 형식 만큼 높 지 않 습 니 다.
다른 유형 은 나의 업무 장면 에 적합 하지 않 아서 사용 할 생각 을 하지 않 았 다.
4.그래서 프로젝트 팀 은 마지막 으로 공유 메모리 로 사용 하기 로 결 정 했 습 니 다.먼저.net 환경 에서 c\#공유 메모 리 를 사용 하기 로 결 정 했 습 니 다.이 기능 은 사용 할 수 있 는 사람 이 많 지 않 습 니 다.사실은.net 4.0 버 전에 이미 통합 되 었 습 니 다.
System.IO.Memory Mapped File 네 임 스페이스 에서이 라 이브 러 리 는 어 이 없 게 한다.안에 쓸 수 있 는 것 은 Write,read 두 가지 방법 뿐 이 고 바이트 에 대한 조작 이기 때문이다.
아주 많은 타 입 전환 이 필요 합 니 다.귀 찮 습 니 다!바이트 단위 로 백만 급 데 이 터 를 저장 해 야 하 는 메모리 데이터 베 이 스 를 구축 하 는 것 이 얼마나 번 거 로 운 지 생각해 보 세 요.
색인 기능 을 수 동 으로 해결 해 야 합 니 다.각종 조 회 를 지원 해 야 하기 때문에 마지막 으로 하루 동안 DEMO 를 썼 습 니 다.마지막 으로 테스트 한 결과 효율 이 크게 향상 되 지 않 았 습 니 다.그 당시 에 상호 배척 테스트 를 추 가 했 기 때 문 입 니 다.
하지만 밀리초 급 차 는 멀다.이 기술 에 관심 이 있 는 것 은 정원 에 있다 는 것 을 알 수 있다.예 를 들 어:https://www.cnblogs.com/zeroone/archive/2012/04/18/2454776.html
2.맞아요.1 절 은 너무 많이 썼어 요.
1.마지막 으로 분석 하면 이것 은 c\#언어의 병목 이 어야 한다.c\#이런 소란 조작 에 대해 그리 성숙 하지 않다.
2.마지막 으로 겨냥 하여 VC 를 사용 하여 dll 을 개발 하고 그 안에 메모리 데이터 에 대한 읽 기와 쓰기 기능 을 패키지 한 다음 c\#호출 하기 로 결정 합 니 다.
3.본인 의 C,C++가 그리 익숙 하지 않 고 사례 를 참고 했다.예 를 들 어 정원 안의:http://www.cnblogs.com/cwbcwb505/archive/2008/12/08/1350505.html
4.네,잘못 보지 않 았 습 니 다.2008 년 에 저 는 더 빠 른 것 을 보 았 습 니 다.보아하니 바 텀 개발 C,C++가 그렇게 오래 지속 되 고 쇠퇴 하지 않 는 것 은 이치 에 맞지 않 는 것 이 아니 라 많은 기술 이 지금 사용 되 고 있 는 것 같 습 니 다.
5.공유 메모리 가 무엇 인지 봅 시다.
3.코드 쓰기 시 작 했 어 요.
1.먼저 2 개의 콘 솔 프로젝트 를 구축 하고 MFC 를 지원 합 니 다.
2.먼저 이렇게:공유 메모 리 를 만 들 고 데 이 터 를 초기 화 합 니 다.
3.다시 이렇게:읽 기와 쓰기 데이터 테스트,마지막 수정
4.마지막 으로 그림 의 디 테 일 을 수정 하고 테스트 하 며 효 과 를 봅 니 다.
5.완 성 했 습 니 다.see,쉽 지 않 나 요?다 알 아 요?
4.정말 코드 를 붙 여 야 겠 어 요.
1.매 거 진 반환 상 태 를 정의 합 니 다.
typedef enum
{
Success = 0,
AlreadyExists = 1,
Error = 2,
OverSize = 3
}enumMemory;
2.테스트 에 사용 할 구조 체 를 다시 정의 합 니 다.
typedef struct
{
int TagID;
char TagName[32];
int Area;
double EngVal;
double UpdateTime;
double RawMax;
double RawMin;
double RawVal;
char Name[50];
char Al;
double ASTime;
char MaskState;
double AMTime;
char Cf;
char Tdf;
char AlarmCode[32];
}TENG;
3.공유 메모리 생 성 시작
int Create(UINT size)
{
// Data
HANDLE fileMap = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, size, “Name”);
if (fileMap == NULL || fileMap == INVALID_HANDLE_VALUE)
return Error;
if (GetLastError() == ERROR_ALREADY_EXISTS)
return AlreadyExists;
// init
void *mapView = MapViewOfFile(fileMap, FILE_MAP_WRITE, 0, 0, size);
if (mapView == NULL)
return Error;
else
memset(mapView, 0, size);
return Success;
}
4.다시 데 이 터 를 쓰기 시작 합 니 다.
int Write(void *pDate, UINT nSize, UINT offset)
{
// open
HANDLE fileMap = OpenFileMapping(FILE_MAP_WRITE, FALSE, “Name”);
if (fileMap == NULL)
return Error;
// hander
void *mapView = MapViewOfFile(fileMap, FILE_MAP_WRITE, 0, 0, nSize);
if (mapView == NULL)
return Error;
else
WriteDataPtr = mapView;
// write
memcpy(mapView, pDate, nSize);
UnmapViewOfFile(pMapView);
return Success;
}
5.데이터 읽 기 시작
int Read(void *pData, UINT nSize, UINT offset)
{
// open
HANDLE fileMap = OpenFileMapping(FILE_MAP_READ, FALSE, GetTableName());
if (fileMap == NULL)
return Error;
// hander
void *pMapView = MapViewOfFile(fileMap, FILE_MAP_READ, 0, 0, nSize);
if (pMapView == NULL)
return Error;
else
ReadDataPtr = pMapView;
memcpy(pData, (pMapView, nSize);
UnmapViewOfFile(pMapView);
return Success;
}
6.OK,복잡 하지 않 습 니 다.인터넷 에 이런 자료 가 있 습 니 다.마지막 으로 우 리 는 테스트 프로그램 을 붙 입 니 다.
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
int length = 100000;
CEng * ceng = new CEng();
DWORD dwStart = GetTickCount();
for (int i = 0; i < length; i++) {
TENG eng;
ceng->Read(&eng, ceng->size, ceng->size * i);
eng.EngVal = i;
ceng->Write(&eng, ceng->size, (i*ceng->size));
if (i % 10000 == 0 || i == length - 1)
printf(" Eng.TagName:%s
", eng.TagName);
}
printf(" %d, :%d
", length, GetTickCount() - dwStart);
//
TENG eng5000;
ceng->Read(&eng5000, ceng->size, ceng->size * 5000);
printf("
");
printf(" 5000 Eng TagID:%d, EngVal:%lf
", eng5000.TagID, eng5000.EngVal);
scanf_s(" ");
return 0;
}
7.테스트 프로그램 도 작성
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
int length = 100000;
CEng * ceng = new CEng();
ceng->Create(ceng->size * length);
DWORD dwStart = GetTickCount();
for (int i = 0; i < length; i++)
{
TENG eng;
memset(&eng, 0, ceng->size);
eng.TagID = i;
sprintf_s(eng.AlarmCode, "AlarmCode.%d", i);
sprintf_s(eng.TagName, "TagName.%d", i);
if (i % 10000 == 0 || i == length - 1)
printf(" Eng.TagName:%s
", eng.TagName);
ceng->Write(&eng, ceng->size, (i*ceng->size));
}
// print time
printf(" , :%d
", length);
printf(" :%d
", GetTickCount() - dwStart);
scanf_s(" ");
return 0;
}
8、다시 붙 여야 지5.DLL 만 드 는 걸 깜빡 할 뻔 했 어 요.
1.외부 함수 정의
extern "C" __declspec(dllexport) int ReadFromSharedMemory(TENG *pData, int nSize, int offset)
{
return ceng->Read(pData, nSize, offset);
}
extern "C" __declspec(dllexport) int WriteToSharedMemory(void *pData, int nSize, int offset)
{
return ceng->Write(pData, nSize, offset);
}
2.자,VC 는 여기까지 입 니 다.도시락 을 받 으 러 가도 됩 니 다.c\#입장
public class Lib
{
[DllImport("ConsoleApplication4.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int ReadFromSharedMemory(IntPtr pData, int nSize, int offset);
[DllImport("ConsoleApplication4.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int WriteToSharedMemory(IntPtr pData, int nSize, int offset);
}
3,c\#테스트
static void Main(string[] args)
{
var length = 100000;
var startTime = DateTime.Now;
var size = Marshal.SizeOf(typeof(TEng));
var intPtrOut = Marshal.AllocHGlobal(size);
var intPtrIn = Marshal.AllocHGlobal(size);
for (var i = 0; i < length; i++)
{
Lib.ReadFromSharedMemory(intPtrOut, size, size * i);
var eng = Marshal.PtrToStructure<TEng>(intPtrOut);
eng.EngVal = i;
Marshal.StructureToPtr(eng, intPtrIn, true);
Lib.WriteToSharedMemory(intPtrIn, size, size * i);
if (i % 10000 == 0)
Console.WriteLine("eng.TagID:{0}", eng.TagID);
}
Console.WriteLine(" {0}, :{1} ", length.ToString(),
(DateTime.Now - startTime).TotalMilliseconds.ToString());
//
var intPtr100 = Marshal.AllocHGlobal(size);
Lib.ReadFromSharedMemory(intPtr100, size, size * 100);
var eng100 = Marshal.PtrToStructure<TEng>(intPtr100);
Console.WriteLine();
Console.WriteLine(" ");
Console.WriteLine(" 100 Eng TagID:{0},EngVal:{1}", eng100.TagID, eng100.EngVal);
Console.ReadKey();
}
4.165 밀리초 로 VC 에서 운행 하 는 것 에 비해 수량 급 이 부족 하지만 괜 찮 습 니 다.
c\#환경 에서 끊 임 없 는 Marshal.PtrToStructure,Marshal.structureToPtr 가 필요 하기 때문에 데 이 터 를 위탁 관리 메모리 유 공유 메모리 사이 로 자주 옮 깁 니 다.
시간 이 필요 합 니 다.더 좋 은 처리 방법 이 있 습 니 다.가르쳐 주세요.
6.크로스 스 레 드,프로 세 스 때문에 상호 배척 량 을 고려 해 야 합 니 다.
1.아주 간단 합 니 다.MFC 에 기 존의 CMutex 가 있 는데 Write 에 넣 어서 효율 을 봅 니 다.
상호 배척 량 은 자원 을 소모 해 야 하 며,100 밀리초 가 더 들 어 갈 것 이다.
2.읽 기와 쓰기 에 서로 배척 하 는 양 을 더 해 보 자.
80 여 밀리초 가 더 많아 졌 습 니 다.
물고기 와 곰 발바닥 을 동시에 가 질 수 는 없 잖 아.실제 운용 장면 에 근거 하여 상호 반 론 량 을 더 해 야 한다 고 생각해 야 한다.
자,사람들 이 51 번 놀 러 갔 는데 저 는 집에 서 프로그램 을 만 들 었 습 니 다.이 를 통 해 제 취미 가 높 은 것 을 알 수 있 습 니 다.목욕,빨래,그리고 밥 을 먹 으 러 갔 고 하루 종일 음식 을 먹 지 않 았 습 니 다.
이상 은.net 환경 에서 크로스 프로 세 스,고주파 읽 기 쓰기 데이터 에 대한 상세 한 내용 입 니 다.더 많은.net 크로스 프로 세 스 고주파 읽 기 쓰기 데이터 에 관 한 자 료 는 우리 의 다른 관련 글 에 관심 을 가 져 주 십시오!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
AS를 통한 Module 개발1. ModuleLoader 사용 2. IModuleInfo 사용 ASModuleOne 모듈...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.