c语言结构体数组指针怎么用指针移动法_指针数组初始化

(58) 2024-08-19 13:01:01

ci框架 数组 指针移动

A few years ago, when Gojek was scaling internationally, at the forefront of the expansion was our consumer app used by millions of people across Southeast Asia. Needless to say, our engineering team was growing too, and we rapidly increased from 40 to 140+ Android and iOS engineers — all working on the #SuperApp.

几年前,当Gojek进行国际扩张时,在扩展的最前沿是我们的消费类应用程序被东南亚数百万人使用。 不用说,我们的工程团队也在增长,我们的Android和iOS工程师从40人Swift增加到140多人,所有这些人都在#SuperApp上工作。

Every line of code committed has to go through unit tests, code quality checks, regression tests and other routines to maintain high quality code… You know the drill.

提交的每一行代码都必须经过单元测试,代码质量检查,回归测试和其他例程,以维护高质量的代码……您知道该练习。

一点背景,对于那些没有经验的人 (A little bit of background, for the uninitiated)

The moment a commit is pushed to the remote branch, a pipeline is triggered in the CI. The pipeline staunchly does the job of running a wide array of quality checks and runs for ~45-50 minutes (test: ~10min, build ~20 min, static analysis ~15min). Some engineers are very meticulous and commit granularly. With nearly 10-20 commits and an average of 300 minutes of pipelines run every day, per developer.

将提交推送到远程分支后,CI中就会触发管道。 管道会严格执行运行大量质量检查的工作,并运行约45-50分钟(测试:约10分钟,构建约20分钟,静态分析约15分钟)。 一些工程师非常细致,细致入微。 每个开发人员每天要进行近10-20次提交,平均每天要运行300分钟的管道。

We had 140+ engineers.An average of ~1100 pipelines per day.Amounting to ~550 hours of pipeline duration each day.

我们有140多名工程师,平均每天约有1100条管道,每天约有550小时的管道持续时间。

This is the story of how the Developer Experience (devX) team has been tackling this huge load. 🖖

这就是开发者体验(devX)团队如何应对如此巨大的负载的故事。 🖖

为什么CI对我们很重要? (Why is CI important to us?)

  • Engineers code confidently knowing what they write wouldn’t break other parts of the system

    工程师自信地编写代码,知道他们编写的内容不会破坏系统的其他部分

  • Development teams confidently ship faster

    开发团队可以放心地更快地发货

  • Provides early feedback to engineers

    向工程师提供早期反馈

  • Ensures better collaboration between engineers and Quality Analysts

    确保工程师和质量分析师之间更好的协作

  • Product managers get builds(Nightly, Alpha, Beta) to see their features

    产品经理获取构建(Nightly,Alpha,Beta版)以查看其功能

  • Designers can smoothly run periodic compliance checks of the design standards

    设计师可以顺利进行设计标准的定期合规性检查

  • For early feedback on features, the CI system is expected to distribute builds as easily as possible

    为了对功能进行早期反馈,预计CI系统将尽可能轻松地分发内部版本

挑战 (The challenges)

The CI pipeline impacts across the org wide and deep, and with hundreds of engineers working towards a common goal, the challenges we face on the mobile infra are unique.

CI管道影响着整个组织,影响深远,数百名工程师朝着一个共同的目标努力,我们在移动基础设施方面面临的挑战是独一无二的。

  • Availability of runners

    跑步者人数

  • Duration of pipelines

    管道的持续时间

  • Feedback cycles

    反馈周期

Before we delve into how we go about tackling challenges, what’s a runner, you ask? 🤔

在我们深入研究如何应对挑战之前,您问什么? 🤔

Gitlab Runner is an open source project used to run jobs and send the results back to GitLab. It is used in conjunction with GitLab CI/CD, the open-source continuous integration service included with GitLab which coordinates the jobs.

Gitlab Runner是一个开源项目,用于运行作业并将结果发送回GitLab。 它与GitLab CI / CD结合使用,GitLab CI / CD是GitLab随附的用于协调作业的开源持续集成服务。

