浏览代码

ft: 优化

master
SisMaker 1年前
父节点
当前提交
61290d4cf3
共有 3 个文件被更改,包括 60 次插入183 次删除
  1. +2
    -3
      README.md
  2. +53
    -179
      c_src/eNifLock/eNifLock.cc
  3. +5
    -1
      src/eCLock.erl

+ 2
- 3
README.md 查看文件

@ -11,6 +11,5 @@ Build
说明
----
eALock 基于atmoics
eCLock 基于c11 atomic
两者性能基本一致
eCLock 基于c++11 atomic

+ 53
- 179
c_src/eNifLock/eNifLock.cc 查看文件

@ -1,14 +1,8 @@
#include "erl_nif.h"
#include <atomic>
#include <forward_list>
#include <list>
#include <set>
#include <map>
#include <unordered_set>
using namespace std;
const int LockSize = 2097152;
const int ScheduleCnt = 50;
const int HashSalt = 786234121;
atomic<uint64_t> LockSlot[LockSize];
@ -16,24 +10,32 @@ ERL_NIF_TERM atomTrue;
ERL_NIF_TERM atomFalse;
ERL_NIF_TERM atomUndefined;
int nifLoad(ErlNifEnv *env, void **priv_data, ERL_NIF_TERM)
typedef struct KeyNode_r
{
atomTrue = enif_make_atom(env, "true");
atomFalse = enif_make_atom(env, "false");
atomUndefined = enif_make_atom(env, "undefined");
return 0;
}
int KeyIx;
struct KeyNode_r *next;
} KeyNode;
bool isNotCurLocked(forward_list<int> *locked, int KeyIx)
bool isNotLocked(KeyNode *LockedHead, int KeyIx)
{
for (auto it : *locked)
KeyNode *temp = LockedHead;
while (temp != NULL)
{
if (it == KeyIx)
if (temp->KeyIx == KeyIx)
return false;
temp = temp->next;
}
return true;
}
int nifLoad(ErlNifEnv *env, void **priv_data, ERL_NIF_TERM)
{
atomTrue = enif_make_atom(env, "true");
atomFalse = enif_make_atom(env, "false");
atomUndefined = enif_make_atom(env, "undefined");
return 0;
}
bool lockOne(ErlNifEnv *env, ErlNifPid *ThePid, int KeyIx, uint64_t Val)
{
uint64_t Expected = 0;
@ -62,179 +64,65 @@ bool lockOne(ErlNifEnv *env, ErlNifPid *ThePid, int KeyIx, uint64_t Val)
}
}
ERL_NIF_TERM tryLockSchedule(ErlNifEnv *env, int, const ERL_NIF_TERM argv[])
{
//enif_fprintf(stdout, "IMY************tryLocksSchedule00 %T \n", argv[0]);
set<int> locked;
ERL_NIF_TERM allList = argv[1];
ERL_NIF_TERM head;
int KeyIx;
while (enif_get_list_cell(env, allList, &head, &allList))
{
enif_get_int(env, head, &KeyIx);
locked.insert(KeyIx);
}
ErlNifPid ThePid;
enif_self(env, &ThePid);
uint64_t Val = (uint64_t)(ThePid.pid);
allList = argv[0];
//enif_fprintf(stdout, "IMY************tryLocksSchedule222 %T \n", allList);
auto search = locked.end();
while (enif_get_list_cell(env, allList, &head, &allList))
{
KeyIx = enif_hash(ERL_NIF_INTERNAL_HASH, head, HashSalt) % LockSize;
//enif_fprintf(stdout, "IMY************tryLocksSchedule222000 %d \n", KeyIx);
search = locked.find(KeyIx);
if (search != locked.end())
{
if (!lockOne(env, &ThePid, KeyIx, Val))
{
goto Failed;
}
else
{
locked.insert(KeyIx);
}
}
}
//enif_fprintf(stdout, "IMY************tryLocksSchedule333 %T \n", allList);
return atomTrue;
Failed:
{
uint64_t RExpected;
for (auto it : locked)
{
RExpected = Val;
LockSlot[it].compare_exchange_strong(RExpected, 0);
}
return atomFalse;
}
}
ERL_NIF_TERM tryLock(ErlNifEnv *env, int, const ERL_NIF_TERM argv[])
{
if (enif_is_list(env, argv[0]))
{
// enif_fprintf(stdout, "IMY************tryLocks00 %T \n", argv[0]);
ERL_NIF_TERM allList = argv[0];
ERL_NIF_TERM head;
ErlNifPid ThePid;
enif_self(env, &ThePid);
uint64_t Val = (uint64_t)(ThePid.pid);
int KeyIx;
//forward_list<int> locked(15);
//list<int> locked;
set<int> locked;
// map<int, int> locked;
unsigned int cnt = 0;
auto search = locked.end();
// enif_fprintf(stdout, "IMY************tryLocks222 %T \n", allList);
KeyNode *LockedHead = NULL;
while (enif_get_list_cell(env, allList, &head, &allList))
{
// enif_fprintf(stdout, "IMY************tryLocks222---- %T %T\n", head, allList);
KeyIx = enif_hash(ERL_NIF_INTERNAL_HASH, head, HashSalt) % LockSize;
// enif_fprintf(stdout, "IMY************tryLocks222000 %d \n", KeyIx);
search = locked.find(KeyIx);
if (search != locked.end())
//if (isNotCurLocked(&locked, KeyIx))
KeyNode OneKeyNode = {KeyIx, LockedHead};
if (isNotLocked(LockedHead, KeyIx))
{
if (!lockOne(env, &ThePid, KeyIx, Val))
if (lockOne(env, &ThePid, KeyIx, Val))
{
goto Failed;
LockedHead = &OneKeyNode;
}
else
{
// enif_fprintf(stdout, "IMY************tryLocks222111 %d \n", KeyIx);
//locked.push_front(KeyIx);
//locked.push_back(KeyIx);
locked.insert(KeyIx);
//locked.insert({KeyIx, 0});
cnt++;
// enif_fprintf(stdout, "IMY************tryLocks222222 %d \n", cnt);
if (cnt >= ScheduleCnt)
uint64_t RExpected;
KeyNode *temp = LockedHead;
while (temp != NULL)
{
goto Schedule;
RExpected = Val;
LockSlot[temp->KeyIx].compare_exchange_strong(RExpected, 0);
temp = temp->next;
}
}
}
}
// enif_fprintf(stdout, "IMY************tryLocks333 %T \n", allList);
return atomTrue;
Schedule:
{
ERL_NIF_TERM ListLocked = enif_make_list(env, 0);
//for (auto it : locked)
// {
// enif_make_list_cell(env, enif_make_int(env, it), ListLocked);
//}
ERL_NIF_TERM newargv[2] = {allList, ListLocked};
//enif_fprintf(stdout, "IMY************tryLocks4444 %T \n", newargv);
return enif_schedule_nif(env, "tryLockSchedule", 0, &tryLockSchedule, 2, newargv);
}
Failed:
{
//uint64_t RExpected;
//for (auto it : locked)
// {
//RExpected = Val;
// LockSlot[it].compare_exchange_strong(RExpected, 0);
// }
return atomFalse;
}
}
else
{
int KeyIx;
KeyIx = enif_hash(ERL_NIF_INTERNAL_HASH, argv[0], HashSalt) % LockSize;
ErlNifPid ThePid;
enif_self(env, &ThePid);
uint64_t Val = (uint64_t)(ThePid.pid);
if (lockOne(env, &ThePid, KeyIx, Val))
{
return atomTrue;
}
else
{
return atomFalse;
}
}
}
ERL_NIF_TERM releaseLockSchedule(ErlNifEnv *env, int, const ERL_NIF_TERM argv[])
{
ERL_NIF_TERM allList = argv[0];
ERL_NIF_TERM head;
ErlNifPid ThePid;
enif_self(env, &ThePid);
uint64_t Expected = (uint64_t)(ThePid.pid);
uint64_t RExpected;
int KeyIx;
int isAllOk = 1;
enif_get_int(env, argv[1], &isAllOk);
int KeyIx;
KeyIx = enif_hash(ERL_NIF_INTERNAL_HASH, argv[0], HashSalt) % LockSize;
ErlNifPid ThePid;
enif_self(env, &ThePid);
uint64_t Val = (uint64_t)(ThePid.pid);
while (enif_get_list_cell(env, allList, &head, &allList))
{
KeyIx = enif_hash(ERL_NIF_INTERNAL_HASH, head, HashSalt) % LockSize;
RExpected = Expected;
if (!LockSlot[KeyIx].compare_exchange_strong(RExpected, 0))
if (lockOne(env, &ThePid, KeyIx, Val))
{
isAllOk = 0;
return atomTrue;
}
else
{
return atomFalse;
}
}
return isAllOk > 0 ? atomTrue : atomFalse;
}
ERL_NIF_TERM releaseLock(ErlNifEnv *env, int, const ERL_NIF_TERM argv[])
{
if (enif_is_list(env, argv[0]))
{
ERL_NIF_TERM allList = argv[0];
ERL_NIF_TERM head;
ErlNifPid ThePid;
@ -242,7 +130,6 @@ ERL_NIF_TERM releaseLock(ErlNifEnv *env, int, const ERL_NIF_TERM argv[])
uint64_t Expected = (uint64_t)(ThePid.pid);
uint64_t RExpected;
int KeyIx;
unsigned int cnt = 0;
int isAllOk = 1;
while (enif_get_list_cell(env, allList, &head, &allList))
@ -253,40 +140,27 @@ ERL_NIF_TERM releaseLock(ErlNifEnv *env, int, const ERL_NIF_TERM argv[])
{
isAllOk = 0;
}
cnt++;
if (cnt >= ScheduleCnt)
{
goto Schedule;
}
}
return isAllOk > 0 ? atomTrue : atomFalse;
Schedule:
{
ERL_NIF_TERM ArgvAllOk = enif_make_int(env, isAllOk);
ERL_NIF_TERM newargv[2] = {allList, ArgvAllOk};
//enif_fprintf(stdout, "IMY************tryLocks4444 %T \n", newargv);
return enif_schedule_nif(env, "releaseLockSchedule", ERL_NIF_DIRTY_JOB_CPU_BOUND, &releaseLockSchedule, 2, newargv);
}
}
else
{
int KeyIx;
KeyIx = enif_hash(ERL_NIF_INTERNAL_HASH, argv[0], HashSalt) % LockSize;
ErlNifPid ThePid;
enif_self(env, &ThePid);
uint64_t Expected = (uint64_t)(ThePid.pid);
if (LockSlot[KeyIx].compare_exchange_strong(Expected, 0))
{
return atomTrue;
}
else
{
return atomFalse;
int KeyIx;
KeyIx = enif_hash(ERL_NIF_INTERNAL_HASH, argv[0], HashSalt) % LockSize;
ErlNifPid ThePid;
enif_self(env, &ThePid);
uint64_t Expected = (uint64_t)(ThePid.pid);
if (LockSlot[KeyIx].compare_exchange_strong(Expected, 0))
{
return atomTrue;
}
else
{
return atomFalse;
}
}
}
}
ERL_NIF_TERM getLockPid(ErlNifEnv *env, int, const ERL_NIF_TERM argv[])
{

+ 5
- 1
src/eCLock.erl 查看文件

@ -1,8 +1,12 @@
-module(eCLock).
-include("eGLock.hrl").
-define(CASE(Cond, Then, That), case Cond of true -> Then; _ -> That end).
%% :Ms
-define(LockTimeOut, 5000).
%% :Ms
-define(ReTryTime, 3).
-export([
tryLock/1
, tryLock/2

正在加载...
取消
保存