首页 文章 精选 留言 我的

精选列表

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

Windows Networking 5: .Net Framework 应用程序响应慢排查一则

与Java一样,.Net Framework也是基于IL解析执行的,通过Microsoft提供的 !sos debug extension,我们基本上可以把.Net Framework的应用程序看个通透。本文通过一个用户的.Net Framework应用网络问题,抛砖引玉。 问题 有用户反馈他们Windows上的应用程序访问MySQL慢,但是行为很奇怪。架构是这样的, Client --------Internet---> Windows IIS server (.Net Framework application) ------Internet-----> MySQL server 用户反馈, 客户端访问IIS server慢。 IIS server通过自己的公网IP访问相同的页面也比较慢 (VPC机器,EIP)。 用户怀疑是Wi

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

“互联网+”英特尔,快速响应让零售更贴心

第十届商业信息化行业大会今天在深圳拉开帷幕。英特尔携手国内领先的POS和智能POS产品生产商、板卡厂家以及方案提供商等众多生态系统合作伙伴,联合展示了多款智能零售创新产品和解决方案,全面阐释了智能零售和智能收银收单新定义,以及支付终端在其中所扮演的重要作用。 从以连锁店为代表的传统实体零售,到以电商为代表的在线零售,再到当前虚实结合的智能零售模式,全球零售业正在经历一场史无前例的剧烈变革。2017年,资源整合的步伐正在不断加快,线上与线下的融合越发紧密。直到2020年,零售物联网市场的规模将达到356.4亿美元[1],零售商越来越多的通过物联网解决方案来提高运营效率,并在线上和线下创造令人兴奋的全新用户体验。而作为技术的前沿的支付,受到愈演愈烈的智能零售风潮以及新兴市场的催化,也在经历一场全新的转型:从单一应用、单一功能和体验,升级至集成多种应用和功能、支持多屏触控和多种操作系统,有效联动智能商店的其他设备,从而实现更多基于数据分析和其他相关的增值应用。 为了解决零售业面临的挑战,英特尔正在为零售业开发全面的端到端产品组合,整合了先进计算、客户体验、资源部署、通信与深度学习所必需的广泛技术,这些技术拥有跨实体店、云基础设施和数据中心的无与伦比的可扩展性和安全性。英特尔拥有得天独厚的优势来实现智能互联世界的各个环节--支持全球绝大多数数据中心、连接数亿个物联网设备并履行对时刻在线、5G连接、深度机器学习以及安全和隐私的承诺。 “英特尔广泛的与解决方案提供商合作,致力于推动零售业的持续增长。”英特尔公司物联网事业部零售解决方案部门零售平台市场总监Alec Gefrides表示:“随着越来越多的商家将资金投入到支付终端及店面智能设备的升级换代中,英特尔致力于提供强大的计算能力和独一无二的端到端的技术支持。” 随着物联网下的智能消费体验日渐深入人心,从线上的精准营销到线下的购物体验,全渠道营销真正实现了跨界发展,从根本上推动了整个零售行业的变革。英特尔凭借着自身优异的CPU和GPU性能,通过软硬集成的服务逐年不断优化为零售行业量身订制的参考设计,从前端到后端提供完善的智能零售解决方案和技术,配合大数据分析对于消费者的深入洞察,真正瞄准了目标群体,提升了用户黏性,大幅增加了销售利润,最终助推实体店回归商业本质,线上线下两条腿走路实现了实体店的全新逆袭。 本文出处:畅享网 本文来自云栖社区合作伙伴畅享网,了解相关信息可以关注vsharing.com网站。

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

10 亿条数据秒级响应

