|
@@ -27,10 +27,7 @@ import java.io.IOException;
|
|
|
import java.io.InputStream;
|
|
import java.io.InputStream;
|
|
|
import java.io.InputStreamReader;
|
|
import java.io.InputStreamReader;
|
|
|
import java.util.*;
|
|
import java.util.*;
|
|
|
-import java.util.concurrent.ConcurrentHashMap;
|
|
|
|
|
-import java.util.concurrent.CountDownLatch;
|
|
|
|
|
-import java.util.concurrent.Future;
|
|
|
|
|
-import java.util.concurrent.TimeUnit;
|
|
|
|
|
|
|
+import java.util.concurrent.*;
|
|
|
import java.util.stream.Collectors;
|
|
import java.util.stream.Collectors;
|
|
|
|
|
|
|
|
import static com.tzld.piaoquan.ad.engine.commons.math.Const.*;
|
|
import static com.tzld.piaoquan.ad.engine.commons.math.Const.*;
|
|
@@ -158,8 +155,13 @@ public class RankStrategyBy688 extends RankStrategyBasic {
|
|
|
Random random = new Random();
|
|
Random random = new Random();
|
|
|
List<Future<AdRankItem>> futures = new ArrayList<>();
|
|
List<Future<AdRankItem>> futures = new ArrayList<>();
|
|
|
CountDownLatch cdl1 = new CountDownLatch(request.getAdIdList().size());
|
|
CountDownLatch cdl1 = new CountDownLatch(request.getAdIdList().size());
|
|
|
|
|
+
|
|
|
|
|
+ // 优化:根据开关选择线程池
|
|
|
|
|
+ ExecutorService featurePool = optimizeSwitch ? ThreadPoolFactory.featureOptimized() : ThreadPoolFactory.feature();
|
|
|
|
|
+
|
|
|
for (AdPlatformCreativeDTO dto : request.getAdIdList()) {
|
|
for (AdPlatformCreativeDTO dto : request.getAdIdList()) {
|
|
|
- Future<AdRankItem> future = ThreadPoolFactory.feature().submit(() -> {
|
|
|
|
|
|
|
+ Future<AdRankItem> future = featurePool.submit(() -> {
|
|
|
|
|
+
|
|
|
AdRankItem adRankItem = new AdRankItem();
|
|
AdRankItem adRankItem = new AdRankItem();
|
|
|
try {
|
|
try {
|
|
|
adRankItem.setAdId(dto.getCreativeId());
|
|
adRankItem.setAdId(dto.getCreativeId());
|
|
@@ -173,14 +175,30 @@ public class RankStrategyBy688 extends RankStrategyBasic {
|
|
|
adRankItem.setSkuId(dto.getSkuId());
|
|
adRankItem.setSkuId(dto.getSkuId());
|
|
|
adRankItem.setCustomerId(dto.getCustomerId());
|
|
adRankItem.setCustomerId(dto.getCustomerId());
|
|
|
adRankItem.setProfession(dto.getProfession());
|
|
adRankItem.setProfession(dto.getProfession());
|
|
|
- adRankItem.setRandom(random.nextInt(1000));
|
|
|
|
|
|
|
+ adRankItem.setProfession(dto.getProfession());
|
|
|
|
|
+
|
|
|
|
|
+ // 优化:使用 ThreadLocalRandom 减少锁竞争
|
|
|
|
|
+ if (optimizeSwitch) {
|
|
|
|
|
+ adRankItem.setRandom(java.util.concurrent.ThreadLocalRandom.current().nextInt(1000));
|
|
|
|
|
+ } else {
|
|
|
|
|
+ adRankItem.setRandom(random.nextInt(1000));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
if (noApiAdVerIds.contains(dto.getAdVerId())) {
|
|
if (noApiAdVerIds.contains(dto.getAdVerId())) {
|
|
|
adRankItem.getExt().put("isApi", "0");
|
|
adRankItem.getExt().put("isApi", "0");
|
|
|
} else {
|
|
} else {
|
|
|
adRankItem.getExt().put("isApi", "1");
|
|
adRankItem.getExt().put("isApi", "1");
|
|
|
}
|
|
}
|
|
|
adRankItem.getExt().put("recallsources", dto.getRecallSources());
|
|
adRankItem.getExt().put("recallsources", dto.getRecallSources());
|
|
|
- adRankItem.getExt().put("correctCpaMap", JSONObject.toJSONString(correctCpaMap.get(dto.getAdId())));
|
|
|
|
|
|
|
+ adRankItem.getExt().put("recallsources", dto.getRecallSources());
|
|
|
|
|
+
|
|
|
|
|
+ // 优化:直接存对象,避免循环内 JSON 序列化
|
|
|
|
|
+ if (optimizeSwitch) {
|
|
|
|
|
+ adRankItem.getExt().put("correctCpaMap", correctCpaMap.get(dto.getAdId()));
|
|
|
|
|
+ } else {
|
|
|
|
|
+ adRankItem.getExt().put("correctCpaMap", JSONObject.toJSONString(correctCpaMap.get(dto.getAdId())));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
adRankItem.getExt().put("correctionFactor", correctCpaMap.get(dto.getAdId()).getCorrectionFactor());
|
|
adRankItem.getExt().put("correctionFactor", correctCpaMap.get(dto.getAdId()).getCorrectionFactor());
|
|
|
setGuaranteeWeight(map, dto.getAdVerId(), adRankItem.getExt(), isGuaranteedFlow, reqFeature);
|
|
setGuaranteeWeight(map, dto.getAdVerId(), adRankItem.getExt(), isGuaranteedFlow, reqFeature);
|
|
|
String cidStr = dto.getCreativeId().toString();
|
|
String cidStr = dto.getCreativeId().toString();
|
|
@@ -267,7 +285,7 @@ public class RankStrategyBy688 extends RankStrategyBasic {
|
|
|
userFeatureMap = this.featureBucket(userFeatureMap);
|
|
userFeatureMap = this.featureBucket(userFeatureMap);
|
|
|
CountDownLatch cdl4 = new CountDownLatch(adRankItems.size());
|
|
CountDownLatch cdl4 = new CountDownLatch(adRankItems.size());
|
|
|
for (AdRankItem adRankItem : adRankItems) {
|
|
for (AdRankItem adRankItem : adRankItems) {
|
|
|
- ThreadPoolFactory.feature().submit(() -> {
|
|
|
|
|
|
|
+ featurePool.submit(() -> {
|
|
|
try {
|
|
try {
|
|
|
Map<String, String> featureMap = adRankItem.getFeatureMap();
|
|
Map<String, String> featureMap = adRankItem.getFeatureMap();
|
|
|
adRankItem.setFeatureMap(this.featureBucket(featureMap));
|
|
adRankItem.setFeatureMap(this.featureBucket(featureMap));
|
|
@@ -689,7 +707,12 @@ public class RankStrategyBy688 extends RankStrategyBasic {
|
|
|
if (scoreParam.getExpCodeSet().contains(word2vecExp)) {
|
|
if (scoreParam.getExpCodeSet().contains(word2vecExp)) {
|
|
|
score = SimilarityUtils.word2VecSimilarity(cTitle, vTitle);
|
|
score = SimilarityUtils.word2VecSimilarity(cTitle, vTitle);
|
|
|
} else {
|
|
} else {
|
|
|
- score = Similarity.conceptSimilarity(cTitle, vTitle);
|
|
|
|
|
|
|
+ // 优化:使用 Caffeine 缓存相似度计算结果
|
|
|
|
|
+ if (optimizeSwitch) {
|
|
|
|
|
+ score = ExtractorUtils.cachedConceptSimilarity(cTitle, vTitle);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ score = Similarity.conceptSimilarity(cTitle, vTitle);
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
featureMap.put("ctitle_vtitle_similarity", String.valueOf(score));
|
|
featureMap.put("ctitle_vtitle_similarity", String.valueOf(score));
|
|
|
}
|
|
}
|
|
@@ -718,8 +741,22 @@ public class RankStrategyBy688 extends RankStrategyBasic {
|
|
|
if (scoreParam.getExpCodeSet().contains(word2vecExp)) {
|
|
if (scoreParam.getExpCodeSet().contains(word2vecExp)) {
|
|
|
doubles = ExtractorUtils.funcC34567ForTagsNew(tags, title);
|
|
doubles = ExtractorUtils.funcC34567ForTagsNew(tags, title);
|
|
|
} else {
|
|
} else {
|
|
|
|
|
+ // 优化:使用带缓存的 Word2Vec 相似度 (如果需要可进一步优化 word2vec)
|
|
|
|
|
+ // 这里暂时只优化 conceptSimilarity
|
|
|
doubles = ExtractorUtils.funcC34567ForTags(tags, title);
|
|
doubles = ExtractorUtils.funcC34567ForTags(tags, title);
|
|
|
|
|
+ if (optimizeSwitch) {
|
|
|
|
|
+ // 如果 funcC34567ForTags 内部也用了 conceptSimilarity,需要透传开关或使用 cached 版本
|
|
|
|
|
+ // 由于 funcC34567ForTags 是静态方法,我们在方法内部判断?
|
|
|
|
|
+ // 实际上 ExtractorUtils.funcC34567ForTags 内部调用了 Similarity.conceptSimilarity
|
|
|
|
|
+ // 我们应该修改 ExtractorUtils 或者在这里替换实现
|
|
|
|
|
+ // 简单起见,我们复制 funcC34567ForTags 的逻辑到这里并使用 cachedConceptSimilarity
|
|
|
|
|
+ // 或者修改 ExtractorUtils.funcC34567ForTags 让他支持缓存?
|
|
|
|
|
+ // 最好的办法是修改 ExtractorUtils.funcC34567ForTags
|
|
|
|
|
+ // 但为了稳妥,我们调用新的 cached 方法
|
|
|
|
|
+ doubles = funcC34567ForTagsCached(tags, title);
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
featureMap.put(prefix + "_" + tagsField + "_matchnum", String.valueOf(doubles[0]));
|
|
featureMap.put(prefix + "_" + tagsField + "_matchnum", String.valueOf(doubles[0]));
|
|
|
featureMap.put(prefix + "_" + tagsField + "_maxscore", String.valueOf(doubles[1]));
|
|
featureMap.put(prefix + "_" + tagsField + "_maxscore", String.valueOf(doubles[1]));
|
|
|
featureMap.put(prefix + "_" + tagsField + "_avgscore", String.valueOf(doubles[2]));
|
|
featureMap.put(prefix + "_" + tagsField + "_avgscore", String.valueOf(doubles[2]));
|
|
@@ -908,4 +945,27 @@ public class RankStrategyBy688 extends RankStrategyBasic {
|
|
|
}
|
|
}
|
|
|
return newFeatureMap;
|
|
return newFeatureMap;
|
|
|
}
|
|
}
|
|
|
|
|
+ private Double[] funcC34567ForTagsCached(String tags, String title) {
|
|
|
|
|
+ String[] tagsList = tags.split(",");
|
|
|
|
|
+ int d1 = 0;
|
|
|
|
|
+ double d3 = 0.0;
|
|
|
|
|
+ double d4 = 0.0;
|
|
|
|
|
+
|
|
|
|
|
+ for (String tag : tagsList) {
|
|
|
|
|
+ if (title.contains(tag)) {
|
|
|
|
|
+ d1++;
|
|
|
|
|
+ }
|
|
|
|
|
+ // 使用缓存的相似度计算
|
|
|
|
|
+ double score = ExtractorUtils.cachedConceptSimilarity(tag, title);
|
|
|
|
|
+ if (score > d3) {
|
|
|
|
|
+ d3 = score;
|
|
|
|
|
+ }
|
|
|
|
|
+ d4 += score;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ d4 = (tagsList.length > 0) ? d4 / tagsList.length : d4;
|
|
|
|
|
+
|
|
|
|
|
+ return new Double[]{(double) d1, d3, d4};
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
}
|
|
}
|