Let’s understand what runner availability means, to know the gravity of the situation. Imagine a software engineer commits a block of code to a remote repository and this change needs to be run through a pipeline to do a few validations. The pipeline needs a machine to run on and there are runners we have kept ready.

让我们了解跑步者的可用性意味着什么,以了解情况的严重性。 想象一下,软件工程师将代码块提交到远程存储库,并且此更改需要通过管道运行以进行一些验证。 管道需要一台机器来运行,我们已经准备好了流道。

Ideally, the idea is to have a few runners and run the pipeline on one of them. But what if there are several developers pushing code during peak work hours? Probably 20 of them simultaneously or in quick succession. We’ve had days with more than 250 commits to the master branch and we don’t have an infinite number of runner machines available with us. This means some of the developers have to wait for a while until their code change can be run through pipelines.

理想情况下,该想法是让几个跑步者并在其中一个跑步者上运行。 但是,如果有几个开发人员在繁忙的工作时间内推送代码怎么办? 大约有20个同时或快速连续出现。 我们过去几天已经对master分支进行了250次以上的提交,而我们没有无限数量的运行器机器可用。 这意味着一些开发人员必须等待一段时间,直到他们的代码更改可以通过管道运行。

Waiting is not cool. The challenge at hand is to not let developers wait for a long time. The faster developers get feedback on their code change, the better.

等待不是很酷。 当前的挑战是不要让开发人员等待很长时间。 开发人员获得有关其代码更改的反馈越快越好。

应对这些挑战 (Tackling these challenges)

⚙️技术 (⚙️ The tech)

  • Gitlab yml[For configuration]

    Gitlab yml [用于配置]

  • Kubernetes [ For infrastructure and orchestration ]

    Kubernetes [用于基础架构和编排]

  • Docker Images [For a reproducible build environment]

    Docker镜像[用于可复制的构建环境]

  • Elastic search + Kibana [ For analysis and visualization ]

    弹性搜索+ Kibana [用于分析和可视化]

  • Ruby [ Scripting for CI ]

    Ruby [CI脚本]

  • MinIO for gradle cache

    MinIO用于Gradle缓存

  • Slack bots [ For proactive feedback to developers ]

    Slack机器人[向开发人员提供主动反馈]

  • Helm [For deployments on kubernetes]

    头盔 [用于kubernetes上的部署]