坦白讲,每次看性能测试排行榜,我都会下意识地先找找 Apache Doris 在哪个位置。 这次打开 JSONBench 的榜单,心情一如既往的期待加紧张。 好在结果让我松了一口气:默认配置下就能排到第三,仅次于维护方 ClickHouse 的两个版本。 不过,Doris 只能止步于此了吗?经过一系列优化后,查询时长能不能再缩短点?和 ClickHouse 的差距在哪里? 调优前后对比图镇楼,至于调优的具体思路,请一起往下看吧。 Apache Doris 排名 (Default) Apache Doris 排名 (Unofficial Tuned) JSONBench 简介 JSONBench 是一个为 JSON 数据而生的数据分析 Benchmark,简单来说,它由 10 亿条来自真实生产环境的 JSON 数据、5 个针对 JSON 构造的特定 SQL 查询组成,旨在对比各个数据库系统对半结构化数据的处理能力。目前榜单包括 ClickHouse、MongoDB、Elasticsearch、DuckDB、PostgreSQL 等知名数据库系统,截至目前,Doris 的性能表现是 Elasticsearch 的 2 倍,是 PostgreSQL 的 80 倍。 JSONBench 官网地址:jsonbench.com 不仅在性能上 Apache Doris 领先其他同类产品,在数据集相同的情况下,Apache Doris 的存储占用是 Elasticsearch 的 1/2、PostgreSQL 的 1/3。 JSONBench 测试具体流程:首先在数据库中创建一张名为 Bluesky 的表,并导入十亿条真实的用户行为日志数据。测试过程中,每个查询重复执行三次,并且在每次查询前清空操作系统的 Page Cache,以模拟冷热查询的不同场景。最终,通过综合计算各查询的执行耗时得出数据库的性能排名。 在这个测试中,Apache Doris 使用了 Variant 数据类型来存储 JSON 数据,默认的建表 Schema 如下: CREATE TABLE bluesky ( `id` BIGINT NOT NULL AUTO_INCREMENT, `data` variant NOT NULL ) DISTRIBUTED BY HASH(id) BUCKETS 32 PROPERTIES ("replication_num"="1"); Variant 是 Apache Doris 2.1 中引入一种新的数据类型 ,它可以存储半结构化 JSON 数据,并且允许存储包含不同数据类型(如整数、字符串、布尔值等)的复杂数据结构,而无需在表结构中提前定义具体的列。Variant 类型特别适用于处理复杂的嵌套结构,而这些结构可能随时会发生变化。在写入过程中,该类型可以自动根据列的结构、类型推断列信息,动态合并写入的 schema,并通过将 JSON 键及其对应的值存储为列和动态子列。 Apache Doris Variant 类型详情 调优思路与原理 JSONBench 榜单排名依据各个数据库系统在默认配置下的性能数据,那么能否通过调优,让 Apache Doris 进一步释放性能潜力,实现更好的性能效果呢? 01 环境说明 测试机器:AWS M6i.8xlarge(32C128G); 操作系统:Ubuntu24.04; Apache Doris: 3.0.5; 02 Schema 结构化处理 由于 JSONBench 特定查询中涉及到的 JSON 数据都是固定的提取路径,换言之,半结构化数据的 Schema 是固定的,因此,我们可以借助生成列,将常用的字段提取出来,实现半结构化数据和结构化数据结合的效果。类似的高频访问的 JSON 路径或者需要计算的表达式,都可以使用该优化思路,添加对应的生成列来实现查询加速。 查看 JSONBench 查询 Apache Doris 生成列详情 CREATE TABLE bluesky ( kind VARCHAR(100) GENERATED ALWAYS AS (get_json_string(data, '$.kind')) NOT NULL, operation VARCHAR(100) GENERATED ALWAYS AS (get_json_string(data, '$.commit.operation')) NULL, collection VARCHAR(100) GENERATED ALWAYS AS (get_json_string(data, '$.commit.collection')) NULL, did VARCHAR(100) GENERATED ALWAYS AS (get_json_string(data,'$.did')) NOT NULL, time DATETIME GENERATED ALWAYS AS (from_microsecond(get_json_bigint(data, '$.time_us'))) NOT NULL, `data` variant NOT NULL ) DUPLICATE KEY (kind, operation, collection) DISTRIBUTED BY HASH(collection, did) BUCKETS 32 PROPERTIES ("replication_num"="1"); 除了可以减少查询时提取数据的开销,还可以用展平出来的列作为分区列,使得数据分布更均衡。 需要注意的是,查询的 SQL 语句也要改为使用展平列的版本: // JSONBench 原始查询: SELECT cast(data['commit']['collection'] AS TEXT ) AS event, COUNT(*) AS count FROM bluesky GROUP BY event ORDER BY count DESC; SELECT cast(data['commit']['collection'] AS TEXT ) AS event, COUNT(*) AS count, COUNT(DISTINCT cast(data['did'] AS TEXT )) AS users FROM bluesky WHERE cast(data['kind'] AS TEXT ) = 'commit' AND cast(data['commit']['operation'] AS TEXT ) = 'create' GROUP BY event ORDER BY count DESC; SELECT cast(data['commit']['collection'] AS TEXT ) AS event, HOUR(from_microsecond(CAST(data['time_us'] AS BIGINT))) AS hour_of_day, COUNT(*) AS count FROM bluesky WHERE cast(data['kind'] AS TEXT ) = 'commit' AND cast(data['commit']['operation'] AS TEXT ) = 'create' AND cast(data['commit']['collection'] AS TEXT ) IN ('app.bsky.feed.post', 'app.bsky.feed.repost', 'app.bsky.feed.like') GROUP BY event, hour_of_day ORDER BY hour_of_day, event; SELECT cast(data['did'] AS TEXT ) AS user_id, MIN(from_microsecond(CAST(data['time_us'] AS BIGINT))) AS first_post_ts FROM bluesky WHERE cast(data['kind'] AS TEXT ) = 'commit' AND cast(data['commit']['operation'] AS TEXT ) = 'create' AND cast(data['commit']['collection'] AS TEXT ) = 'app.bsky.feed.post' GROUP BY user_id ORDER BY first_post_ts ASC LIMIT 3; SELECT cast(data['did'] AS TEXT ) AS user_id, MILLISECONDS_DIFF(MAX(from_microsecond(CAST(data['time_us'] AS BIGINT))),MIN(from_microsecond(CAST(data['time_us'] AS BIGINT)))) AS activity_span FROM bluesky WHERE cast(data['kind'] AS TEXT ) = 'commit' AND cast(data['commit']['operation'] AS TEXT ) = 'create' AND cast(data['commit']['collection'] AS TEXT ) = 'app.bsky.feed.post' GROUP BY user_id ORDER BY activity_span DESC LIMIT 3; // 使用展平列改写的查询: SELECT collection AS event, COUNT(*) AS count FROM bluesky GROUP BY event ORDER BY count DESC; SELECT collection AS event, COUNT(*) AS count, COUNT(DISTINCT did) AS users FROM bluesky WHERE kind = 'commit' AND operation = 'create' GROUP BY event ORDER BY count DESC; SELECT collection AS event, HOUR(time) AS hour_of_day, COUNT(*) AS count FROM bluesky WHERE kind = 'commit' AND operation = 'create' AND collection IN ('app.bsky.feed.post', 'app.bsky.feed.repost', 'app.bsky.feed.like') GROUP BY event, hour_of_day ORDER BY hour_of_day, event; SELECT did AS user_id, MIN(time) AS first_post_ts FROM bluesky WHERE kind = 'commit' AND operation = 'create' AND collection = 'app.bsky.feed.post' GROUP BY user_id ORDER BY first_post_ts ASC LIMIT 3; SELECT did AS user_id, MILLISECONDS_DIFF(MAX(time),MIN(time)) AS activity_span FROM bluesky WHERE kind = 'commit' AND operation = 'create' AND collection = 'app.bsky.feed.post' GROUP BY user_id ORDER BY activity_span DESC LIMIT 3; 03 Page Cache 调整 调整查询语句后,开启 profile,执行完整的查询测试: set enable_profile=true; 进入 FE 8030 端口的 Web 页面,找到相关 profile 进行分析,此时发现 SCAN Operator 中的 Page Cache 命中率较低,导致热读测试过程中存在一部分冷读操作。 - CachedPagesNum: 1.258K (1258) - TotalPagesNum: 7.422K (7422) 这种情况通常是由于 Page Cache 容量不足,无法完整缓存 Bluesky 表中的数据。建议在 be.conf 中添加配置项 storage_page_cache_limit=60%,将 Page Cache 的大小从默认的内存总量的 20% 提升至 60%。重新运行测试后,可以观察到冷读问题已得到解决。 - CachedPagesNum: 7.316K (7316) - TotalPagesNum: 7.316K (7316) 04 最大化并行度 为了进一步挖掘 Doris 的性能潜力,可以将 Session 变量中的parallel_pipeline_task_num设为 32,因为本次 Benchmark 测试机器m6i.8xlarge为 32 核,所以我们将并行度设置为 32 以最大程度发挥 CPU 的计算能力。 // 单个 Fragment 的并行度 set global parallel_pipeline_task_num=32; 调优结果 经过上述对 Schema、Query、内存限制、CPU 等参数的调整,我们对比了调优前后 Doris 的性能表现以及一些其他数据库系统的成绩,有如下结果: 可以看到,对比调优前的 Doris,调优后 Doris 查询整体耗时降低了 74%,对比原榜单第一的 ClickHouse 产品实现了 39% 的领先优势。 总结与展望 通过对 Schema 的结构化处理、查询语句的优化、缓存配置的调整以及并行参数的设置,Apache Doris 整体查询耗时显著下降,并超越 ClickHouse。 在默认设置下,Doris 在 10 亿条 JSON 的查询耗时与 ClickHouse 仍有数秒的差异。然而,依托于 Doris 在 JSON 处理、Variant 类型支持及生成列等能力的加持,经调优后,其半结构化数据处理性能获得了进一步显著提升,并在同类数据库中表现出明显的领先优势。 未来,Apache Doris 将继续打磨在半结构化领域的数据处理能力,为用户带来更加优质、高效的分析体验,包括: 优化 Variant 类型稀疏列的存储空间,支持万列以上的子列; 优化万列大宽表的内存占用; 支持 Variant 子列根据列名的 Pattern 自定义类型、索引等。 推荐阅读 Apache Doris 针对半结构化数据分析的解决方案及典型场景 揭秘 Variant 数据类型:灵活应对半结构化数据,JSON 查询提速超 8 倍,存储空间节省 65% 欢迎扫码并备注 “半结构化” 加入 Apache Doris 社区专项交流群,免费领取 100+ 企业实践案例集和 Doris x AI 更多资料、获取技术帮助、了解最新动态,并与更多开发者和用户互动。

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

