首页 文章 精选 留言 我的

精选列表

搜索[优化],共10000篇文章
优秀的个人博客,低调大师

node上的redis调用优化示例

Node.js读写数据到influxDB,目前已经有一个库node-influx, 这个库功能非常强大,但是我个人使用这个库的时候,遇到无法解决的问题。 使用curl都可以写数据到influxDB,但是用node-influx总是报错,搞了半天也无法解决,就索性不用它了。 influxDB提供HTTP的API,也就是说Node.js中的axios或[request等HTTP客户端工具是可以直接和influx交互的。 需要注意的一点是,写到influxDB的数据格式必须是二进制流。 1. 字符串转二进制 const data = Buffer.from('mymeas,mytag=1 myfield=90') 2. 设置请求Content-Type为二进制 'Content-Type': 'application/octet-stream' 完整代码展示: \`const axios = require(\`\`'axios'``)` \`const data = Buffer.from(\`\`'mylog,name=wdd error\_count=2003,no\_send=0'``)` \`axios({\` \`url:\` `'\[http://localhost:8923/write?db=poc&rp=poc\](http://localhost:8923/write?db=poc&rp=poc)'``,` \`method:\` `'post'``,` \`headers: {\` `'Content-Type'``:` `'application/octet-stream'` `},` \`data: data\` `})` `.then((res) => {` \`console.log(\`\`'ok'``)` `// console.log(res)` `})`//欢迎加入全栈开发交流圈一起学习交流:864305860 `.\`\`catch\`\`((err) => {`//帮助突破技术瓶颈,提升思维能力 \`console.log(\`\`'err'``)` `})` 使用axios或者requst这种底层库的好处是,你用curl做的成功的任何操作,都可以转换成axios或request的请求,而不依赖与其他库。

优秀的个人博客,低调大师

Android代码优化之Handler内存泄漏

目录 目录 前言 Android代码中涉及进程间通信的地方经常会使用Handler。 public class MainActivity extends AppCompatActivity { //可能引入内存泄漏的方法 private Handler handler=new Handler(){ @Override public void handleMessage(Message msg) { super.handleMessage(msg); } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } } 而上面这种用法可能会导致内存泄漏,比如使用如下代码,由于消息会在5分钟后发送,所以当用户进入并退出Activity后,在消息发送并处理完成之前,这个Activity是不会被回收的,这样就会导致内存泄漏。 public class MainActivity extends AppCompatActivity { //可能引入内存泄漏的方法 private Handler handler=new Handler(){ @Override public void handleMessage(Message msg) { super.handleMessage(msg); } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //5分钟后发送消息 handler.postDelayed(new Runnable() { @Override public void run() { Log.e("测试","123"); } },1000*10*5); } } 内存泄漏的原因 由于Handler、Looper和MessageQueue是一起工作的,在Android中一个应用启动后系统会默认创建一个用于处理主线程所有Message对象的Looper对象,它的生命周期贯穿于整个应用的生命周期,所以在主线程使用Handler的时候都会默认绑定这个Looper对象并关联MessageQueue,这时发送到MessageQueue的Message对象都会持有这个Handler对象的引用,这样Looper在处理消息的时候才能回调到Handler中年的handleMessage方法。因此如果Message对象还没有处理完成,那么Handler对象也就不会被垃圾回收。而在Java中非静态内部类会持有外部类的一个隐式引用,所以当Handler无法回收时由于Handler持有MainActivity的引用导致MainActivity也无法被回收,从而导致内存泄漏。 解决方法:将Handler改为静态内部类并使用弱引用 public class MainActivity extends AppCompatActivity { private final InnerHandler mInnerHandler=new InnerHandler(this); private final Runnable sRunnable=new Runnable() { @Override public void run() { Toast.makeText(MainActivity.this, "解决方法", Toast.LENGTH_SHORT).show(); } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mInnerHandler.postDelayed(sRunnable,1000*60*5); } private static class InnerHandler extends Handler{ private final WeakReference<MainActivity> activityWeakReference; public InnerHandler(MainActivity activity) { this.activityWeakReference = new WeakReference<MainActivity>(activity); } @Override public void handleMessage(Message msg) { super.handleMessage(msg); MainActivity activity=activityWeakReference.get(); if(activity!=null){ } } } } 个人技术博客:https://myml666.github.io/ 我的博客即将入驻“云栖社区”,诚邀技术同仁一同入驻。

优秀的个人博客,低调大师

Spark性能优化:基于分区进行操作

版权声明:本文由董可伦首发于https://dongkelun.com,非商业转载请注明作者及原创出处。商业转载请联系作者本人。 https://blog.csdn.net/dkl12/article/details/82496977 我的原创地址:https://dongkelun.com/2018/09/02/sparkMapPartitions/ 前言(摘自Spark快速大数据分析) 基于分区对数据进行操作可以让我们避免为每个数据元素进行重复的配置工作。诸如打开数据库连接或创建随机数生成器等操作,都是我们应当尽量避免为每个元素都配置一次的工作。Spark 提供基于分区的map 和foreach,让你的部分代码只对RDD 的每个分区运行一次,这样可以帮助降低这些操作的代价。 当基于分区操作RDD 时,Spark 会为函数提供该分区中的元素的迭代器。返回值方面,也返回一个迭代器。除mapPartitions() 外,Spark 还有一些别的基于分区的操作符,见下表: 函数名 调用所提供的 返回的 对于RDD[T]的函数签名 mapPartitions() 该分区中元素的迭代器 返回的元素的迭代器 f: (Iterator[T]) → Iterator[U] mapPartitionsWithIndex() 分区序号,以及每个分区中的元素的迭代器 返回的元素的迭代器 f: (Int, Iterator[T]) → Iterator[U] foreachPartitions() 元素迭代器 无 f: (Iterator[T]) → Unit 首先给出上面三个算子的具体代码示例。 1、mapPartitions 与map类似,不同点是map是对RDD的里的每一个元素进行操作,而mapPartitions是对每一个分区的数据(迭代器)进行操作,具体可以看上面的表格。 下面同时用map和mapPartitions实现WordCount,看一下mapPartitions的用法以及与map的区别 package com.dkl.leanring.spark.test import org.apache.spark.sql.SparkSession object WordCount { def main(args: Array[String]): Unit = { val spark = SparkSession.builder().master("local").appName("WordCount").getOrCreate() val sc = spark.sparkContext val input = sc.parallelize(Seq("Spark Hive Kafka", "Hadoop Kafka Hive Hbase", "Java Scala Spark")) val words = input.flatMap(line => line.split(" ")) val counts = words.map(word => (word, 1)).reduceByKey { (x, y) => x + y } println(counts.collect().mkString(",")) val counts1 = words.mapPartitions(it => it.map(word => (word, 1))).reduceByKey { (x, y) => x + y } println(counts1.collect().mkString(",")) spark.stop() } } 2、mapPartitionsWithIndex 和mapPartitions一样,只是多了一个分区的序号,下面的代码实现了将Rdd的元素数字n变为(分区序号,n*n) val rdd = sc.parallelize(1 to 10, 5) val res = rdd.mapPartitionsWithIndex((index, it) => { it.map(n => (index, n * n)) }) println(res.collect().mkString(" ")) 3、foreachPartitions foreachPartitions和foreach类似,不同点也是foreachPartitions基于分区进行操作的 rdd.foreachPartition(it => it.foreach(println)) 4、关于如何避免重复配置 下面以打开数据库连接举例,需求是这样的: 读取mysql表里的数据,做了一系列数据处理得到结果之后,需要修改我们mysql表里的每一条数据的状态,代表程序已经处理过了,下次不需要处理了。 4.1 表 以最简单表结构示例 字段名 注释 ID 主键、唯一标识 ISDEAL 程序是否处理过 建表语句 CREATE TABLE test ( id INTEGER NOT NULL AUTO_INCREMENT, isdeal INTEGER DEFAULT 0 NOT NULL, primary key(id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci; 4.2 不基于分区操作 一共用两种方法 4.2.1 第一种 package com.dkl.leanring.spark.sql.mysql import org.apache.spark.sql.SparkSession object UpdateMysqlDemo { def main(args: Array[String]): Unit = { val spark = SparkSession.builder().appName("UpdateMysqlDemo").master("local").getOrCreate() val database_url = "jdbc:mysql://192.168.44.128:3306/test?useUnicode=true&characterEncoding=utf-8&useSSL=false" val user = "root" val password = "Root-123456" val df = spark.read .format("jdbc") .option("url", database_url) .option("dbtable", "(select * from test where isDeal=0 limit 5)a") .option("user", user) .option("password", password) .option("driver", "com.mysql.jdbc.Driver") .option("numPartitions", "5") .option("partitionColumn", "ID") .option("lowerBound", "1") .option("upperBound", "10") .load() import java.sql.{ Connection, DriverManager, ResultSet }; df.rdd.foreach(row => { val conn = DriverManager.getConnection(database_url, user, password) try { // Configure to be Read Only val statement = conn.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY) val prep = conn.prepareStatement(s"update test set isDeal=1 where id=?") val id = row.getAs[Int]("id") prep.setInt(1, id) prep.executeUpdate } catch { case e: Exception => e.printStackTrace } finally { conn.close() } }) spark.stop() } } 上面的代码,取isDeal=0的前五条,因为造的数据量少,所以只取了前五条,然后指定了五个分区,这里只是一个代码示例,实际工作中应该数据量很大,每个分区肯定不止一条数据 根据上面的代码,看到用这种方式的缺点是每一个元素都要创建一个数据库连接,这样频繁创建连接、关闭连接,在数据量很大的情况下,势必会对性能产生影响,但是优点是不用担心内存不够。 4.2.2 第二种 val conn = DriverManager.getConnection(database_url, user, password) try { val statement = conn.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY) val prep = conn.prepareStatement(s"update test set isDeal=1 where id=?") df.select("id").collect().foreach(row => { val id = row.getAs[Int]("id") prep.setInt(1, id) prep.executeUpdate }) } catch { case e: Exception => e.printStackTrace } 这种方式的缺点是把要操作的数据全部转成scala数组,仅在Driver端执行,但是如果数据量很大的话,可能因为Driver内存不够大而抛出异常,优点是只建立一次数据库连接,在数据量不是特别大,且确定Driver的内存足够的时候,可以采取这种方式。 4.3 基于分区的方式 df.rdd.foreachPartition(it => { val conn = DriverManager.getConnection(database_url, user, password) try { val statement = conn.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY) val prep = conn.prepareStatement(s"update test set isDeal=1 where id=?") it.foreach(row => { val id = row.getAs[Int]("id") prep.setInt(1, id) prep.executeUpdate }) } catch { case e: Exception => e.printStackTrace } finally { conn.close() } }) 这种方式就结合了上面两种方式的优点,基于分区的方式使得创建连接的次数不会那么多,然后每个分区的数据也可以平均分到每个节点的executor上,避免了内存不足产生的异常,当然前提是要合理的分配分区数,既不能让分区数太多,也不能让每个分区的数据太多,还有要注意数据倾斜的问题,因为当数据倾斜造成某个分区数据量太大同样造成OOM(内存溢出)。 4.4 其他 上面只是列举了一个例子,且只是在foreach这样的action算子里体现的,当然肯定也有需求需是在transformation里进行如数据库的连接这样的操作,大家可类比的使用mapPartitions即可 5、其他优点(未证实) 网上有很多博客提到mapPartitions还有其他优点,就是mapPartitions比map快,性能高,原因是因为map的function会执行rdd.count次,而mapPartitions的function则执行rdd.numPartitions次。 但我并这么认为,因mapPartitions的function和map的function是不一样的,mapPartitions里的迭代器的每个元素还是都要执行一遍的,实际上也是执行rdd.count次。 下面以其中一篇博客举例(只列出优点,大部分博客上的写的都一样的,应该出自同一篇博客吧~) 博客地址:Spark—算子调优之MapPartitions提升Map类操作性能 至于mapPartitions是否真的比map处理速度快,如果我有时间验证得到结果的话,我再更新一下这个地方~ 相关阅读 Spark Sql 连接mysql Spark 创建RDD、DataFrame各种情况的默认分区数

优秀的个人博客,低调大师

POI框架EXCEL解析性能优化

背景 在做商品EXCEL的时候,线上发现了Full GC,排查得知是商家搞了一个巨大的excel,单商品发布接口平均耗时400ms(调用sell耗时200ms左右,系统自身处理商品同步耗时150ms左右),对于3000个商品的发布,耗时在20min左右,这20min内该excel的内存一直未能释放。 第一时间想到的是POI真坑,真吃内存。 事情发生了就想着怎么处理, 止血 线上机器分批重启, 马上加一个excel行数的限制然后发布 线上半个小时左右就没有任何问题了。 思考 为什么poi这么吃内存,poi这么老了,肯定有人踩过这个坑,撸起袖子,搜poi full gc. 很多文档将的都太粗糙了,本质没有说透 原因 excel本质上是xml文件的集合体。从office 2007起开始使用xml来存档和数据交换:https://zh.wikipedia

优秀的个人博客,低调大师

简单优化前端工程几种方式(上篇)

使用CDN 如果A网站和B网站, 同时使用了 https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js的资源, 在访问其他网站A时, 浏览器会缓存jquery.min.js资源文件, 访问网站B时,就可以免于下载jquery.min.js的文件, 这样既节省了服务器流量, 又提升了资源加载的速度, 一举两得~ 减少网络请求 使用雪碧图(用Photoshop将多个icon拼接到一张图上) 将多个js文件合并压缩为单个js文件(使用Webpack,或在线工具) 减少图片尺寸 可以使用PP鸭一键压缩, 具体介绍: PP鸭为你的图片瘦瘦瘦身 (支持快速压缩jpg, png, gif三种格式) 将图片保存为渐进式jpg 将图片保存为渐进式jpg后, 图片在浏览器显示时, 可以由模糊到清晰渐进式加载, 提升用户体验 将javascript脚本放到html的底部 HTML文件是从上往下渲染的, 如果js脚本有大量耗时操作, js执行期间, 用户是不能看到页面的 mdn的解释链接: https://developer.mozilla.org/zh-CN/docs/Learn/Getting_started_with_the_web/JavaScript_basics 一般我们会把css样式文件放在html的头部, javascript脚本文件放在页面底部, 但什么事情都有特例, 比如bootstrap的部分组件依赖jquery,也就是jquery必须在bootstrap之前引入, 如果我们要在页面头部引入bootstrp样式的话, 那jquery也必须放到了页面的头部!

优秀的个人博客,低调大师

二分法优化

1,基本的二分思想: int BinarySearch(int a[],int size,int key) { int L = 0; //查找区间的左端点 int R = size - 1; //查找区间的右端点 while( L <= R) { //如果查找区间不为空就继续查找 int mid = L+(R-L)/2; //取查找区间正中元素的下标 if( key == a[mid] ) return mid; else if( key > a[mid]) L = mid + 1; //设置新的查找区间的左端点 else R = mid - 1; //设置新的查找区间的右端点 } return -1; } 其实:L+(R-L)/2=(R+L)/2 为了防止(L+R)溢出,才这样写(出于ACM的需要) 2,将L R的初始化边界扩展1 int internalFor(int a[], int l, int r, int key) {//二分法查找a[] l到r区间的某个值 int L = l - 1; int R = r + 1; int mid; while (R - L > 1) {//不能设置等于 mid = L + (R - L) / 2; if (a[mid] > key) { R = mid; } if (a[mid] < key) { L = mid; } if (a[mid] == key) { return mid; } } return -1; } 3,二分算法用于不等式范围查找: int bs_nomorethan(int a[], int l, int r, int key) {//寻找小于等于key的元素的个数 int L = l - 1; int R = r + 1; int mid; while (R - L > 1) { mid = L + (R - L) / 2; if (a[mid] <= key) { L = mid; } if (a[mid] > key) { R = mid; } } return L; } 4,基于二分法思想的左右线性移动查找: void ArrayTwoNumberAdd(int a[], int size,int sum) {//使用两边移动桶的方式,进行对数组的两个数之和进行判断 int L = 0; int R = size - 1; int num = 0; while (L <= R) { if (a[L] + a[R] > sum) { R--; } if (a[L] + a[R] < sum) { L++; } if (a[L] + a[R] == sum) { cout << a[L] << "+" << a[R] << "=" << sum << endl; L++; R--; num++; } } cout << "总共有个:" << num << "对" << endl; }

资源下载

更多资源
优质分享App

优质分享App

近一个月的开发和优化,本站点的第一个app全新上线。该app采用极致压缩,本体才4.36MB。系统里面做了大量数据访问、缓存优化。方便用户在手机上查看文章。后续会推出HarmonyOS的适配版本。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

用户登录
用户注册