protobuf - go

Tips

optional 字段生成基本变量指针

对于 proto2 语法,如果基础字段添加了 optional 修饰,那么生成的 go 文件对应的字段是指针。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// proto 定义
syntax = "proto2";

message Foo {
optional int32 id = 1;
optional string bar = 2;
}

// go 文件
type Foo struct {
...

Id *int32 `protobuf:"varint,1,opt,name=id" json:"id,omitempty"`
Bar *string `protobuf:"bytes,2,opt,name=bar" json:"bar,omitempty"`
}

go 语法不能对常量、右值取地址,无法直接赋值给对应变量。proto 提供了对应的 wrapper 工具,传入右值,返回指针。

1
2
foo := pb.Foo{}
foo.Id = proto.Int32(23)

s3

递归删除

1
2
3
4
aws s3 rm --recursive s3://bucket/ --exclude="*" --include="/folder_path/*" 

# 递归删除 s3://bucket/offline/data/2022
aws s3 rm --recursive s3://bucket/offline/data --include="2022"

查看空间占用

1
2
3
$ aws s3 ls s3://bucket/patth --recursive --summarize --human-readable | grep Total
Total Objects: 8382
Total Size: 984.4 GiB

brew - ubuntu

安装

1
2
3
4
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

# 配置
echo 'eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"' >> /home/ubuntu/.profile

服务

consul

1
2
3
4
5
6
7
8
9
10
# 安装
brew install consul

# 配置
vim /home/linuxbrew/.linuxbrew/Cellar/consul/1.12.0/homebrew.consul.service
## 修改 ExecStart
ExecStart=/home/linuxbrew/.linuxbrew/opt/consul/bin/consul agent -dev -bind 0.0.0.0 -advertise 127.0.0.1 -client 0.0.0.0

# 手动启动
/home/linuxbrew/.linuxbrew/opt/consul/bin/consul agent -dev -bind 0.0.0.0 -advertise 127.0.0.1 -client 0.0.0.0

scala basic

[toc]

组织

文件

数据类型

类型

数字

字符串

布尔

限定

常量

变量

数据结构

数组

列表

集合

映射

语法

程序结构

注释

运算符

条件控制

循环

1
2
// 遍历次数
(0 until 10).map(...)

判断

函数

1
2
3
4
class Point(xc: Int, yc: Int) {
var x: Int = xc
var y: Int = yc
}

特性

语法糖

空指针处理

函数式编程

泛型编程

flatbuffer

定义

1
2
3
4
table Weapon {
name:string;
damage:short;
}

转换

1
2
3
4
flatbuffers::FlatBufferBuilder fbb;
...

const Weapon * weapon = GetWeapon(fbb.GetBufferPointer());

打印

1
2
3
4
5
6
7
// 打印结构
#include "flatbuffers/minireflect.h"

RequestT req;
flatbuffers::FlatBufferBuilder fbb;
fbb.Finish(Request::Pack(fbb, &req));
std::string debug_info = flatbuffers::FlatBufferToString(fbb.GetBufferPointer(), RequestTypeTable());

protobuf - c++

Descriptor & Reflection

message

1
2
3
4
5
6
7
8
9
10
syntax = "proto3";

message Sea {
string name = 1;
}

message World {
int64 age = 1;
repeated string tag = 2;
}

Descriptor & Reflection

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
World wd{};

// protobuf 3
auto age = World::GetDescriptor()->FindFieldByName("age");
// protobuf 2
auto age = wd.GetDescriptor()->FindFieldByName("age");

// 设置单值
World::GetReflection->SetInt64(&wd, age, 10);
// 设置 repeated 字段
World::GetReflection()->AddString(&wd, tag, "a");
World::GetReflection()->AddString(&wd, tag, "b");
World::GetReflection()->SetRepeatedString(&wd, tag, 1, "c");

// 设置 submessage
wd.mutable_sea()->set_name("pacific");

Json

1
2
3
4
5
6
7
8
9
10
#include <google/protobuf/util/json_util.h>

// message -> json
std::string output;
google::protobuf::util::MessageToJsonString(message, &output);