Redis淘汰+过期双向保证高可用,单线程如何做到快速响应

2 --> 前言 redis和数据相比除了他们的结构性颠覆以外!还有他们存储位置也是不相同。传统数据库将数据存储在硬盘上每次数据操作都需要IO而Redis是将数据存储在内存上的。这里稍微解释下IO是啥意思。IO就是输入流输出流方式将数据在硬盘和内存之间进行交互!而redis直接在内存上就剩下了IO操作。这也是redis快的原因之一吧 内存相对于硬盘来说很宝贵。我们平时的电脑也是硬盘是内存的几百倍。既然内存很宝贵而redis又将数据存储在内存上那么redis肯定不能肆无忌惮的进行存储 。这就需要redis和开发者们作出相应的优化 首先redis在配置文件(redis.conf)中通过maxmemory参数指定redis 设置整个对内存的支配大小! 其次就是要求我们开发者在想redis中填值的时候根据自己的需求设置相应的key过期时间。这样不必要的数据就会被redis过期驱逐策略清除。从而节省内存供别人使用 内存分配 maxmemory 指定大小。在redis.conf配置文件中可以直接指定。他的单位时byte。 上图中注释部分是给大家的解释,实际中#配置需要换行哈!!!友情提示 另外我们可以连接上redis通过config命令来设置 两种方式都可以设置,前者是全局设置重启之后仍然有效!后者是临时设置重启之后就会重新加载redis.conf中的配置。 键过期 上面我们从redis本身角度出发设置了内存限制,这样不用担心他们吞噬系统内存!下面就需要我们开发者设计角度约束自己了。 设置过期时间 expire key time 设置过期时间默认单位时S 。 然后通过ttl 命令可以查看剩余过期时间 经过多次执行ttl能够观察到剩余时间在不断的减少!当减少到0的时候就被给驱逐策略驱逐!注意这里说的是驱逐策略驱逐并不是意味着立马被删除 更新过期时间 del key 直接将key删除了那么该key对应的过期自然也就不存在了!这种情况笔者也算作是更新过期时间 set getset等命令重新设置key、value方式会覆盖过期时间 , 直接被覆盖成-1 set 、 getset包括del严格意义是覆盖过期时间。真正做到更新过期时间的还是expire .在expire是以最新为准的! 上面其实都修改了key才会引发原本的过期时间失效的!因为此key非彼key 。 但是append、incr 等命令是改变值这种命令是不会影响到原来的过期设置的 淘汰策略 根据上面配置我们可以将我们的redis最大内存设置为1MB , 设置大小随便最好能小点。然后我们通过Java小程序不断向redis中填充。最终当内存不够使用时就会报错 报错就是因为内存满了,新增的key被redis拒绝了!不仅仅是新增的被拒绝,就算此时我们想改变已经在redis中的key的值也是不可用的 public static void main(String[] args) { Jedis jedis = new Jedis("39.102.60.114", 6379); jedis.auth("Qq025025"); Integer index = 1; while (true) { String uuid = UUID.randomUUID().toString(); jedis.set(index.toString(), uuid); System.out.println(index++); } } 不管是append 还是set 全都是报OOM command not allowed when used memory > maxmemory 。代码中打印和redis键个数一致;说明我们默认的淘汰策略是直接拒绝 总结下来就是:当redis内存被使用满了后,任何的写操作都会被拒绝! 当没有足够内存时难道就这么直接拒绝吗?上面也提到了需要我们程序员自己根据需求设置键过期已释放内存供其他有需要的key使用!那么设置了过期key之后这些key又是怎么被清除的呢? 这就牵扯出我们的淘汰策略 volatile-lru【最近很少使用】 当内存告警时redis会将近期很少使用且设置了过期时间的key剔除出去,即使该key还没有到过期时间。如果没有符合的key也就是执行之后内存仍然不足时将会和默认淘汰策略noeviction抛出一样的错误OOM command not allowed when used memory > maxmemory 首先我们在redis.conf中配置我们最近很少使用策略. maxmemory-policy volatile-lru 。 然后重启我们的redis服务 。重启之后flushall清空所有数据,我们在通过上面的Java程序重新生成下数据! Java程序中我们设置前100个key添加过期时间 public static void main(String[] args) { Jedis jedis = new Jedis("39.102.60.114", 6379); jedis.auth("Qq025025"); Integer index = 1; while (true) { String uuid = UUID.randomUUID().toString(); if (index < 100) { jedis.setex(index.toString(),360, uuid); } else { jedis.set(index.toString(), uuid); } System.out.println(index++); } } 简单分析下为什么程序计数器大于redis库中的key数量!就是因为我们为前100设置了过期时间。当内存不足时redis就会将当前设置了过期时间的key中最近最少使用的key进行剔除!所以我们计数器会大于键数量。因为有部分键被清除了!我们获取前100的key都是null , 说明被删除了! 那么为什么本次计数器不是比上次多100 。 那是因为我们每次存储进来的是uuid, 所占长度都不是固定的。还有本身淘汰策略也是占用内存的 策略总结 上面演示了最近最少使用的淘汰策略!除此之外还有其他的策略 noeviction:拒绝写请求,正常提供读请求,这样可以保证已有数据不会丢失(默认策略); 2. volatile-lru:尝试淘汰设置了过期时间的key,虽少使用的key被淘汰,没有设置过期时间的key不会淘汰; 3. volatile-ttl:跟volatile-lru几乎一样,但是他是使用的key的ttl值进行比较,最先淘汰ttl最小的key; 4. volatile-random:其他同上,唯一就是他通过很随意的方式随机选择淘汰key集合中的key; 5. allkeys-lru:区别于volatile-lru的地方就是淘汰目标是全部key,没设置过期时间的key也不能幸免; 6. allkeys-random:这种方式同上,随机的淘汰所有的key。 使用哪种淘汰策略需要我们结合自己的项目场景来配合使用!!! 过期删除 上面我们从【键过期】、【淘汰策略】两个角度分析了redis 。 仅仅这两方面还没有完全高效使用内存!淘汰策略是濒临内存不足时触发。那么当设置了过期时间的键真正到了过期时间而此时内存尚够使用?这种场景是不是需要将过期键删除呢? 因为redis是单线程,那么在键过期的时候如何不影响对外服务的同时清除过期键呢?答案是【不行】。严格意义是无法解决的因为单线程同时只能做一件事!既然无法解决那么我们可以达到一种协调状态!如果同一时刻出现一个过期键那么清除键很快这时候阻塞外部服务的时间很短可能毫秒级设置纳秒级! 但是如何同一时间发生上万键过期,如果想要删除上万键那肯定需要花费一定时间这时候就会阻塞对外服务!这肯定是不能接受的,阻塞时间过长会导致客户端连接超时报错的。这在并发场景下更是无法接受的!所以redis如何应对同一时间过多数据过期的场景,他的删除过期键的方法略有不同! 定时清除 针对每个过期键设置一个定时器,在过期时就会进行清理该键! 该做法能够做到数据实时被清理从而保证内存不会被长期占用!提高了内存的使用率! 但是问题也随之而来,每一个key需要设置一个定时器进行跟踪。redis这里笔者猜测应该是启用另外线程来进行定时跟踪!这里有清除的还请帮忙解答下? 当同一时间过期key很多的时候!我们的CPU就需要不断的执行这些定时器从而导致CPU资源紧张。最终会影响到redis服务的性能 定期清除 定期删除就是上面我们图示效果,redis会每隔100ms执行一次定时器,定时器的任务就是随机抽取20个设置过期的key 。 判断是否进行清除。上面图示中说明中写错了不是10S , 而是每隔100ms 。请原谅我的粗心!!! 定期删除和定时删除作用是相反的!定期删除是将key集中进行处理同时为了保证服务的高可用在处理时加入的时间限制。每次执行总时长不能超过25ms 。 也就是说对于客户端来说服务端的延迟不会超过25ms 。 他的优点就是不需要CPU频繁的进行操作key清除!因为他是定期进行清除所以就会导致一部分数据没有来得及清除从而导致内存使用上会被一直占用! 惰性清除 关于惰性删除我们在平时开发中也经常使用这种方式!当数据过期时redis并不急着去清除这些数据,而是等到该key被再次请求时进行删除!这样在最终效果上是没有问题的。 优点和定期清除一样他保证了CPU不必频繁的进行切换!但是缺点也很明显会导致很多已经过期的key仍然在redis中。 惰性清除+定期清除 我们开头说过了既要高可用又要实时清理过期key 这是无法做到的!既然无法做到我们就需要在CPU和内存中间做一个权衡!redis内部是使用惰性清除和定期清除两种方式结合使用,最终保证CPU和内存之间的一种平衡! 总结 相信大家对上面三个概念有点模糊了。【键过期】、【淘汰策略】、【过期清除】 首先【键过期】是redis给我们开发者提供的功能。我们可以根据自己的业务需求合理的设置键的过期时间,从而保证内存的高可用 其次【过期清除】在我们之前设置的过期的key如何进行合理的清除,并不能一股脑一下子进行清除因为数据过大会导致服务的卡顿。这个时候我们需要通过定期清除减缓清除key代码的卡顿。在redis.conf中我们可以设置 hz 10 代表1S中平均执行几次这也是我们上面所说的100MS的由来。但是仅仅定期删除会产生遗漏数据所以我们还需要加上惰性清除,最终保证对客户端来说数据是准确实时清除的。 那么关于【淘汰策略】又是啥呢?在上面过期清除是如果用户一直不请求过期的key ,并且随着业务产生越来越多的过期key . 这时候redis服务中还会堆积很多过期的无效key 。这个时候如果内存不够用了的话那又该怎么办呢?这时候我们需要设置淘汰策略比如果volatile-lru . 就会将最近最少使用的设置过期key进行清除从而保证尽可能地接收更多的有效数据! 这就是为什么会设计三者的原因!好好理解上面三个主题我们再去想想为什么会发生【缓存雪崩】、【缓存崩溃】、【缓存击穿】就好理解一点了呢?

资源下载

更多资源
优质分享App

优质分享App

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

Oracle

Oracle

Oracle Database,又名Oracle RDBMS,或简称Oracle。是甲骨文公司的一款关系数据库管理系统。它是在数据库领域一直处于领先地位的产品。可以说Oracle数据库系统是目前世界上流行的关系数据库管理系统,系统可移植性好、使用方便、功能强,适用于各类大、中、小、微机环境。它是一种高效率、可靠性好的、适应高吞吐量的数据库方案。

Eclipse

Eclipse

Eclipse 是一个开放源代码的、基于Java的可扩展开发平台。就其本身而言,它只是一个框架和一组服务,用于通过插件组件构建开发环境。幸运的是,Eclipse 附带了一个标准的插件集,包括Java开发工具(Java Development Kit,JDK)。

Sublime Text

Sublime Text

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