c语言结构体数组指针怎么用指针移动法_指针数组初始化 (https://mushiming.com/)  第1张

techniques技术 (🛠 The techniques)

  • Measure

    测量

  • Segregate

    分离

  • Parallelise

    平行度

管道隔离 (Segregation of pipelines)

  • Categorising pipelines

    管道分类

  • Categorising jobs based on functionality

    根据功能对作业进行分类

  • Categorising jobs based on infra needed

    根据需要对工作进行分类

Categorising pipelines

管道分类

For running 550 hours of pipelines every day, we could have provisioned ~22 machines with 20–30 GB RAM and 8 cores each. But, this unoptimised approach means

为了每天运行550小时的管道,我们可以配置约22台具有20–30 GB RAM和8个内核的机器。 但是,这种未优化的方法意味着

  • High cost

    成本高

  • Low availability (Only 22 jobs can be run at any point of time and the rest would have to wait)

    可用性低(在任何时间点只能运行22个作业,其余的必须等待)

  • Under-utilisation of resources (A job with 20 GB RAM and a job with just 500mb of RAM would run on machines with 30 GB RAM, which is not optimal)

    资源利用不足(具有20 GB RAM的作业和仅有500mb RAM的作业将在具有30 GB RAM的计算机上运行,​​这不是最佳选择)

Examples of pipeline categories

管道类别示例

c语言结构体数组指针怎么用指针移动法_指针数组初始化 (https://mushiming.com/)  第2张

Table depicting different types of pipelines and different jobs run on those pipelines
该表描述了不同类型的管道以及在这些管道上运行的不同作业

These examples indicate that different pipelines/jobs have different functional and infrastructure requirements. Categorising pipelines allows better infrastructure planning.

这些示例表明,不同的管道/作业具有不同的功能和基础架构要求。 对管道进行分类可以更好地进行基础架构规划。

Here’s how we plan for such differences:

这是我们如何计划这种差异的方法:

  • Each pipeline is divided into different stages

    每个管道分为不同的阶段

  • Each stage is divided into small jobs

    每个阶段分为小工作

That being said, the smallest unit of a CI Pipeline is a ‘job’ and it needs an environment to run. It is as this point that the infrastructure needs to be planned. There are a few variables that can help us to determine the infrastructure needs of a job.

话虽如此,CI管道的最小单元是一个“工作”,它需要一个运行环境。 正是在这一点上,需要对基础架构进行规划。 有一些变量可以帮助我们确定工作的基础架构需求。

Variables of a job

工作变量

  • Runtime Environment

    运行环境

  • Memory requirements

    内存需求

Example 1:

范例1:

A job that executes a Ruby script would require

执行Ruby脚本的作业需要

  • A ruby docker container to be loaded

    一个要加载的Ruby Docker容器

  • A gigabyte of RAM, and probably 1 core of CPU

    1 GB的RAM,可能是1个CPU核

  • Hence we would need a machine with a GB of RAM and one core CPU

    因此,我们需要一台具有GB RAM和一个核心CPU的计算机

Example 2:

范例2:

A job that needs to sync code from repository and build an APK would need

需要同步存储库中的代码并构建APK的工作将需要

  • A linux docker container with Android SDK, Gradle, and Git installed

    安装了Android SDK,Gradle和Git的Linux docker容器

  • At least 16 GB of RAM for building a decent sized Android App + memory for docker and Gradle daemon

    至少16 GB的RAM用于为docker和Gradle守护程序构建像样的Android应用+内存

  • At the least 2–4 cores of CPU to speed up builds

    至少2–4个CPU内核可加快构建速度

我们如何隔离? (How do we segregate?)

c语言结构体数组指针怎么用指针移动法_指针数组初始化 (https://mushiming.com/)  第3张

Different machine configurations on the CI system
CI系统上的不同机器配置
  • Low config machines [ 2 GB RAM, 2 Core CPU]

    配置较低的计算机[2 GB RAM,2个核心CPU]

→ For jobs that do not involve GIT

→对于不涉及GIT的工作

→ For jobs that do not involve Gradle

→对于不涉及Gradle的工作

→ For jobs that involve only running small scripts (Typically for data collection and executing curl commands)

→对于仅运行小脚本的作业(通常用于数据收集和执行curl命令)

  • Mid config machines [ 8+ GB RAM, 2+ cores ]

    中型配置机[8+ GB RAM,2 +内核]

→ For publishing artefacts

→用于出版文物

→ For jobs involving GIT

→对于涉及GIT的工作

  • High config machines [ 25+ GB RAM, 4+ Cores ]

    高配置计算机[25+ GB RAM,4 +内核]

→ For compiling and building code

→用于编译和构建代码

→ For jobs involving Gradle daemons

→对于涉及Gradle守护程序的作业

→ For jobs involving GIT

→对于涉及GIT的工作

Each job in the CI falls into one of the following categories.

CI中的每个作业都属于以下类别之一。

Hence, each job that we define in .gitlab-ci.yml would have a tag for indicating the jobs infra category.

因此,我们在.gitlab-ci.yml中定义的每个作业都将具有一个标记,用于指示以下作业类别。

For example, a Gitlab template for jobs executing only a ruby script may look like this

例如,仅执行ruby脚本的作业的Gitlab模板可能如下所示

.ruby_job_template: &ruby_job_template
<<: *job_template
image: ruby:2.7.0
tags:
- low-config

测量 (Measure)

Faster feedback is directly proportional to developer experience.

更快的反馈与开发人员的经验成正比。

Variables contributing to this are:

造成这种情况的变量有:

  • Waiting time: The moment a developer submits a Merge Request, if the pipelines start immediately, the developer is happy. If the developer keeps seeing “Waiting for pipeline to start”, that’s a bad thing especially if this is for more than a few minutes.

    等待时间 :开发人员提交合并请求的那一刻,如果管道立即启动,则开发人员很高兴。 如果开发人员一直看到“等待管道启动”,那是一件坏事,尤其是如果这持续了几分钟。

  • Completion time: A pipeline taking hours to complete is obviously irritating.

    完成时间:一条要花费数小时才能完成的管道很烦人。

Now that we have the infra provisioned and the entire CI up and running, there are a myriad of things that can go wrong because we are dealing with a lot of different variables and the code is continuously changing.

既然我们已经配置了基础设施,并且整个CI都已启动并运行,那么由于我们要处理许多不同的变量并且代码在不断变化,因此可能会出现很多错误。

In order to proactively adapt the CI with the changing code characteristics, we need to be one step ahead. That’s where we need to monitor, measure and react.

为了使CI适应不断变化的代码特性,我们需要领先一步。 那是我们需要监视,衡量做出React的地方。

Our measuring and monitoring framework of choice was ELK.

我们选择的测量和监视框架是ELK。

我们要衡量什么? (What do we measure?)

There are 2 category of things we measure

我们测量的东西有2类

基础架构和管道统计(以帮助Devops团队) (Infrastructure and pipeline statistics (to help the Devops team))

  • Time taken by each job to run

    每个作业花费的时间

  • Time taken by each pipeline to complete

    每个管道完成所需的时间

  • Frequency of pipeline failure

    管道故障频率

  • Availability of infrastructure at any moment

    随时可用的基础架构

  • Average waiting time for each job

    每个工作的平均等待时间

  • Build time of apps over time

    随着时间的推移构建应用程序的时间

  • Execution times of different Gradle tasks over time

    随时间推移不同Gradle任务的执行时间

  • Development environment settings of dev machines

    开发机器的开发环境设置

代码统计(以帮助开发人员) (Code statistics (to help the developers))

  • Code smells over time

    代码随着时间的流逝而闻

  • Code coverage per module over time

    随时间推移每个模块的代码覆盖率

  • Apk size over time

    APK大小随时间变化

  • Number of warnings on lint over time

    随时间推移的皮棉警告数量

These extensive measurements allow us to take action proactively.

这些广泛的衡量标准使我们能够主动采取行动。

我们如何衡量? (How do we measure?)

We need to keep the measuring simple and not overload the infrastructure due to measurement. Hence, all the metrics that we collect over the pipeline are transmitted through a Curl Http to an Elastic data store.

我们需要使测量保持简单,并且不要由于测量而使基础架构过载。 因此,我们通过管道收集的所有指标都通过Curl Http传输到Elastic数据存储。

Here are a few visualisations that the team often uses:

以下是团队经常使用的一些可视化效果:

c语言结构体数组指针怎么用指针移动法_指针数组初始化 (https://mushiming.com/)  第4张

Pipeline duration over time
管道持续时间
c语言结构体数组指针怎么用指针移动法_指针数组初始化 (https://mushiming.com/)  第5张

Gauges representing availability of runners at present
代表目前跑步人数的量规
c语言结构体数组指针怎么用指针移动法_指针数组初始化 (https://mushiming.com/)  第6张

Execution time of build tasks over time. As it shoots up we get to work
随着时间的推移,构建任务的执行时间。 随着时间的推移,我们开始工作

平行度 (Parallelise)

If jobs are independent of each other, running them parallely can directly contribute to reduction in pipeline times. The Gitlab runner configuration file allows us to define how many jobs can be run in parallel in each runner.

如果作业彼此独立,则并行运行它们可以直接减少流水线时间。 Gitlab运行器配置文件允许我们定义每个运行器中可以并行运行多少个作业 。

Also, leveraging auto scale capabilities of Kubernetes to provision nodes will handle the peak loads coming during days preceding releases.

此外,利用Kubernetes的自动扩展功能来配置节点将可以处理发布前几天的峰值负载。

完成反馈循环 (Completing the feedback loop)

Developers need to be made aware of the status of merge requests. Events like pipeline start, pipeline completion, pipeline success, pipeline failures are conveyed to MR authors via slack bots that are integrated into the CI system.

需要使开发人员知道合并请求的状态。 诸如流水线启动,流水线完成,流水线成功,流水线故障之类的事件通过集成到CI系统中的松散僵尸程序传达给MR作者。

c语言结构体数组指针怎么用指针移动法_指针数组初始化 (https://mushiming.com/)  第7张

Slack DM to a developer on the status of pipelines
向开发人员介绍DM的管道状态

优化管道的持续时间 (Optimising the duration of pipelines)

Better Caching in CI is crucial for improving pipeline times. However, this topic is big enough and deserves a separate blog altogether. 🤷‍♂️

CI中更好的缓存对于缩短流水线时间至关重要。 但是,这个主题足够大,应该单独放置一个博客。 ♂‍♂️

Some ways of optimising the duration of pipelines are:

优化管道持续时间的一些方法是:

  • Failing fast

    快速失败

  • Fine-tuning Gradle properties for faster builds

    微调Gradle属性以加快构建速度

  • Reducing the amount of network requests done from the CI

    减少从配置项完成的网络请求数量

  • Lean installation (Install only ruby/android sdk binaries and not docs)

    精益安装(仅安装ruby / android sdk二进制文件,而不安装docs)

我们在忙什么呢? (What are we up to?)

We have come a long way on building a reliable CI system. The next phase would be to package the CI system as a plug-and-play software and probably make it open source. We have miles to go and we are continuously improving, learning, and evolving.

我们在构建可靠的CI系统方面已经走了很长一段路。 下一阶段将是将CI系统打包为即插即用软件,并可能使其开源。 我们还有很长的路要走,我们正在不断改进,学习和发展。

How are you solving CI at scale? Do share with us your learnings, we’d be glad to hear about them.

您如何大规模解决CI? 一定要与我们分享您的经验,我们很高兴听到他们的经验。

使这一切成为可能的团队 (The team that makes all this possible)

Satyarth is the Architect for the devX (Developer Experience) team. He loves meddling with Gradle and calls himself a Gradle activist.

Satyarth是devX(开发人员体验)团队的架构师。 他喜欢干预Gradle,并自称为Gradle活动家。

Prashanth is the iOS Engineering Manager and sets the entire infrastructure for running iOS app pipelines.

Prashanth是iOS工程经理,负责设置运行iOS应用程序管道的整个基础架构。

Shailesh is a script master and designs workflows to get the maximum output in minimum time. He sees the build pipeline as an assembly line.

Shailesh是脚本大师,他设计工作流以在最短的时间内获得最大的输出。 他将构建管道视为组装线。

Prathyush is a Software Development Engineer in the devX team. Kubernetes and infra excite him.

Prathyush是devX团队的一名软件开发工程师。 Kubernetes和Infra激发了他。

Sanju works on the tooling and infrastructure for the iOS app. He is always interested in automating dev workflows.

Sanju致力于iOS应用程序的工具和基础架构。 他一直对自动化开发工作流程很感兴趣。

Asif works on the build tools for iOS that includes optimising for XCode and the project structure.

Asif致力于iOS的构建工具,其中包括针对XCode和项目结构进行优化。

Avadhut works on the tooling around iOS to enhance developer productivity.

Avadhut使用围绕iOS的工具来提高开发人员的生产力。

Dinesh is the Engineering Manager for devX (Tooling, Infra and Build System).

Dinesh是devX(工具,基础架构和构建系统)的工程经理。

Stay tuned for more on the Devops series. CI for iOS, optimising Gradle caching for faster builds are in the writing room!

请继续关注Devops系列的更多信息。 用于iOS的CI,正在编写室中优化Gradle缓存以加快构建速度!

c语言结构体数组指针怎么用指针移动法_指针数组初始化 (https://mushiming.com/)  第8张

Click here for more stories on how we at Gojek solve tech challenges and have a lot of fun while at it.

单击此处 ,了解有关我们Gojek如何解决技术挑战并在此过程中获得很多乐趣的更多故事。

翻译自: https://blog.gojekengineering.com/running-ci-for-mobile-engineers-at-scale-de951b556cf4

ci框架 数组 指针移动

THE END

发表回复