// json -> message
SomeMessage msg;
std::string input;
google::protobuf::util::MessageToJsonString(input, &msg);

cmake

广告推荐

广告商可以在广告交易平台,选择适合需求的计费模型和指标来优化广告投放。

买量方式

不同的广告系统,会根据业务的不同选择不同的买量方式(出价方式),程序化广告交易平台支持的常用买量方式有 CPI、CPC、CPM、深度转化出价、Target-CPE、Target-ROAS 等。对于视频平台广告系统可能会有 CPV 等买量方式。

  • CPI,Cost Per Install,每次安装成本
  • CPC,Cost Per Click,每次点击成本
  • CPM,Cost Per Mille,每千次展示成本
  • 双出价 / 深度转化出价
  • Target-CPE,Target Cost Per Engagement,每次参与成本,按参与收费
  • Target-ROAS,Target Return on Advertising Spend,按回报率收费
  • CPA,Cost Per Acquisition,每次获客成本
  • CPV,Cost Per View,每次观看成本,主要用于视频广告

指标

  • eCPM,期望价值,用于评估当前请求的预估价值

    • 基于 eCPM 来控制利润率
  • 填充率,FillRate,有效请求量(有广告填充) / 总请求量

  • ROI

ROI ,投资回报率(Return on Investment),利润 / 花费

  • CTR,点击率(点击 / 展示)
  • CVR,点击转化率(转化 / 点击)
  • IVR,曝光转化率(转化 / 展示)

eCPM = ivr * price * 1000

  • LTV,Lifetime Value,生命周期总价值,指一个用户在其与企业之间的整个生命周期内产生的总价值或收益

术语

  • Offer,在广告行业,广告主投的广告为 Offer,开发者接受 Offer,广告交易平台的作用是撮合开发者拿到广告主的 Offer
  • Campaign,广告活动,一个 Offer 可以拆分多个 Campaign
  • Supply,供给方,媒体
  • Demand,需求方,广告主
  • Advertiser,广告主
  • PMP,Private Marketplace,优质媒体私有化购买
  • IAA,In-App Advertising,应用内广告,通过展示广告来获得收入
  • IAP,In-App Purchases,应用内购买,帮助开发者实现收入来源
  • EGR,Engagement Rate,参与率,广告或营销活动中用户互动的比率
  • SKAN,基于苹果官方归因解决方案 SKAdNetwork 的回传数据做出的一个帮助广告主衡量 iOS 端投放效果的榜单,属于确定性归因

服务

DMP

数据管理平台(Data Management Platform,DMP),用于存储设备用户的兴趣、安装列表、以及人物画像等数据。

其他

  • PCOC,Predict Click Over Click,校准之后的点击率与后验点击率(近似真实概率)的比值

参考

logrotate

配置

示例

rotate.conf

1
2
3
4
5
6
7
8
9
/home/wii/www/logs/*.log {
daily
rotate 30
missingok
nocompress
copytruncate
notifempty
dateext
}

Rotate

触发 rotate

1
2
3
4
5
6
logrotate [options] [config-file]

logrotate -v -s /home/wii/www/logs/rotate-status rotate.conf

-v: 打印具体信息
-s: 指定 status 保存路径; 默认在 /var/lib/logrotate/ 下,可能没有权限

注意

  • logrotate 根据 status 文件判断是否需要 rotate,第一次执行可能只创建 status 文件,并不会创建 rotate 日志文件。如果想要触发,修改 status 文件记录的最后一次 rotate 时间,以触发 rotate

c++ threads

Thread

thread

1
2
3
#include <thread>

std::thread trd(function, args...);

线程私有数据

1
2
3
4
5
6
7
8
# 创建线程私有数据
int pthread_key_create(pthread_key_t *key, void (*destructor)(void*)); # 第二个函数为 destructor 函数,线程结束时调用
# 设置私有数据
int pthread_setspecific(pthread_key_t key,const void *pointer)); # 第一个参数由 pthread_key_create 产生
# 获取私有数据
void *pthread_getspecific(pthread_key_t key);
# 删除
int pthread_key_delete(pthread_key_t key);

Mutex

1
2
#include <mutex>
#include <shared_mutex>